SD initialization failure happens with some UHS-I SD cards on
iMX8MM/iMX93/iMX91 EVK after
commit 4fcba5d556b4 ("regulator: implement basic reference counter").
When sending operation condition to SD card, the OCR does not return
correct status. The root cause is regulator on/off delay is missed
in MMC power cycle with above commit, so SD card is not completely
power off.

When SD startup, the sequence of MMC power cycle is:
mmc_power_init(get vmmc_supply dev) -> mmc_power_off -> udelay(2000)
-> mmc_power_on

Before above commit, as a fixed regulator, the GPIO is set as:
  GPIO inactive (in mmc_power_init) ->
  GPIO inactive and delay off-on-delay-us (in mmc_power_off) ->
  udelay(2000) ->
  GPIO active (in mmc_power_on)

After the commit:
  GPIO inactive (in mmc_power_init) ->
  enable_count is 0, regulator_set_enable returns -EALREADY immediately,
      so GPIO is inactive but No off-on-delay-us (in mmc_power_off) ->
  udelay(2000) ->
  GPIO active (in mmc_power_on)

Move the off-on-delay-us delay before setting GPIO active to fix the issue.

Signed-off-by: Ye Li <[email protected]>
---
Changes in v2:
 - move the off-on-delay before enabling the GPIO

 drivers/power/regulator/regulator_common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/power/regulator/regulator_common.c 
b/drivers/power/regulator/regulator_common.c
index 85af8d599ad..c0387eff4fc 100644
--- a/drivers/power/regulator/regulator_common.c
+++ b/drivers/power/regulator/regulator_common.c
@@ -87,6 +87,9 @@ int regulator_common_set_enable(const struct udevice *dev,
                        }
                }
 
+               if (enable && plat->off_on_delay_us)
+                       udelay(plat->off_on_delay_us);
+
                ret = dm_gpio_set_value(&plat->gpio, enable);
                if (ret) {
                        pr_err("Can't set regulator : %s gpio to: %d\n", 
dev->name,
@@ -97,9 +100,6 @@ int regulator_common_set_enable(const struct udevice *dev,
                if (enable && plat->startup_delay_us)
                        udelay(plat->startup_delay_us);
 
-               if (!enable && plat->off_on_delay_us)
-                       udelay(plat->off_on_delay_us);
-
                if (enable)
                        plat->enable_count++;
                else
-- 
2.37.1

Reply via email to