aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2011-08-24 21:27:26 -0400
committerChris Ball <cjb@laptop.org>2011-10-26 15:43:36 -0400
commit7729c7a232a95360fa17ffe8beb1adb621bc0ba0 (patch)
tree1e535ba26812b203e802939b9dbc3bb788f94232 /drivers/mmc
parent54680fe7f6ad0fb0c52e330484e2cf1609587862 (diff)
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: Magnus Damm <magnus.damm@gmail.com> Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/tmio_mmc.h3
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c131
2 files changed, 86 insertions, 48 deletions
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 1cf8db558d08..3020f98218f0 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -97,6 +97,9 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host);
97void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i); 97void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
98void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i); 98void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
99irqreturn_t tmio_mmc_irq(int irq, void *devid); 99irqreturn_t tmio_mmc_irq(int irq, void *devid);
100irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid);
101irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid);
102irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid);
100 103
101static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, 104static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
102 unsigned long *flags) 105 unsigned long *flags)
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index f0c7830b8301..6275e3d76d39 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -545,44 +545,20 @@ out:
545 spin_unlock(&host->lock); 545 spin_unlock(&host->lock);
546} 546}
547 547
548irqreturn_t tmio_mmc_irq(int irq, void *devid) 548static void tmio_mmc_card_irq_status(struct tmio_mmc_host *host,
549 int *ireg, int *status)
549{ 550{
550 struct tmio_mmc_host *host = devid; 551 *status = sd_ctrl_read32(host, CTL_STATUS);
551 struct mmc_host *mmc = host->mmc; 552 *ireg = *status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask;
552 struct tmio_mmc_data *pdata = host->pdata;
553 unsigned int ireg, status;
554 unsigned int sdio_ireg, sdio_status;
555
556 pr_debug("MMC IRQ begin\n");
557
558 status = sd_ctrl_read32(host, CTL_STATUS);
559 ireg = status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask;
560 553
561 sdio_ireg = 0; 554 pr_debug_status(*status);
562 if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) { 555 pr_debug_status(*ireg);
563 sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS); 556}
564 sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL &
565 ~host->sdio_irq_mask;
566
567 sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL);
568
569 if (sdio_ireg && !host->sdio_irq_enabled) {
570 pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
571 sdio_status, host->sdio_irq_mask, sdio_ireg);
572 tmio_mmc_enable_sdio_irq(mmc, 0);
573 goto out;
574 }
575
576 if (mmc->caps & MMC_CAP_SDIO_IRQ &&
577 sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
578 mmc_signal_sdio_irq(mmc);
579
580 if (sdio_ireg)
581 goto out;
582 }
583 557
584 pr_debug_status(status); 558static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host,
585 pr_debug_status(ireg); 559 int ireg, int status)
560{
561 struct mmc_host *mmc = host->mmc;
586 562
587 /* Card insert / remove attempts */ 563 /* Card insert / remove attempts */
588 if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { 564 if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
@@ -592,43 +568,102 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
592 ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) && 568 ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) &&
593 !work_pending(&mmc->detect.work)) 569 !work_pending(&mmc->detect.work))
594 mmc_detect_change(host->mmc, msecs_to_jiffies(100)); 570 mmc_detect_change(host->mmc, msecs_to_jiffies(100));
595 goto out; 571 return true;
596 } 572 }
597 573
598 /* CRC and other errors */ 574 return false;
599/* if (ireg & TMIO_STAT_ERR_IRQ) 575}
600 * handled |= tmio_error_irq(host, irq, stat); 576
601 */ 577irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid)
578{
579 unsigned int ireg, status;
580 struct tmio_mmc_host *host = devid;
602 581
582 tmio_mmc_card_irq_status(host, &ireg, &status);
583 __tmio_mmc_card_detect_irq(host, ireg, status);
584
585 return IRQ_HANDLED;
586}
587EXPORT_SYMBOL(tmio_mmc_card_detect_irq);
588
589static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host,
590 int ireg, int status)
591{
603 /* Command completion */ 592 /* Command completion */
604 if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) { 593 if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
605 tmio_mmc_ack_mmc_irqs(host, 594 tmio_mmc_ack_mmc_irqs(host,
606 TMIO_STAT_CMDRESPEND | 595 TMIO_STAT_CMDRESPEND |
607 TMIO_STAT_CMDTIMEOUT); 596 TMIO_STAT_CMDTIMEOUT);
608 tmio_mmc_cmd_irq(host, status); 597 tmio_mmc_cmd_irq(host, status);
609 goto out; 598 return true;
610 } 599 }
611 600
612 /* Data transfer */ 601 /* Data transfer */
613 if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) { 602 if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
614 tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ); 603 tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
615 tmio_mmc_pio_irq(host); 604 tmio_mmc_pio_irq(host);
616 goto out; 605 return true;
617 } 606 }
618 607
619 /* Data transfer completion */ 608 /* Data transfer completion */
620 if (ireg & TMIO_STAT_DATAEND) { 609 if (ireg & TMIO_STAT_DATAEND) {
621 tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND); 610 tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
622 tmio_mmc_data_irq(host); 611 tmio_mmc_data_irq(host);
623 goto out; 612 return true;
624 } 613 }
625 614
626 pr_warning("tmio_mmc: Spurious irq, disabling! " 615 return false;
627 "0x%08x 0x%08x 0x%08x\n", status, host->sdcard_irq_mask, ireg); 616}
628 pr_debug_status(status); 617
629 tmio_mmc_disable_mmc_irqs(host, status & ~host->sdcard_irq_mask); 618irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid)
619{
620 unsigned int ireg, status;
621 struct tmio_mmc_host *host = devid;
622
623 tmio_mmc_card_irq_status(host, &ireg, &status);
624 __tmio_mmc_sdcard_irq(host, ireg, status);
625
626 return IRQ_HANDLED;
627}
628EXPORT_SYMBOL(tmio_mmc_sdcard_irq);
629
630irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid)
631{
632 struct tmio_mmc_host *host = devid;
633 struct mmc_host *mmc = host->mmc;
634 struct tmio_mmc_data *pdata = host->pdata;
635 unsigned int ireg, status;
636
637 if (!(pdata->flags & TMIO_MMC_SDIO_IRQ))
638 return IRQ_HANDLED;
639
640 status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
641 ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask;
642
643 sd_ctrl_write16(host, CTL_SDIO_STATUS, status & ~TMIO_SDIO_MASK_ALL);
644
645 if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ)
646 mmc_signal_sdio_irq(mmc);
647
648 return IRQ_HANDLED;
649}
650EXPORT_SYMBOL(tmio_mmc_sdio_irq);
651
652irqreturn_t tmio_mmc_irq(int irq, void *devid)
653{
654 struct tmio_mmc_host *host = devid;
655 unsigned int ireg, status;
656
657 pr_debug("MMC IRQ begin\n");
658
659 tmio_mmc_card_irq_status(host, &ireg, &status);
660 if (__tmio_mmc_card_detect_irq(host, ireg, status))
661 return IRQ_HANDLED;
662 if (__tmio_mmc_sdcard_irq(host, ireg, status))
663 return IRQ_HANDLED;
664
665 tmio_mmc_sdio_irq(irq, devid);
630 666
631out:
632 return IRQ_HANDLED; 667 return IRQ_HANDLED;
633} 668}
634EXPORT_SYMBOL(tmio_mmc_irq); 669EXPORT_SYMBOL(tmio_mmc_irq);