diff options
author | Simon Horman <horms@verge.net.au> | 2011-08-24 21:27:26 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-10-26 15:43:36 -0400 |
commit | 7729c7a232a95360fa17ffe8beb1adb621bc0ba0 (patch) | |
tree | 1e535ba26812b203e802939b9dbc3bb788f94232 /drivers/mmc | |
parent | 54680fe7f6ad0fb0c52e330484e2cf1609587862 (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.h | 3 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_pio.c | 131 |
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); | |||
97 | void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i); | 97 | void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i); |
98 | void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i); | 98 | void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i); |
99 | irqreturn_t tmio_mmc_irq(int irq, void *devid); | 99 | irqreturn_t tmio_mmc_irq(int irq, void *devid); |
100 | irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid); | ||
101 | irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid); | ||
102 | irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid); | ||
100 | 103 | ||
101 | static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, | 104 | static 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 | ||
548 | irqreturn_t tmio_mmc_irq(int irq, void *devid) | 548 | static 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); | 558 | static 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 | */ | 577 | irqreturn_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 | } | ||
587 | EXPORT_SYMBOL(tmio_mmc_card_detect_irq); | ||
588 | |||
589 | static 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); | 618 | irqreturn_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 | } | ||
628 | EXPORT_SYMBOL(tmio_mmc_sdcard_irq); | ||
629 | |||
630 | irqreturn_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 | } | ||
650 | EXPORT_SYMBOL(tmio_mmc_sdio_irq); | ||
651 | |||
652 | irqreturn_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 | ||
631 | out: | ||
632 | return IRQ_HANDLED; | 667 | return IRQ_HANDLED; |
633 | } | 668 | } |
634 | EXPORT_SYMBOL(tmio_mmc_irq); | 669 | EXPORT_SYMBOL(tmio_mmc_irq); |