Obtain the optional vmmc and vqmmc regulators and configure them for
the normal SD voltage range before card initialization.

Request the standard 3.3 V target within the allowed 2.7-3.6 V range.
The regulator clamp operation lets regulators with discrete selectors
choose the closest supported voltage. This selects 2.91 V on AB8500 and
3.05 V on AB8505.

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 | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index 528612359789..8483d859fb96 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,21 @@
 #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
+
 struct arm_pl180_mmc_plat {
        struct mmc_config cfg;
        struct mmc mmc;
 };
 
+static int arm_pl180_set_supply_voltage(struct udevice *supply)
+{
+       return regulator_set_value_clamp(supply, SD_VOLTAGE_MIN_UV,
+                                        SD_VOLTAGE_UV, SD_VOLTAGE_MAX_UV);
+}
+
 static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
 {
        u32 hoststatus, statusmask;
@@ -445,6 +456,24 @@ 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);
+                       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);
+                       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

Reply via email to