summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRavikumar Kattekola <rk@ti.com>2017-05-30 14:42:53 +0530
committerDavid Huang <d-huang@ti.com>2017-10-30 15:54:09 -0600
commit2352f6a4a8e0384d8c013a5d8c4592a07a2dbe11 (patch)
treede42fe0f3857c55ebab45e33dfe1700774539e4d
parent0f924ed3fb4badf92a0d9e8c65565cae9a9de3cf (diff)
downloadomap-omapzoom-2352f6a4a8e0384d8c013a5d8c4592a07a2dbe11.tar.gz
mmc: host: omap_hsmmc: Enable io voltage switch to 3.3V
commit 54d44bde0a6e ("mmc: host: omap_hsmmc: Enable io voltage switch to 3.3V") branch ti-linux-4.9.y The mmc ip on OMAPx/DRA7x platforms supports io operation at 3.3v but it has been trimmed to 3.0v in order to align with the PBIAS cell supported voltage, as documented in the reference manuals. PBIAS cell is an additional hw component on the chip external to the mmc ip that provides an internal bias voltage reference needed for reliable operation of the ios - on dual voltage capable mmc instances. Reference manuals of OMAP5x and DRA7x have been updated to reflect the PBIAS regulator max-voltage as 3.3V instead of 3.0V, while OMAP3x and OMAP4x are still quoting 3.0V. So, as of now, the mmc driver needs to support both 3.0V and 3.3V IO voltage based on the max-voltage supported by the PBIAS regulator. Document reference: SWPU249AF - OMAP543x Technical reference manual - August 2016 SPRUI30C – DRA75x, DRA74x Technical reference manual November 2016 Tested on: DRA75x PG 2.0 REV H EVM Signed-off-by: Ravikumar Kattekola <rk@ti.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
-rw-r--r--drivers/mmc/host/omap_hsmmc.c83
1 files changed, 67 insertions, 16 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index e3d6a6e2a6f8..2738871e2933 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -78,6 +78,7 @@
#define MADMA_EN (1 << 0)
#define VS18 (1 << 26)
#define VS30 (1 << 25)
+#define VS33 (1 << 24)
#define VS_MASK (0x7 << 24)
#define HSS (1 << 21)
#define SDVS18 (0x5 << 9)
@@ -186,8 +187,10 @@
#define VDD_1V8 1800000 /* 180000 uV */
#define VDD_3V0 3000000 /* 300000 uV */
+#define VDD_3V3 3300000 /* 330000 uV */
#define VDD_165_195 (ffs(MMC_VDD_165_195) - 1)
#define VDD_30_31 (ffs(MMC_VDD_30_31) - 1)
+#define VDD_33_34 (ffs(MMC_VDD_33_34) - 1)
#define CON_CLKEXTFREE (1 << 16)
#define CON_PADEN (1 << 15)
@@ -257,6 +260,7 @@ struct omap_hsmmc_host {
struct clk *dbclk;
struct regulator *pbias;
bool pbias_enabled;
+ bool io_3_3v_support;
void __iomem *base;
int vqmmc_enabled;
resource_size_t mapbase;
@@ -368,7 +372,13 @@ static int omap_hsmmc_enable_supply(struct mmc_host *mmc, int iov)
host->vqmmc_enabled = 0;
}
- uvoltage = (iov == VDD_165_195) ? VDD_1V8 : VDD_3V0;
+ if (iov == VDD_165_195)
+ uvoltage = VDD_1V8;
+ else if (iov == VDD_33_34)
+ uvoltage = VDD_3V3;
+ else
+ uvoltage = VDD_3V0;
+
ret = regulator_set_voltage(mmc->supply.vqmmc, uvoltage,
uvoltage);
if (ret) {
@@ -436,7 +446,13 @@ static int omap_hsmmc_set_pbias(struct omap_hsmmc_host *host, bool power_on,
return 0;
if (power_on) {
- uvoltage = (iov <= VDD_165_195) ? VDD_1V8 : VDD_3V0;
+ if (iov <= VDD_165_195)
+ uvoltage = VDD_1V8;
+ else if (iov == VDD_33_34)
+ uvoltage = VDD_3V3;
+ else
+ uvoltage = VDD_3V0;
+
ret = regulator_set_voltage(host->pbias, uvoltage, uvoltage);
if (ret) {
dev_err(host->dev, "pbias set voltage failed\n");
@@ -862,12 +878,21 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
if (host->power_mode != MMC_POWER_OFF &&
(1 << ios->vdd) <= MMC_VDD_23_24)
hctl = SDVS18;
- else
+ else if (host->io_3_3v_support) {
+ hctl = SDVS33;
+ capa = VS33 | VS18;
+ } else {
hctl = SDVS30;
- capa = VS30 | VS18;
+ capa = VS30 | VS18;
+ }
} else if (host->pdata->controller_flags & OMAP_HSMMC_NO_1_8_V) {
- hctl = SDVS30;
- capa = VS30;
+ if (host->io_3_3v_support) {
+ hctl = SDVS33;
+ capa = VS33;
+ } else {
+ hctl = SDVS30;
+ capa = VS30;
+ }
} else {
hctl = SDVS18;
capa = VS18;
@@ -2150,9 +2175,15 @@ static void omap_hsmmc_set_capabilities(struct omap_hsmmc_host *host)
val = OMAP_HSMMC_READ(host->base, CAPA) & ~VS_MASK;
if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
- val |= (VS30 | VS18);
+ if (host->io_3_3v_support)
+ val |= (VS33 | VS18);
+ else
+ val |= (VS30 | VS18);
} else if (host->pdata->controller_flags & OMAP_HSMMC_NO_1_8_V) {
- val |= VS30;
+ if (host->io_3_3v_support)
+ val |= VS33;
+ else
+ val |= VS30;
} else {
val |= VS18;
}
@@ -2162,10 +2193,15 @@ static void omap_hsmmc_set_capabilities(struct omap_hsmmc_host *host)
static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host, int iov)
{
- u32 hctl, value;
+ u32 hctl = SDVS30, value;
value = OMAP_HSMMC_READ(host->base, HCTL) & ~SDVS_MASK;
- hctl = (iov == MMC_SIGNAL_VOLTAGE_180) ? SDVS18 : SDVS30;
+
+ if (iov == MMC_SIGNAL_VOLTAGE_180)
+ hctl = SDVS18;
+ else if (host->io_3_3v_support)
+ hctl = SDVS33;
+
OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl);
/* Set SD bus power bit */
@@ -2188,27 +2224,35 @@ static int omap_hsmmc_start_signal_voltage_switch(struct mmc_host *mmc,
struct omap_hsmmc_host *host;
u32 val = 0;
int ret = 0;
+ u32 iov;
host = mmc_priv(mmc);
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
val = OMAP_HSMMC_READ(host->base, CAPA);
- if (!(val & VS30))
+ if (!(val & (VS30 | VS33)))
return -EOPNOTSUPP;
+ if (val & VS33)
+ iov = VDD_33_34;
+ else
+ iov = VDD_30_31;
+
omap_hsmmc_conf_bus_power(host, ios->signal_voltage);
val = OMAP_HSMMC_READ(host->base, AC12);
val &= ~AC12_V1V8_SIGEN;
OMAP_HSMMC_WRITE(host->base, AC12, val);
- ret = omap_hsmmc_set_power(host->dev, 1, VDD_30_31);
+ ret = omap_hsmmc_set_power(host->dev, 1, iov);
if (ret) {
- dev_err(mmc_dev(host->mmc), "failed to switch to 3v\n");
+ dev_err(mmc_dev(host->mmc),
+ "failed to switch to %uV\n", iov);
return ret;
}
- dev_dbg(mmc_dev(host->mmc), " i/o voltage switch to 3V\n");
+ dev_dbg(mmc_dev(host->mmc),
+ "i/o voltage switched to %uV\n", iov);
} else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
val = OMAP_HSMMC_READ(host->base, CAPA);
if (!(val & VS18))
@@ -2895,8 +2939,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
mmc->pm_caps |= mmc_pdata(host)->pm_caps;
- omap_hsmmc_set_capabilities(host);
-
ret = omap_hsmmc_get_iodelay_pinctrl_state(host);
if (ret)
goto err_pinctrl;
@@ -2922,6 +2964,15 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
mmc->ocr_avail = mmc_pdata(host)->ocr_mask;
+ /* Get pbias max-voltage and update host capabilities */
+ if (host->pbias &&
+ regulator_is_supported_voltage(host->pbias, VDD_3V3, VDD_3V3)) {
+ host->io_3_3v_support = true;
+ dev_dbg(mmc_dev(host->mmc), "PBIAS supports 3.3V not 3V\n");
+ }
+
+ omap_hsmmc_set_capabilities(host);
+
omap_hsmmc_disable_irq(host);
/*