aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/mmci.c51
-rw-r--r--drivers/mmc/host/mmci.h2
2 files changed, 45 insertions, 8 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 8324e3ec21c2..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,14 +1162,19 @@ 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
1147 cmd = host->cmd; 1175 cmd = host->cmd;
1148 if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT| 1176 if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
1149 MCI_CMDRESPEND) && cmd) 1177 MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
1150 mmci_cmd_irq(host, cmd, status); 1178 mmci_cmd_irq(host, cmd, status);
1151 1179
1152 data = host->data; 1180 data = host->data;
@@ -1155,6 +1183,10 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
1155 MCI_DATABLOCKEND) && data) 1183 MCI_DATABLOCKEND) && data)
1156 mmci_data_irq(host, data, status); 1184 mmci_data_irq(host, data, status);
1157 1185
1186 /* Don't poll for busy completion in irq context. */
1187 if (host->busy_status)
1188 status &= ~MCI_ST_CARDBUSY;
1189
1158 ret = 1; 1190 ret = 1;
1159 } while (status); 1191 } while (status);
1160 1192
@@ -1504,12 +1536,6 @@ static int mmci_probe(struct amba_device *dev,
1504 goto clk_disable; 1536 goto clk_disable;
1505 } 1537 }
1506 1538
1507 if (variant->busy_detect) {
1508 mmci_ops.card_busy = mmci_card_busy;
1509 mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
1510 }
1511
1512 mmc->ops = &mmci_ops;
1513 /* 1539 /*
1514 * The ARM and ST versions of the block have slightly different 1540 * The ARM and ST versions of the block have slightly different
1515 * clock divider equations which means that the minimum divider 1541 * clock divider equations which means that the minimum divider
@@ -1543,6 +1569,15 @@ static int mmci_probe(struct amba_device *dev,
1543 mmc->caps = plat->capabilities; 1569 mmc->caps = plat->capabilities;
1544 mmc->caps2 = plat->capabilities2; 1570 mmc->caps2 = plat->capabilities2;
1545 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
1546 /* We support these PM capabilities. */ 1581 /* We support these PM capabilities. */
1547 mmc->pm_caps = MMC_PM_KEEP_POWER; 1582 mmc->pm_caps = MMC_PM_KEEP_POWER;
1548 1583
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 168bc72f7a94..b008ace3e8ee 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -139,6 +139,7 @@
139/* Extended status bits for the ST Micro variants */ 139/* Extended status bits for the ST Micro variants */
140#define MCI_ST_SDIOITMASK (1 << 22) 140#define MCI_ST_SDIOITMASK (1 << 22)
141#define MCI_ST_CEATAENDMASK (1 << 23) 141#define MCI_ST_CEATAENDMASK (1 << 23)
142#define MCI_ST_BUSYEND (1 << 24)
142 143
143#define MMCIMASK1 0x040 144#define MMCIMASK1 0x040
144#define MMCIFIFOCNT 0x048 145#define MMCIFIFOCNT 0x048
@@ -186,6 +187,7 @@ struct mmci_host {
186 u32 pwr_reg; 187 u32 pwr_reg;
187 u32 clk_reg; 188 u32 clk_reg;
188 u32 datactrl_reg; 189 u32 datactrl_reg;
190 u32 busy_status;
189 bool vqmmc_enabled; 191 bool vqmmc_enabled;
190 struct mmci_platform_data *plat; 192 struct mmci_platform_data *plat;
191 struct variant_data *variant; 193 struct variant_data *variant;