diff options
-rw-r--r-- | drivers/mmc/host/mmci.c | 51 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.h | 2 |
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; |