Skip to content

Commit

Permalink
mmc: tmio: Provide separate interrupt handlers
Browse files Browse the repository at this point in the history
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: Magnus Damm <magnus.damm@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Chris Ball <cjb@laptop.org>
  • Loading branch information
Simon Horman authored and Chris Ball committed Oct 26, 2011
1 parent 54680fe commit 7729c7a
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 48 deletions.
3 changes: 3 additions & 0 deletions drivers/mmc/host/tmio_mmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
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,
unsigned long *flags)
Expand Down
131 changes: 83 additions & 48 deletions drivers/mmc/host/tmio_mmc_pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,44 +545,20 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
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;
struct mmc_host *mmc = host->mmc;
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;
*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);

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);
pr_debug_status(*ireg);
}

pr_debug_status(status);
pr_debug_status(ireg);
static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host,
int ireg, int status)
{
struct mmc_host *mmc = host->mmc;

/* Card insert / remove attempts */
if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
Expand All @@ -592,43 +568,102 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) &&
!work_pending(&mmc->detect.work))
mmc_detect_change(host->mmc, msecs_to_jiffies(100));
goto out;
return true;
}

/* CRC and other errors */
/* if (ireg & TMIO_STAT_ERR_IRQ)
* handled |= tmio_error_irq(host, irq, stat);
*/
return false;
}

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 */
if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
tmio_mmc_ack_mmc_irqs(host,
TMIO_STAT_CMDRESPEND |
TMIO_STAT_CMDTIMEOUT);
tmio_mmc_cmd_irq(host, status);
goto out;
return true;
}

/* Data transfer */
if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
tmio_mmc_pio_irq(host);
goto out;
return true;
}

/* Data transfer completion */
if (ireg & TMIO_STAT_DATAEND) {
tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
tmio_mmc_data_irq(host);
goto out;
return true;
}

pr_warning("tmio_mmc: Spurious irq, disabling! "
"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);
return false;
}

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;
}
EXPORT_SYMBOL(tmio_mmc_irq);
Expand Down

0 comments on commit 7729c7a

Please sign in to comment.