Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: mmci: Enable support for busy detection for ux500 variant

The ux500 variants have HW busy detection support, which is indicated
by the busy_detect flag. For these variants let's enable the
MMC_CAP_WAIT_WHILE_BUSY flag and add the support for it.

The mmc core will provide the RSP_BUSY command flag for those requests
we should care about busy detection. Regarding the max_busy_timeout,
the HW don't support busy detection timeouts so at this initial step
let's make it simple and set it to zero to indicate we are able to
support any timeout.

Cc: Russell King <linux@arm.linux.org.uk>
Cc: Johan Rudholm <jrudholm@gmail.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Chris Ball <chris@printf.net>

authored by

Ulf Hansson and committed by
Chris Ball
8d94b54d e7f3d222

+45 -8
+43 -8
drivers/mmc/host/mmci.c
··· 921 921 { 922 922 void __iomem *base = host->base; 923 923 bool sbc = (cmd == host->mrq->sbc); 924 + bool busy_resp = host->variant->busy_detect && 925 + (cmd->flags & MMC_RSP_BUSY); 926 + 927 + /* Check if we need to wait for busy completion. */ 928 + if (host->busy_status && (status & MCI_ST_CARDBUSY)) 929 + return; 930 + 931 + /* Enable busy completion if needed and supported. */ 932 + if (!host->busy_status && busy_resp && 933 + !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) && 934 + (readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) { 935 + writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND, 936 + base + MMCIMASK0); 937 + host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND); 938 + return; 939 + } 940 + 941 + /* At busy completion, mask the IRQ and complete the request. */ 942 + if (host->busy_status) { 943 + writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND, 944 + base + MMCIMASK0); 945 + host->busy_status = 0; 946 + } 924 947 925 948 host->cmd = NULL; 926 949 ··· 1162 1139 status &= ~MCI_IRQ1MASK; 1163 1140 } 1164 1141 1142 + /* 1143 + * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's 1144 + * enabled) since the HW seems to be triggering the IRQ on both 1145 + * edges while monitoring DAT0 for busy completion. 1146 + */ 1165 1147 status &= readl(host->base + MMCIMASK0); 1166 1148 writel(status, host->base + MMCICLEAR); 1167 1149 1168 1150 dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); 1169 1151 1170 1152 cmd = host->cmd; 1171 - if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT| 1172 - MCI_CMDRESPEND) && cmd) 1153 + if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT| 1154 + MCI_CMDSENT|MCI_CMDRESPEND) && cmd) 1173 1155 mmci_cmd_irq(host, cmd, status); 1174 1156 1175 1157 data = host->data; ··· 1182 1154 MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND| 1183 1155 MCI_DATABLOCKEND) && data) 1184 1156 mmci_data_irq(host, data, status); 1157 + 1158 + /* Don't poll for busy completion in irq context. */ 1159 + if (host->busy_status) 1160 + status &= ~MCI_ST_CARDBUSY; 1185 1161 1186 1162 ret = 1; 1187 1163 } while (status); ··· 1536 1504 goto clk_disable; 1537 1505 } 1538 1506 1539 - if (variant->busy_detect) { 1540 - mmci_ops.card_busy = mmci_card_busy; 1541 - mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE); 1542 - } 1543 - 1544 - mmc->ops = &mmci_ops; 1545 1507 /* 1546 1508 * The ARM and ST versions of the block have slightly different 1547 1509 * clock divider equations which means that the minimum divider ··· 1568 1542 1569 1543 mmc->caps = plat->capabilities; 1570 1544 mmc->caps2 = plat->capabilities2; 1545 + 1546 + if (variant->busy_detect) { 1547 + mmci_ops.card_busy = mmci_card_busy; 1548 + mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE); 1549 + mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; 1550 + mmc->max_busy_timeout = 0; 1551 + } 1552 + 1553 + mmc->ops = &mmci_ops; 1571 1554 1572 1555 /* We support these PM capabilities. */ 1573 1556 mmc->pm_caps = MMC_PM_KEEP_POWER;
+2
drivers/mmc/host/mmci.h
··· 139 139 /* Extended status bits for the ST Micro variants */ 140 140 #define MCI_ST_SDIOITMASK (1 << 22) 141 141 #define MCI_ST_CEATAENDMASK (1 << 23) 142 + #define MCI_ST_BUSYEND (1 << 24) 142 143 143 144 #define MMCIMASK1 0x040 144 145 #define MMCIFIFOCNT 0x048 ··· 187 186 u32 pwr_reg; 188 187 u32 clk_reg; 189 188 u32 datactrl_reg; 189 + u32 busy_status; 190 190 bool vqmmc_enabled; 191 191 struct mmci_platform_data *plat; 192 192 struct variant_data *variant;