Skip to content

Commit de5ccd2

Browse files
tmlindstorulf
authored andcommitted
mmc: sdhci-omap: Handle voltages to add support omap4
In order to start deprecating the custom omap_hsmmc.c in favor of the generic sdhci-omap driver, we need to add support for voltages for earlier SoCs. The PBIAS regulator on omap4 and earlier only supports nominal values of 1.8V and 3.0V, while omap5 and later support nominal values of 1.8V and 3.3V IO voltage. This gets omap4/5 working with sdhci-omap driver. Signed-off-by: Tony Lindgren <tony@atomide.com> Link: https://lore.kernel.org/r/20211015104720.52240-3-tony@atomide.com Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent 5310a77 commit de5ccd2

File tree

1 file changed

+96
-28
lines changed

1 file changed

+96
-28
lines changed

drivers/mmc/host/sdhci-omap.c

Lines changed: 96 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ static int sdhci_omap_set_pbias(struct sdhci_omap_host *omap_host,
178178
}
179179

180180
static int sdhci_omap_enable_iov(struct sdhci_omap_host *omap_host,
181-
unsigned int iov)
181+
unsigned int iov_pbias)
182182
{
183183
int ret;
184184
struct sdhci_host *host = omap_host->host;
@@ -189,14 +189,15 @@ static int sdhci_omap_enable_iov(struct sdhci_omap_host *omap_host,
189189
return ret;
190190

191191
if (!IS_ERR(mmc->supply.vqmmc)) {
192-
ret = regulator_set_voltage(mmc->supply.vqmmc, iov, iov);
193-
if (ret) {
192+
/* Pick the right voltage to allow 3.0V for 3.3V nominal PBIAS */
193+
ret = mmc_regulator_set_vqmmc(mmc, &mmc->ios);
194+
if (ret < 0) {
194195
dev_err(mmc_dev(mmc), "vqmmc set voltage failed\n");
195196
return ret;
196197
}
197198
}
198199

199-
ret = sdhci_omap_set_pbias(omap_host, true, iov);
200+
ret = sdhci_omap_set_pbias(omap_host, true, iov_pbias);
200201
if (ret)
201202
return ret;
202203

@@ -206,16 +207,28 @@ static int sdhci_omap_enable_iov(struct sdhci_omap_host *omap_host,
206207
static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host,
207208
unsigned char signal_voltage)
208209
{
209-
u32 reg;
210+
u32 reg, capa;
210211
ktime_t timeout;
211212

212213
reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL);
213214
reg &= ~HCTL_SDVS_MASK;
214215

215-
if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
216-
reg |= HCTL_SDVS_33;
217-
else
216+
switch (signal_voltage) {
217+
case MMC_SIGNAL_VOLTAGE_330:
218+
capa = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA);
219+
if (capa & CAPA_VS33)
220+
reg |= HCTL_SDVS_33;
221+
else if (capa & CAPA_VS30)
222+
reg |= HCTL_SDVS_30;
223+
else
224+
dev_warn(omap_host->dev, "misconfigured CAPA: %08x\n",
225+
capa);
226+
break;
227+
case MMC_SIGNAL_VOLTAGE_180:
228+
default:
218229
reg |= HCTL_SDVS_18;
230+
break;
231+
}
219232

220233
sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, reg);
221234

@@ -533,28 +546,32 @@ static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc,
533546

534547
if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
535548
reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA);
536-
if (!(reg & CAPA_VS33))
549+
if (!(reg & (CAPA_VS30 | CAPA_VS33)))
537550
return -EOPNOTSUPP;
538551

552+
if (reg & CAPA_VS30)
553+
iov = IOV_3V0;
554+
else
555+
iov = IOV_3V3;
556+
539557
sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage);
540558

541559
reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12);
542560
reg &= ~AC12_V1V8_SIGEN;
543561
sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg);
544562

545-
iov = IOV_3V3;
546563
} else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
547564
reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA);
548565
if (!(reg & CAPA_VS18))
549566
return -EOPNOTSUPP;
550567

568+
iov = IOV_1V8;
569+
551570
sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage);
552571

553572
reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12);
554573
reg |= AC12_V1V8_SIGEN;
555574
sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg);
556-
557-
iov = IOV_1V8;
558575
} else {
559576
return -EOPNOTSUPP;
560577
}
@@ -910,34 +927,73 @@ static struct sdhci_ops sdhci_omap_ops = {
910927
.set_timeout = sdhci_omap_set_timeout,
911928
};
912929

913-
static int sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host)
930+
static unsigned int sdhci_omap_regulator_get_caps(struct device *dev,
931+
const char *name)
914932
{
915-
u32 reg;
916-
int ret = 0;
933+
struct regulator *reg;
934+
unsigned int caps = 0;
935+
936+
reg = regulator_get(dev, name);
937+
if (IS_ERR(reg))
938+
return ~0U;
939+
940+
if (regulator_is_supported_voltage(reg, 1700000, 1950000))
941+
caps |= SDHCI_CAN_VDD_180;
942+
if (regulator_is_supported_voltage(reg, 2700000, 3150000))
943+
caps |= SDHCI_CAN_VDD_300;
944+
if (regulator_is_supported_voltage(reg, 3150000, 3600000))
945+
caps |= SDHCI_CAN_VDD_330;
946+
947+
regulator_put(reg);
948+
949+
return caps;
950+
}
951+
952+
static int sdhci_omap_set_capabilities(struct sdhci_host *host)
953+
{
954+
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
955+
struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host);
917956
struct device *dev = omap_host->dev;
918-
struct regulator *vqmmc;
957+
const u32 mask = SDHCI_CAN_VDD_180 | SDHCI_CAN_VDD_300 | SDHCI_CAN_VDD_330;
958+
unsigned int pbias, vqmmc, caps = 0;
959+
u32 reg;
919960

920-
vqmmc = regulator_get(dev, "vqmmc");
921-
if (IS_ERR(vqmmc)) {
922-
ret = PTR_ERR(vqmmc);
923-
goto reg_put;
924-
}
961+
pbias = sdhci_omap_regulator_get_caps(dev, "pbias");
962+
vqmmc = sdhci_omap_regulator_get_caps(dev, "vqmmc");
963+
caps = pbias & vqmmc;
964+
965+
if (pbias != ~0U && vqmmc == ~0U)
966+
dev_warn(dev, "vqmmc regulator missing for pbias\n");
967+
else if (caps == ~0U)
968+
return 0;
969+
970+
/*
971+
* Quirk handling to allow 3.0V vqmmc with a valid 3.3V PBIAS. This is
972+
* needed for 3.0V ldo9_reg on omap5 at least.
973+
*/
974+
if (pbias != ~0U && (pbias & SDHCI_CAN_VDD_330) &&
975+
(vqmmc & SDHCI_CAN_VDD_300))
976+
caps |= SDHCI_CAN_VDD_330;
925977

926978
/* voltage capabilities might be set by boot loader, clear it */
927979
reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA);
928980
reg &= ~(CAPA_VS18 | CAPA_VS30 | CAPA_VS33);
929981

930-
if (regulator_is_supported_voltage(vqmmc, IOV_3V3, IOV_3V3))
931-
reg |= CAPA_VS33;
932-
if (regulator_is_supported_voltage(vqmmc, IOV_1V8, IOV_1V8))
982+
if (caps & SDHCI_CAN_VDD_180)
933983
reg |= CAPA_VS18;
934984

985+
if (caps & SDHCI_CAN_VDD_300)
986+
reg |= CAPA_VS30;
987+
988+
if (caps & SDHCI_CAN_VDD_330)
989+
reg |= CAPA_VS33;
990+
935991
sdhci_omap_writel(omap_host, SDHCI_OMAP_CAPA, reg);
936992

937-
reg_put:
938-
regulator_put(vqmmc);
993+
host->caps &= ~mask;
994+
host->caps |= caps;
939995

940-
return ret;
996+
return 0;
941997
}
942998

943999
static const struct sdhci_pltfm_data sdhci_omap_pdata = {
@@ -953,6 +1009,16 @@ static const struct sdhci_pltfm_data sdhci_omap_pdata = {
9531009
.ops = &sdhci_omap_ops,
9541010
};
9551011

1012+
static const struct sdhci_omap_data omap4_data = {
1013+
.offset = 0x200,
1014+
.flags = SDHCI_OMAP_SPECIAL_RESET,
1015+
};
1016+
1017+
static const struct sdhci_omap_data omap5_data = {
1018+
.offset = 0x200,
1019+
.flags = SDHCI_OMAP_SPECIAL_RESET,
1020+
};
1021+
9561022
static const struct sdhci_omap_data k2g_data = {
9571023
.offset = 0x200,
9581024
};
@@ -973,6 +1039,8 @@ static const struct sdhci_omap_data dra7_data = {
9731039
};
9741040

9751041
static const struct of_device_id omap_sdhci_match[] = {
1042+
{ .compatible = "ti,omap4-sdhci", .data = &omap4_data },
1043+
{ .compatible = "ti,omap5-sdhci", .data = &omap5_data },
9761044
{ .compatible = "ti,dra7-sdhci", .data = &dra7_data },
9771045
{ .compatible = "ti,k2g-sdhci", .data = &k2g_data },
9781046
{ .compatible = "ti,am335-sdhci", .data = &am335_data },
@@ -1212,7 +1280,7 @@ static int sdhci_omap_probe(struct platform_device *pdev)
12121280
goto err_rpm_disable;
12131281
}
12141282

1215-
ret = sdhci_omap_set_capabilities(omap_host);
1283+
ret = sdhci_omap_set_capabilities(host);
12161284
if (ret) {
12171285
dev_err(dev, "failed to set system capabilities\n");
12181286
goto err_put_sync;

0 commit comments

Comments
 (0)