|
@@ -545,44 +545,20 @@ out:
|
|
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;
|
|
|
|
- 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 */
|
|
/* 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)
|
|
((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 */
|
|
|
|
-/* 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 */
|
|
/* 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! "
|
|
|
|
- "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;
|
|
return IRQ_HANDLED;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(tmio_mmc_irq);
|
|
EXPORT_SYMBOL(tmio_mmc_irq);
|