diff options
author | Kishon Vijay Abraham I <kishon@ti.com> | 2018-02-05 07:50:15 -0500 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2018-03-05 03:00:56 -0500 |
commit | 20ea26a1e3a513dadafcd35531c6d289820f60cb (patch) | |
tree | 8a6fff7dbd43e31b2b252c09fd7d950bc965b351 | |
parent | 300df508c806c0b0446f075bc7658f0fefa1b701 (diff) |
mmc: sdhci-omap: Add card_busy host ops
Add card_busy host ops in sdhci_omap to check card busy status.
The voltage switching sequence for AM572x platform is mentioned
in Figure 25-48. eMMC/SD/SDIO Power Switching Procedure of
AM572x Sitara Processors Silicon Revision 2.0, 1.1 TRM
(SPRUHZ6I - October 2014–Revised April 2017 [1]).
In the voltage switching sequence, CLKEXTFREE bit in MMCHS_CON
should also be set after switching to 1.8v which is also taken
care in the card_busy ops.
[1] -> http://www.ti.com/lit/ug/spruhz6i/spruhz6i.pdf
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/host/sdhci-omap.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 96985786cadf..df927f3faaf6 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c | |||
@@ -31,11 +31,17 @@ | |||
31 | #define SDHCI_OMAP_CON 0x12c | 31 | #define SDHCI_OMAP_CON 0x12c |
32 | #define CON_DW8 BIT(5) | 32 | #define CON_DW8 BIT(5) |
33 | #define CON_DMA_MASTER BIT(20) | 33 | #define CON_DMA_MASTER BIT(20) |
34 | #define CON_CLKEXTFREE BIT(16) | ||
35 | #define CON_PADEN BIT(15) | ||
34 | #define CON_INIT BIT(1) | 36 | #define CON_INIT BIT(1) |
35 | #define CON_OD BIT(0) | 37 | #define CON_OD BIT(0) |
36 | 38 | ||
37 | #define SDHCI_OMAP_CMD 0x20c | 39 | #define SDHCI_OMAP_CMD 0x20c |
38 | 40 | ||
41 | #define SDHCI_OMAP_PSTATE 0x0224 | ||
42 | #define PSTATE_DLEV_DAT0 BIT(20) | ||
43 | #define PSTATE_DATI BIT(1) | ||
44 | |||
39 | #define SDHCI_OMAP_HCTL 0x228 | 45 | #define SDHCI_OMAP_HCTL 0x228 |
40 | #define HCTL_SDBP BIT(8) | 46 | #define HCTL_SDBP BIT(8) |
41 | #define HCTL_SDVS_SHIFT 9 | 47 | #define HCTL_SDVS_SHIFT 9 |
@@ -191,6 +197,51 @@ static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host, | |||
191 | } | 197 | } |
192 | } | 198 | } |
193 | 199 | ||
200 | static int sdhci_omap_card_busy(struct mmc_host *mmc) | ||
201 | { | ||
202 | u32 reg, ac12; | ||
203 | int ret = false; | ||
204 | struct sdhci_host *host = mmc_priv(mmc); | ||
205 | struct sdhci_pltfm_host *pltfm_host; | ||
206 | struct sdhci_omap_host *omap_host; | ||
207 | u32 ier = host->ier; | ||
208 | |||
209 | pltfm_host = sdhci_priv(host); | ||
210 | omap_host = sdhci_pltfm_priv(pltfm_host); | ||
211 | |||
212 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); | ||
213 | ac12 = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); | ||
214 | reg &= ~CON_CLKEXTFREE; | ||
215 | if (ac12 & AC12_V1V8_SIGEN) | ||
216 | reg |= CON_CLKEXTFREE; | ||
217 | reg |= CON_PADEN; | ||
218 | sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); | ||
219 | |||
220 | disable_irq(host->irq); | ||
221 | ier |= SDHCI_INT_CARD_INT; | ||
222 | sdhci_writel(host, ier, SDHCI_INT_ENABLE); | ||
223 | sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); | ||
224 | |||
225 | /* | ||
226 | * Delay is required for PSTATE to correctly reflect | ||
227 | * DLEV/CLEV values after PADEN is set. | ||
228 | */ | ||
229 | usleep_range(50, 100); | ||
230 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_PSTATE); | ||
231 | if ((reg & PSTATE_DATI) || !(reg & PSTATE_DLEV_DAT0)) | ||
232 | ret = true; | ||
233 | |||
234 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); | ||
235 | reg &= ~(CON_CLKEXTFREE | CON_PADEN); | ||
236 | sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg); | ||
237 | |||
238 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | ||
239 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | ||
240 | enable_irq(host->irq); | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
194 | static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc, | 245 | static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc, |
195 | struct mmc_ios *ios) | 246 | struct mmc_ios *ios) |
196 | { | 247 | { |
@@ -562,6 +613,7 @@ static int sdhci_omap_probe(struct platform_device *pdev) | |||
562 | host->mmc_host_ops.start_signal_voltage_switch = | 613 | host->mmc_host_ops.start_signal_voltage_switch = |
563 | sdhci_omap_start_signal_voltage_switch; | 614 | sdhci_omap_start_signal_voltage_switch; |
564 | host->mmc_host_ops.set_ios = sdhci_omap_set_ios; | 615 | host->mmc_host_ops.set_ios = sdhci_omap_set_ios; |
616 | host->mmc_host_ops.card_busy = sdhci_omap_card_busy; | ||
565 | 617 | ||
566 | sdhci_read_caps(host); | 618 | sdhci_read_caps(host); |
567 | host->caps |= SDHCI_CAN_DO_ADMA2; | 619 | host->caps |= SDHCI_CAN_DO_ADMA2; |