PL180 card supplies remain enabled after probing and while U-Boot is
running. They are no longer needed once control is handed to the operating
system.

When regulator support is enabled, mark the driver for removal during OS
preparation and disable its VMMC and VQMMC supplies from the remove
callback.

Reviewed-by: Peng Fan <[email protected]>
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 8627196a8050..9c18b666e4d2 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -50,6 +50,22 @@ static int arm_pl180_set_supply_voltage(struct udevice 
*supply)
 }
 #endif
 
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+static int arm_pl180_disable_supply(struct udevice *supply)
+{
+       int ret;
+
+       if (!supply)
+               return 0;
+
+       ret = regulator_set_enable_if_allowed(supply, false);
+       if (ret == -ENOSYS)
+               return 0;
+
+       return ret;
+}
+#endif
+
 static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
 {
        u32 hoststatus, statusmask;
@@ -494,6 +510,22 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
        return 0;
 }
 
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+static int arm_pl180_mmc_remove(struct udevice *dev)
+{
+       struct mmc *mmc = mmc_get_mmc_dev(dev);
+       int ret, vmmc_ret;
+
+       ret = arm_pl180_disable_supply(mmc->vqmmc_supply);
+       if (mmc->vmmc_supply != mmc->vqmmc_supply)
+               vmmc_ret = arm_pl180_disable_supply(mmc->vmmc_supply);
+       else
+               vmmc_ret = 0;
+
+       return ret ? ret : vmmc_ret;
+}
+#endif
+
 int arm_pl180_mmc_bind(struct udevice *dev)
 {
        struct arm_pl180_mmc_plat *plat = dev_get_plat(dev);
@@ -557,8 +589,14 @@ U_BOOT_DRIVER(arm_pl180_mmc) = {
        .of_match = arm_pl180_mmc_match,
        .ops = &arm_pl180_dm_mmc_ops,
        .probe = arm_pl180_mmc_probe,
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+       .remove = arm_pl180_mmc_remove,
+#endif
        .of_to_plat = arm_pl180_mmc_of_to_plat,
        .bind = arm_pl180_mmc_bind,
        .priv_auto      = sizeof(struct pl180_mmc_host),
        .plat_auto      = sizeof(struct arm_pl180_mmc_plat),
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+       .flags = DM_FLAG_OS_PREPARE,
+#endif
 };

-- 
2.55.0

Reply via email to