aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/mmci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/mmci.c')
-rw-r--r--drivers/mmc/host/mmci.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index b93122636531..771c60ab4a32 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -921,6 +921,29 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
921{ 921{
922 void __iomem *base = host->base; 922 void __iomem *base = host->base;
923 bool sbc = (cmd == host->mrq->sbc); 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 host->cmd = NULL; 948 host->cmd = NULL;
926 949
@@ -1139,20 +1162,30 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
1139 status &= ~MCI_IRQ1MASK; 1162 status &= ~MCI_IRQ1MASK;
1140 } 1163 }
1141 1164
1165 /*
1166 * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's
1167 * enabled) since the HW seems to be triggering the IRQ on both
1168 * edges while monitoring DAT0 for busy completion.
1169 */
1142 status &= readl(host->base + MMCIMASK0); 1170 status &= readl(host->base + MMCIMASK0);
1143 writel(status, host->base + MMCICLEAR); 1171 writel(status, host->base + MMCICLEAR);
1144 1172
1145 dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); 1173 dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
1146 1174
1175 cmd = host->cmd;
1176 if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
1177 MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
1178 mmci_cmd_irq(host, cmd, status);
1179
1147 data = host->data; 1180 data = host->data;
1148 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR| 1181 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
1149 MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND| 1182 MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND|
1150 MCI_DATABLOCKEND) && data) 1183 MCI_DATABLOCKEND) && data)
1151 mmci_data_irq(host, data, status); 1184 mmci_data_irq(host, data, status);
1152 1185
1153 cmd = host->cmd; 1186 /* Don't poll for busy completion in irq context. */
1154 if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd) 1187 if (host->busy_status)
1155 mmci_cmd_irq(host, cmd, status); 1188 status &= ~MCI_ST_CARDBUSY;
1156 1189
1157 ret = 1; 1190 ret = 1;
1158 } while (status); 1191 } while (status);
@@ -1503,12 +1536,6 @@ static int mmci_probe(struct amba_device *dev,
1503 goto clk_disable; 1536 goto clk_disable;
1504 } 1537 }
1505 1538
1506 if (variant->busy_detect) {
1507 mmci_ops.card_busy = mmci_card_busy;
1508 mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
1509 }
1510
1511 mmc->ops = &mmci_ops;
1512 /* 1539 /*
1513 * The ARM and ST versions of the block have slightly different 1540 * The ARM and ST versions of the block have slightly different
1514 * clock divider equations which means that the minimum divider 1541 * clock divider equations which means that the minimum divider
@@ -1542,6 +1569,15 @@ static int mmci_probe(struct amba_device *dev,
1542 mmc->caps = plat->capabilities; 1569 mmc->caps = plat->capabilities;
1543 mmc->caps2 = plat->capabilities2; 1570 mmc->caps2 = plat->capabilities2;
1544 1571
1572 if (variant->busy_detect) {
1573 mmci_ops.card_busy = mmci_card_busy;
1574 mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
1575 mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
1576 mmc->max_busy_timeout = 0;
1577 }
1578
1579 mmc->ops = &mmci_ops;
1580
1545 /* We support these PM capabilities. */ 1581 /* We support these PM capabilities. */
1546 mmc->pm_caps = MMC_PM_KEEP_POWER; 1582 mmc->pm_caps = MMC_PM_KEEP_POWER;
1547 1583