Commit 7729c7a2 authored by Simon Horman's avatar Simon Horman Committed by Chris Ball

mmc: tmio: Provide separate interrupt handlers

Provide separate interrupt handlers which may be used by platforms where
SDHI has three interrupt sources.

This patch also removes the commented-out handling of CRC and other errors.

Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: default avatarMagnus Damm <magnus.damm@gmail.com>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 54680fe7
...@@ -97,6 +97,9 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host); ...@@ -97,6 +97,9 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host);
void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i); void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i); void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
irqreturn_t tmio_mmc_irq(int irq, void *devid); irqreturn_t tmio_mmc_irq(int irq, void *devid);
irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid);
irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid);
irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid);
static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
unsigned long *flags) unsigned long *flags)
......
...@@ -545,44 +545,20 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, ...@@ -545,44 +545,20 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
spin_unlock(&host->lock); spin_unlock(&host->lock);
} }
irqreturn_t tmio_mmc_irq(int irq, void *devid) static void tmio_mmc_card_irq_status(struct tmio_mmc_host *host,
int *ireg, int *status)
{ {
struct tmio_mmc_host *host = devid; *status = sd_ctrl_read32(host, CTL_STATUS);
struct mmc_host *mmc = host->mmc; *ireg = *status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask;
struct tmio_mmc_data *pdata = host->pdata;
unsigned int ireg, status;
unsigned int sdio_ireg, sdio_status;
pr_debug("MMC IRQ begin\n");
status = sd_ctrl_read32(host, CTL_STATUS);
ireg = status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask;
sdio_ireg = 0;
if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) {
sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL &
~host->sdio_irq_mask;
sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL); pr_debug_status(*status);
pr_debug_status(*ireg);
if (sdio_ireg && !host->sdio_irq_enabled) { }
pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
sdio_status, host->sdio_irq_mask, sdio_ireg);
tmio_mmc_enable_sdio_irq(mmc, 0);
goto out;
}
if (mmc->caps & MMC_CAP_SDIO_IRQ &&
sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
mmc_signal_sdio_irq(mmc);
if (sdio_ireg)
goto out;
}
pr_debug_status(status); static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host,
pr_debug_status(ireg); int ireg, int status)
{
struct mmc_host *mmc = host->mmc;
/* Card insert / remove attempts */ /* Card insert / remove attempts */
if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
...@@ -592,43 +568,102 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) ...@@ -592,43 +568,102 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) && ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) &&
!work_pending(&mmc->detect.work)) !work_pending(&mmc->detect.work))
mmc_detect_change(host->mmc, msecs_to_jiffies(100)); mmc_detect_change(host->mmc, msecs_to_jiffies(100));
goto out; return true;
} }
/* CRC and other errors */ return false;
/* if (ireg & TMIO_STAT_ERR_IRQ) }
* handled |= tmio_error_irq(host, irq, stat);
*/ irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid)
{
unsigned int ireg, status;
struct tmio_mmc_host *host = devid;
tmio_mmc_card_irq_status(host, &ireg, &status);
__tmio_mmc_card_detect_irq(host, ireg, status);
return IRQ_HANDLED;
}
EXPORT_SYMBOL(tmio_mmc_card_detect_irq);
static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host,
int ireg, int status)
{
/* Command completion */ /* Command completion */
if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) { if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
tmio_mmc_ack_mmc_irqs(host, tmio_mmc_ack_mmc_irqs(host,
TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDRESPEND |
TMIO_STAT_CMDTIMEOUT); TMIO_STAT_CMDTIMEOUT);
tmio_mmc_cmd_irq(host, status); tmio_mmc_cmd_irq(host, status);
goto out; return true;
} }
/* Data transfer */ /* Data transfer */
if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) { if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ); tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
tmio_mmc_pio_irq(host); tmio_mmc_pio_irq(host);
goto out; return true;
} }
/* Data transfer completion */ /* Data transfer completion */
if (ireg & TMIO_STAT_DATAEND) { if (ireg & TMIO_STAT_DATAEND) {
tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND); tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
tmio_mmc_data_irq(host); tmio_mmc_data_irq(host);
goto out; return true;
} }
pr_warning("tmio_mmc: Spurious irq, disabling! " return false;
"0x%08x 0x%08x 0x%08x\n", status, host->sdcard_irq_mask, ireg); }
pr_debug_status(status);
tmio_mmc_disable_mmc_irqs(host, status & ~host->sdcard_irq_mask); irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid)
{
unsigned int ireg, status;
struct tmio_mmc_host *host = devid;
tmio_mmc_card_irq_status(host, &ireg, &status);
__tmio_mmc_sdcard_irq(host, ireg, status);
return IRQ_HANDLED;
}
EXPORT_SYMBOL(tmio_mmc_sdcard_irq);
irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid)
{
struct tmio_mmc_host *host = devid;
struct mmc_host *mmc = host->mmc;
struct tmio_mmc_data *pdata = host->pdata;
unsigned int ireg, status;
if (!(pdata->flags & TMIO_MMC_SDIO_IRQ))
return IRQ_HANDLED;
status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask;
sd_ctrl_write16(host, CTL_SDIO_STATUS, status & ~TMIO_SDIO_MASK_ALL);
if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ)
mmc_signal_sdio_irq(mmc);
return IRQ_HANDLED;
}
EXPORT_SYMBOL(tmio_mmc_sdio_irq);
irqreturn_t tmio_mmc_irq(int irq, void *devid)
{
struct tmio_mmc_host *host = devid;
unsigned int ireg, status;
pr_debug("MMC IRQ begin\n");
tmio_mmc_card_irq_status(host, &ireg, &status);
if (__tmio_mmc_card_detect_irq(host, ireg, status))
return IRQ_HANDLED;
if (__tmio_mmc_sdcard_irq(host, ireg, status))
return IRQ_HANDLED;
tmio_mmc_sdio_irq(irq, devid);
out:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
EXPORT_SYMBOL(tmio_mmc_irq); EXPORT_SYMBOL(tmio_mmc_irq);
......
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