Commit 121d0ccd authored by jjian zhou's avatar jjian zhou Committed by Greg Kroah-Hartman

mmc: mediatek: fix SDIO IRQ interrupt handle flow

commit 8a5df8ac upstream.

SDIO IRQ is triggered by low level. It need disable SDIO IRQ
detected function. Otherwise the interrupt register can't be cleared.
It will process the interrupt more.
Signed-off-by: default avatarJjian Zhou <jjian.zhou@mediatek.com>
Signed-off-by: default avatarChaotian Jing <chaotian.jing@mediatek.com>
Signed-off-by: default avatarYong Mao <yong.mao@mediatek.com>
Fixes: 5215b2e9 ("mmc: mediatek: Add MMC_CAP_SDIO_IRQ support")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 95220219
......@@ -1355,24 +1355,25 @@ static void msdc_request_timeout(struct work_struct *work)
}
}
static void __msdc_enable_sdio_irq(struct mmc_host *mmc, int enb)
static void __msdc_enable_sdio_irq(struct msdc_host *host, int enb)
{
unsigned long flags;
struct msdc_host *host = mmc_priv(mmc);
spin_lock_irqsave(&host->lock, flags);
if (enb)
if (enb) {
sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ);
else
sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
} else {
sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ);
spin_unlock_irqrestore(&host->lock, flags);
sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
}
}
static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb)
{
unsigned long flags;
struct msdc_host *host = mmc_priv(mmc);
__msdc_enable_sdio_irq(mmc, enb);
spin_lock_irqsave(&host->lock, flags);
__msdc_enable_sdio_irq(host, enb);
spin_unlock_irqrestore(&host->lock, flags);
if (enb)
pm_runtime_get_noresume(host->dev);
......@@ -1394,6 +1395,8 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
spin_lock_irqsave(&host->lock, flags);
events = readl(host->base + MSDC_INT);
event_mask = readl(host->base + MSDC_INTEN);
if ((events & event_mask) & MSDC_INT_SDIOIRQ)
__msdc_enable_sdio_irq(host, 0);
/* clear interrupts */
writel(events & event_mask, host->base + MSDC_INT);
......@@ -1402,10 +1405,8 @@ static irqreturn_t msdc_irq(int irq, void *dev_id)
data = host->data;
spin_unlock_irqrestore(&host->lock, flags);
if ((events & event_mask) & MSDC_INT_SDIOIRQ) {
__msdc_enable_sdio_irq(host->mmc, 0);
if ((events & event_mask) & MSDC_INT_SDIOIRQ)
sdio_signal_irq(host->mmc);
}
if (!(events & (event_mask & ~MSDC_INT_SDIOIRQ)))
break;
......@@ -1528,9 +1529,6 @@ static void msdc_init_hw(struct msdc_host *host)
sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
/* Config SDIO device detect interrupt function */
if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
else
sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
/* Configure to default data timeout */
......@@ -2052,7 +2050,12 @@ static void msdc_hw_reset(struct mmc_host *mmc)
static void msdc_ack_sdio_irq(struct mmc_host *mmc)
{
__msdc_enable_sdio_irq(mmc, 1);
unsigned long flags;
struct msdc_host *host = mmc_priv(mmc);
spin_lock_irqsave(&host->lock, flags);
__msdc_enable_sdio_irq(host, 1);
spin_unlock_irqrestore(&host->lock, flags);
}
static const struct mmc_host_ops mt_msdc_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment