[PATCH v3 04/11] mmc: arm_pl180: Set initial supply voltages

Linus Walleij <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <[email protected]>
Obtain the optional vmmc and vqmmc regulators and configure them for
the normal SD voltage range before card initialization.

The Ux500 boards supply their SD cards from AB8500 or AB8505 AUX3,
whose highest voltage selector is 2.91 V. Request that exact voltage
for Ux500 SD and SDIO hosts, while retaining the normal 3.3 V target
for eMMC-only hosts and other PL180 implementations.

Ignore the unsupported set-value operation for fixed regulators; their
voltage is already described by their fixed constraints.

Signed-off-by: Linus Walleij <[email protected]>
---
 drivers/mmc/arm_pl180_mmci.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index 528612359789..a2ea5cf03120 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -16,6 +16,7 @@
 #include <log.h>
 #include <malloc.h>
 #include <mmc.h>
+#include <power/regulator.h>
 #include <dm/device_compat.h>
 #include <dm.h>
 
@@ -28,11 +29,23 @@
 #define MMC_CLOCK_MAX	48000000
 #define MMC_CLOCK_MIN	400000
 
+#define SD_VOLTAGE_MIN_UV	2700000
+#define SD_VOLTAGE_UV		3300000
+#define SD_VOLTAGE_MAX_UV	3600000
+#define MMC_VOLTAGE_UV		3300000
+#define UX500_SD_VOLTAGE_UV	2910000
+
 struct arm_pl180_mmc_plat {
 	struct mmc_config cfg;
 	struct mmc mmc;
 };
 
+static int arm_pl180_set_supply_voltage(struct udevice *supply, int target_uV)
+{
+	return regulator_set_value_clamp(supply, SD_VOLTAGE_MIN_UV,
+					 target_uV, SD_VOLTAGE_MAX_UV);
+}
+
 static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
 {
 	u32 hoststatus, statusmask;
@@ -390,6 +403,7 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
 	struct pl180_mmc_host *host = dev_get_priv(dev);
 	struct mmc_config *cfg = &pdata->cfg;
 	struct clk clk;
+	int supply_uV = SD_VOLTAGE_UV;
 	u32 periphid;
 	int ret;
 
@@ -427,11 +441,15 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
 		cfg->voltages = VOLTAGE_WINDOW_MMC;
 		cfg->f_min = host->clock_in / (2 + SDI_CLKCR_CLKDIV_INIT_V2);
 		host->version2 = true;
+		supply_uV = UX500_SD_VOLTAGE_UV;
 		break;
 	default:
 		host->version2 = false; /* ARM variant */
 	}
 
+	if (dev_read_bool(dev, "no-sd"))
+		supply_uV = MMC_VOLTAGE_UV;
+
 	if (dev_read_bool(dev, "st,sig-dir-dat0"))
 		host->pwr_init |= SDI_PWR_DAT0DIREN;
 	if (dev_read_bool(dev, "st,sig-dir-dat2"))
@@ -445,6 +463,26 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
 	if (dev_read_bool(dev, "st,sig-pin-fbclk"))
 		host->pwr_init |= SDI_PWR_FBCLKEN;
 
+	if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
+		ret = device_get_supply_regulator(dev, "vmmc-supply",
+						  &mmc->vmmc_supply);
+		if (!ret) {
+			ret = arm_pl180_set_supply_voltage(mmc->vmmc_supply,
+							   supply_uV);
+			if (ret && ret != -ENOSYS)
+				return ret;
+		}
+
+		ret = device_get_supply_regulator(dev, "vqmmc-supply",
+						  &mmc->vqmmc_supply);
+		if (!ret) {
+			ret = arm_pl180_set_supply_voltage(mmc->vqmmc_supply,
+							   supply_uV);
+			if (ret && ret != -ENOSYS)
+				return ret;
+		}
+	}
+
 	gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN);
 
 	ret = mmc_of_parse(dev, cfg);

-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.