|
78 | 78 | #define STATUS_BUSY BIT(31) |
79 | 79 |
|
80 | 80 | #define SD_EMMC_IRQ_EN 0x4c |
81 | | -#define IRQ_EN_MASK GENMASK(13, 0) |
82 | 81 | #define IRQ_RXD_ERR_MASK GENMASK(7, 0) |
83 | 82 | #define IRQ_TXD_ERR BIT(8) |
84 | 83 | #define IRQ_DESC_ERR BIT(9) |
85 | 84 | #define IRQ_RESP_ERR BIT(10) |
| 85 | +#define IRQ_CRC_ERR \ |
| 86 | + (IRQ_RXD_ERR_MASK | IRQ_TXD_ERR | IRQ_DESC_ERR | IRQ_RESP_ERR) |
86 | 87 | #define IRQ_RESP_TIMEOUT BIT(11) |
87 | 88 | #define IRQ_DESC_TIMEOUT BIT(12) |
| 89 | +#define IRQ_TIMEOUTS \ |
| 90 | + (IRQ_RESP_TIMEOUT | IRQ_DESC_TIMEOUT) |
88 | 91 | #define IRQ_END_OF_CHAIN BIT(13) |
89 | 92 | #define IRQ_RESP_STATUS BIT(14) |
90 | 93 | #define IRQ_SDIO BIT(15) |
| 94 | +#define IRQ_EN_MASK \ |
| 95 | + (IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN | IRQ_RESP_STATUS |\ |
| 96 | + IRQ_SDIO) |
91 | 97 |
|
92 | 98 | #define SD_EMMC_CMD_CFG 0x50 |
93 | 99 | #define SD_EMMC_CMD_ARG 0x54 |
@@ -760,84 +766,61 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) |
760 | 766 | struct mmc_command *cmd; |
761 | 767 | struct mmc_data *data; |
762 | 768 | u32 irq_en, status, raw_status; |
763 | | - irqreturn_t ret = IRQ_HANDLED; |
| 769 | + irqreturn_t ret = IRQ_NONE; |
764 | 770 |
|
765 | | - if (WARN_ON(!host)) |
| 771 | + if (WARN_ON(!host) || WARN_ON(!host->cmd)) |
766 | 772 | return IRQ_NONE; |
767 | 773 |
|
768 | | - cmd = host->cmd; |
769 | | - |
770 | | - if (WARN_ON(!cmd)) |
771 | | - return IRQ_NONE; |
| 774 | + spin_lock(&host->lock); |
772 | 775 |
|
| 776 | + cmd = host->cmd; |
773 | 777 | data = cmd->data; |
774 | | - |
775 | | - spin_lock(&host->lock); |
776 | 778 | irq_en = readl(host->regs + SD_EMMC_IRQ_EN); |
777 | 779 | raw_status = readl(host->regs + SD_EMMC_STATUS); |
778 | 780 | status = raw_status & irq_en; |
779 | 781 |
|
780 | | - if (!status) { |
781 | | - dev_warn(host->dev, "Spurious IRQ! status=0x%08x, irq_en=0x%08x\n", |
782 | | - raw_status, irq_en); |
783 | | - ret = IRQ_NONE; |
784 | | - goto out; |
785 | | - } |
786 | | - |
787 | | - meson_mmc_read_resp(host->mmc, cmd); |
788 | | - |
789 | 782 | cmd->error = 0; |
790 | | - if (status & IRQ_RXD_ERR_MASK) { |
791 | | - dev_dbg(host->dev, "Unhandled IRQ: RXD error\n"); |
792 | | - cmd->error = -EILSEQ; |
793 | | - } |
794 | | - if (status & IRQ_TXD_ERR) { |
795 | | - dev_dbg(host->dev, "Unhandled IRQ: TXD error\n"); |
796 | | - cmd->error = -EILSEQ; |
797 | | - } |
798 | | - if (status & IRQ_DESC_ERR) |
799 | | - dev_dbg(host->dev, "Unhandled IRQ: Descriptor error\n"); |
800 | | - if (status & IRQ_RESP_ERR) { |
801 | | - dev_dbg(host->dev, "Unhandled IRQ: Response error\n"); |
| 783 | + if (status & IRQ_CRC_ERR) { |
| 784 | + dev_dbg(host->dev, "CRC Error - status 0x%08x\n", status); |
802 | 785 | cmd->error = -EILSEQ; |
| 786 | + ret = IRQ_HANDLED; |
| 787 | + goto out; |
803 | 788 | } |
804 | | - if (status & IRQ_RESP_TIMEOUT) { |
805 | | - dev_dbg(host->dev, "Unhandled IRQ: Response timeout\n"); |
| 789 | + |
| 790 | + if (status & IRQ_TIMEOUTS) { |
| 791 | + dev_dbg(host->dev, "Timeout - status 0x%08x\n", status); |
806 | 792 | cmd->error = -ETIMEDOUT; |
| 793 | + ret = IRQ_HANDLED; |
| 794 | + goto out; |
807 | 795 | } |
808 | | - if (status & IRQ_DESC_TIMEOUT) { |
809 | | - dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n"); |
810 | | - cmd->error = -ETIMEDOUT; |
| 796 | + |
| 797 | + meson_mmc_read_resp(host->mmc, cmd); |
| 798 | + |
| 799 | + if (status & IRQ_SDIO) { |
| 800 | + dev_dbg(host->dev, "IRQ: SDIO TODO.\n"); |
| 801 | + ret = IRQ_HANDLED; |
811 | 802 | } |
812 | | - if (status & IRQ_SDIO) |
813 | | - dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n"); |
814 | 803 |
|
815 | 804 | if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) { |
816 | 805 | if (data && !cmd->error) |
817 | 806 | data->bytes_xfered = data->blksz * data->blocks; |
818 | 807 | if (meson_mmc_bounce_buf_read(data) || |
819 | 808 | meson_mmc_get_next_command(cmd)) |
820 | 809 | ret = IRQ_WAKE_THREAD; |
821 | | - } else { |
822 | | - dev_warn(host->dev, "Unknown IRQ! status=0x%04x: MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n", |
823 | | - status, cmd->opcode, cmd->arg, |
824 | | - cmd->flags, cmd->mrq->stop ? 1 : 0); |
825 | | - if (cmd->data) { |
826 | | - struct mmc_data *data = cmd->data; |
827 | | - |
828 | | - dev_warn(host->dev, "\tblksz %u blocks %u flags 0x%08x (%s%s)", |
829 | | - data->blksz, data->blocks, data->flags, |
830 | | - data->flags & MMC_DATA_WRITE ? "write" : "", |
831 | | - data->flags & MMC_DATA_READ ? "read" : ""); |
832 | | - } |
| 810 | + else |
| 811 | + ret = IRQ_HANDLED; |
833 | 812 | } |
834 | 813 |
|
835 | 814 | out: |
836 | | - /* ack all (enabled) interrupts */ |
837 | | - writel(status, host->regs + SD_EMMC_STATUS); |
| 815 | + /* ack all enabled interrupts */ |
| 816 | + writel(irq_en, host->regs + SD_EMMC_STATUS); |
838 | 817 |
|
839 | 818 | if (ret == IRQ_HANDLED) |
840 | 819 | meson_mmc_request_done(host->mmc, cmd->mrq); |
| 820 | + else if (ret == IRQ_NONE) |
| 821 | + dev_warn(host->dev, |
| 822 | + "Unexpected IRQ! status=0x%08x, irq_en=0x%08x\n", |
| 823 | + raw_status, irq_en); |
841 | 824 |
|
842 | 825 | spin_unlock(&host->lock); |
843 | 826 | return ret; |
@@ -1017,10 +1000,12 @@ static int meson_mmc_probe(struct platform_device *pdev) |
1017 | 1000 | /* Stop execution */ |
1018 | 1001 | writel(0, host->regs + SD_EMMC_START); |
1019 | 1002 |
|
1020 | | - /* clear, ack, enable all interrupts */ |
| 1003 | + /* clear, ack and enable interrupts */ |
1021 | 1004 | writel(0, host->regs + SD_EMMC_IRQ_EN); |
1022 | | - writel(IRQ_EN_MASK, host->regs + SD_EMMC_STATUS); |
1023 | | - writel(IRQ_EN_MASK, host->regs + SD_EMMC_IRQ_EN); |
| 1005 | + writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN, |
| 1006 | + host->regs + SD_EMMC_STATUS); |
| 1007 | + writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN, |
| 1008 | + host->regs + SD_EMMC_IRQ_EN); |
1024 | 1009 |
|
1025 | 1010 | ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq, |
1026 | 1011 | meson_mmc_irq_thread, IRQF_SHARED, |
|
0 commit comments