diff options
Diffstat (limited to 'drivers/mmc/host/mmci.c')
-rw-r--r-- | drivers/mmc/host/mmci.c | 54 |
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 | ||