diff mbox

RFC: mmc: core: Increase delay for voltage to stabilize from 3.3V to 1.8V

Message ID 1431467171-12937-1-git-send-email-dianders@chromium.org (mailing list archive)
State New, archived
Headers show

Commit Message

Doug Anderson May 12, 2015, 9:46 p.m. UTC
Since the regulator used for the SDMMC IO voltage is not expected to
draw a lot of current, most systems will probably use an inexpensive
LDO for it.  LDO regulators apparently have the feature that they
don't actively drive the voltage down--they wait for other components
in the system to drag the voltage down.  Thus they will transition
faster under heavy loads and slower under light loads.

During an SDMMC voltage change from 3.3V to 1.8V, we are almost
certainly under a light load.  To be specific:
* The regulator is hooked through pulls to CMD0-3 and DAT.  Probably
  the CMD pulls are something like 47K and the DAT is something like
  10K.
* The card is supposed to be driving DAT0-3 low during voltage change
  which will draw _some_ current, but not a lot.
* The regulator is also provided to the SDMMC host controller, but the
  SDMMC host controller is in open drain mode during the voltage
  change and so shouldn't be drawing much current.

In order to keep the SDMMC host working properly (or for noise
reasons), there might also be a capacitor attached to the SDMMC IO
regulator.  This also will have the effect of slowing down transitions
of the regulator, especially under light loads.

From experimental evidence, we've seen the voltage change fail if the
card doesn't detect that the voltage fell to less than about 2.3V when
we turn on the clock.  On one device (that admittedly had a 47K CMD
pullup instead of a 10K CMD pullup) we saw that the voltage was just
about 2.3V after 5ms and thus the voltage change would sometimes fail.
Doubling the delay gave margin and made the voltage change work 100%
of the time, despite the slightly weaker CMD pull.

At the moment submitting this as an RFC patch since my problem _could_
be fixed by increasing the pull strength (or using a smaller
capacitor).  However being a little bit more lenient to strange
hardware could also be a good thing.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 drivers/mmc/core/core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Mark Brown May 13, 2015, 11:09 a.m. UTC | #1
On Tue, May 12, 2015 at 02:46:11PM -0700, Doug Anderson wrote:
> Since the regulator used for the SDMMC IO voltage is not expected to
> draw a lot of current, most systems will probably use an inexpensive
> LDO for it.  LDO regulators apparently have the feature that they
> don't actively drive the voltage down--they wait for other components
> in the system to drag the voltage down.  Thus they will transition
> faster under heavy loads and slower under light loads.

What a LDO is doing is basically just charging up a capacitor - the
regulation consists of monitoring the voltage on the capacitor and
opening a transistor to charge the capacitor when the voltage droops too
much.

> From experimental evidence, we've seen the voltage change fail if the
> card doesn't detect that the voltage fell to less than about 2.3V when
> we turn on the clock.  On one device (that admittedly had a 47K CMD
> pullup instead of a 10K CMD pullup) we saw that the voltage was just
> about 2.3V after 5ms and thus the voltage change would sometimes fail.
> Doubling the delay gave margin and made the voltage change work 100%
> of the time, despite the slightly weaker CMD pull.

> At the moment submitting this as an RFC patch since my problem _could_
> be fixed by increasing the pull strength (or using a smaller
> capacitor).  However being a little bit more lenient to strange
> hardware could also be a good thing.

Right, and this is probably going beyond the delays that the regulator
API is handling since it's not something the regulator hardware is
actively managing.
Ulf Hansson May 13, 2015, 1:06 p.m. UTC | #2
On 13 May 2015 at 13:09, Mark Brown <broonie@kernel.org> wrote:
> On Tue, May 12, 2015 at 02:46:11PM -0700, Doug Anderson wrote:
>> Since the regulator used for the SDMMC IO voltage is not expected to
>> draw a lot of current, most systems will probably use an inexpensive
>> LDO for it.  LDO regulators apparently have the feature that they
>> don't actively drive the voltage down--they wait for other components
>> in the system to drag the voltage down.  Thus they will transition
>> faster under heavy loads and slower under light loads.
>
> What a LDO is doing is basically just charging up a capacitor - the
> regulation consists of monitoring the voltage on the capacitor and
> opening a transistor to charge the capacitor when the voltage droops too
> much.
>
>> From experimental evidence, we've seen the voltage change fail if the
>> card doesn't detect that the voltage fell to less than about 2.3V when
>> we turn on the clock.  On one device (that admittedly had a 47K CMD
>> pullup instead of a 10K CMD pullup) we saw that the voltage was just
>> about 2.3V after 5ms and thus the voltage change would sometimes fail.
>> Doubling the delay gave margin and made the voltage change work 100%
>> of the time, despite the slightly weaker CMD pull.
>
>> At the moment submitting this as an RFC patch since my problem _could_
>> be fixed by increasing the pull strength (or using a smaller
>> capacitor).  However being a little bit more lenient to strange
>> hardware could also be a good thing.
>
> Right, and this is probably going beyond the delays that the regulator
> API is handling since it's not something the regulator hardware is
> actively managing.

Thanks for elaborating from the regulator perspective. So may I apply
your ack for this one?

Kind regards
Uffe
Mark Brown May 13, 2015, 3:32 p.m. UTC | #3
On Wed, May 13, 2015 at 03:06:47PM +0200, Ulf Hansson wrote:
> On 13 May 2015 at 13:09, Mark Brown <broonie@kernel.org> wrote:

> > Right, and this is probably going beyond the delays that the regulator
> > API is handling since it's not something the regulator hardware is
> > actively managing.

> Thanks for elaborating from the regulator perspective. So may I apply
> your ack for this one?

I guess, yes.
Doug Anderson May 15, 2015, 5:34 p.m. UTC | #4
Hi,

On Tue, May 12, 2015 at 2:46 PM, Doug Anderson <dianders@chromium.org> wrote:
> Since the regulator used for the SDMMC IO voltage is not expected to
> draw a lot of current, most systems will probably use an inexpensive
> LDO for it.  LDO regulators apparently have the feature that they
> don't actively drive the voltage down--they wait for other components
> in the system to drag the voltage down.  Thus they will transition
> faster under heavy loads and slower under light loads.
>
> During an SDMMC voltage change from 3.3V to 1.8V, we are almost
> certainly under a light load.  To be specific:
> * The regulator is hooked through pulls to CMD0-3 and DAT.  Probably
>   the CMD pulls are something like 47K and the DAT is something like
>   10K.
> * The card is supposed to be driving DAT0-3 low during voltage change
>   which will draw _some_ current, but not a lot.
> * The regulator is also provided to the SDMMC host controller, but the
>   SDMMC host controller is in open drain mode during the voltage
>   change and so shouldn't be drawing much current.
>
> In order to keep the SDMMC host working properly (or for noise
> reasons), there might also be a capacitor attached to the SDMMC IO
> regulator.  This also will have the effect of slowing down transitions
> of the regulator, especially under light loads.
>
> From experimental evidence, we've seen the voltage change fail if the
> card doesn't detect that the voltage fell to less than about 2.3V when
> we turn on the clock.  On one device (that admittedly had a 47K CMD
> pullup instead of a 10K CMD pullup) we saw that the voltage was just
> about 2.3V after 5ms and thus the voltage change would sometimes fail.
> Doubling the delay gave margin and made the voltage change work 100%
> of the time, despite the slightly weaker CMD pull.
>
> At the moment submitting this as an RFC patch since my problem _could_
> be fixed by increasing the pull strength (or using a smaller
> capacitor).  However being a little bit more lenient to strange
> hardware could also be a good thing.
>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> ---
>  drivers/mmc/core/core.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

One other note is that I'm now seeing this even on a device that has
the proper external pulls.  Maybe external capacitor is too big, but
it's too late to change that now.  I didn't see it before on that
device because we (accidentally) also had the internal pulls turned on
which were draining voltage faster.  I could try adding the internal
pulls back in, but that somehow seems worse than this.  One other
benefit of adding a little bit longer delay is that when we start
tuning it's more likely that we'll be tuning at a more stable voltage,
even if we don't actually get an error.

I'm planning to apply this locally, but still up to you of course
whether you want to take it upstream.  :)

-Doug
Ulf Hansson May 18, 2015, 9:23 a.m. UTC | #5
On 12 May 2015 at 23:46, Doug Anderson <dianders@chromium.org> wrote:
> Since the regulator used for the SDMMC IO voltage is not expected to
> draw a lot of current, most systems will probably use an inexpensive
> LDO for it.  LDO regulators apparently have the feature that they
> don't actively drive the voltage down--they wait for other components
> in the system to drag the voltage down.  Thus they will transition
> faster under heavy loads and slower under light loads.
>
> During an SDMMC voltage change from 3.3V to 1.8V, we are almost
> certainly under a light load.  To be specific:
> * The regulator is hooked through pulls to CMD0-3 and DAT.  Probably
>   the CMD pulls are something like 47K and the DAT is something like
>   10K.
> * The card is supposed to be driving DAT0-3 low during voltage change
>   which will draw _some_ current, but not a lot.
> * The regulator is also provided to the SDMMC host controller, but the
>   SDMMC host controller is in open drain mode during the voltage
>   change and so shouldn't be drawing much current.
>
> In order to keep the SDMMC host working properly (or for noise
> reasons), there might also be a capacitor attached to the SDMMC IO
> regulator.  This also will have the effect of slowing down transitions
> of the regulator, especially under light loads.
>
> From experimental evidence, we've seen the voltage change fail if the
> card doesn't detect that the voltage fell to less than about 2.3V when
> we turn on the clock.  On one device (that admittedly had a 47K CMD
> pullup instead of a 10K CMD pullup) we saw that the voltage was just
> about 2.3V after 5ms and thus the voltage change would sometimes fail.
> Doubling the delay gave margin and made the voltage change work 100%
> of the time, despite the slightly weaker CMD pull.
>
> At the moment submitting this as an RFC patch since my problem _could_
> be fixed by increasing the pull strength (or using a smaller
> capacitor).  However being a little bit more lenient to strange
> hardware could also be a good thing.
>
> Signed-off-by: Doug Anderson <dianders@chromium.org>

Thanks, applied.

Kind regards
Uffe

> ---
>  drivers/mmc/core/core.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 92e7671..a7e6110 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -1551,8 +1551,8 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
>                 goto power_cycle;
>         }
>
> -       /* Keep clock gated for at least 5 ms */
> -       mmc_delay(5);
> +       /* Keep clock gated for at least 10 ms, though spec only says 5 ms */
> +       mmc_delay(10);
>         host->ios.clock = clock;
>         mmc_set_ios(host);
>
> --
> 2.2.0.rc0.207.ga3a616c
>
diff mbox

Patch

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 92e7671..a7e6110 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1551,8 +1551,8 @@  int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
 		goto power_cycle;
 	}
 
-	/* Keep clock gated for at least 5 ms */
-	mmc_delay(5);
+	/* Keep clock gated for at least 10 ms, though spec only says 5 ms */
+	mmc_delay(10);
 	host->ios.clock = clock;
 	mmc_set_ios(host);