[U-Boot] [RFT 4/8] regulator: Add support for ramp delay
Krzysztof Kozlowski
krzk at kernel.org
Mon Feb 11 08:14:30 UTC 2019
On Sun, 10 Feb 2019 at 10:49, Simon Glass <sjg at chromium.org> wrote:
>
> Hi Krzysztof,
>
> On Sat, 9 Feb 2019 at 16:54, Krzysztof Kozlowski <krzk at kernel.org> wrote:
> >
> > Changing voltage and enabling regulator might require delays so the
> > regulator stabilizes at expected level.
> >
> > Add support for "regulator-ramp-delay" binding which can introduce
> > required time to both enabling the regulator and to changing the
> > voltage.
>
> Is this binding used in Linux? Can you please add binding
> documentation for this?
Yes, these are bindings from the kernel. I will add them.
>
> >
> > Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> > ---
> > drivers/power/regulator/regulator-uclass.c | 45 +++++++++++++++++++++-
> > include/power/regulator.h | 2 +
> > 2 files changed, 45 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
> > index 39e46279d533..4119f244c74b 100644
> > --- a/drivers/power/regulator/regulator-uclass.c
> > +++ b/drivers/power/regulator/regulator-uclass.c
> > @@ -35,10 +35,22 @@ int regulator_get_value(struct udevice *dev)
> > return ops->get_value(dev);
> > }
> >
> > +static void regulator_set_value_delay(struct udevice *dev, int old_uV,
> > + int new_uV, unsigned int ramp_delay)
> > +{
> > + int delay = DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);
>
> So the ramp delay is microseconds per (microvolt delta)?
The ramp delay is microvolt per microseconds.
int delay = uv / (uV/uS) = uS
>
> > +
> > + debug("regulator %s: delay %u us (%d uV -> %d uV)\n", dev->name,
> > + delay, old_uV, new_uV);
> > +
> > + udelay(delay);
> > +}
> > +
> > int regulator_set_value(struct udevice *dev, int uV)
> > {
> > const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> > struct dm_regulator_uclass_platdata *uc_pdata;
> > + int ret, old_uV = uV;
> >
> > uc_pdata = dev_get_uclass_platdata(dev);
> > if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
> > @@ -49,7 +61,18 @@ int regulator_set_value(struct udevice *dev, int uV)
> > if (!ops || !ops->set_value)
> > return -ENOSYS;
> >
> > - return ops->set_value(dev, uV);
> > + if (uc_pdata->ramp_delay)
> > + old_uV = regulator_get_value(dev);
> > +
> > + ret = ops->set_value(dev, uV);
> > +
> > + if (!ret) {
> > + if (uc_pdata->ramp_delay && old_uV > 0)
> > + regulator_set_value_delay(dev, old_uV, uV,
> > + uc_pdata->ramp_delay);
> > + }
> > +
> > + return ret;
> > }
> >
> > /*
> > @@ -107,6 +130,7 @@ int regulator_set_enable(struct udevice *dev, bool enable)
> > {
> > const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
> > struct dm_regulator_uclass_platdata *uc_pdata;
> > + int ret, old_enable = 0;
> >
> > if (!ops || !ops->set_enable)
> > return -ENOSYS;
> > @@ -115,7 +139,22 @@ int regulator_set_enable(struct udevice *dev, bool enable)
> > if (!enable && uc_pdata->always_on)
> > return 0;
> >
> > - return ops->set_enable(dev, enable);
> > + if (uc_pdata->ramp_delay)
> > + old_enable = regulator_get_enable(dev);
> > +
> > + ret = ops->set_enable(dev, enable);
> > + if (!ret) {
> > + if (uc_pdata->ramp_delay && !old_enable) {
> > + int uV = regulator_get_value(dev);
> > +
> > + if (uV > 0) {
> > + regulator_set_value_delay(dev, 0, uV,
> > + uc_pdata->ramp_delay);
> > + }
>
> How come there is a delay when enabling it as well as when setting the voltage?
Enabling a regulator also requires the time, which might be sum of:
1. Initial enable delay (not included here),
2. Rising of voltage delay (ramp delay) from 0 to expected.
In Linux kernel this is separate property regulator-enable-ramp-delay.
Here I reused the ramp delay to make it simpler.
However indeed there is no point to wait with ramp delay if the
regulator is disabled.
>
> > + }
> > + }
> > +
> > + return ret;
> > }
> >
> > int regulator_get_mode(struct udevice *dev)
> > @@ -324,6 +363,8 @@ static int regulator_pre_probe(struct udevice *dev)
> > -ENODATA);
> > uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
> > uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
> > + uc_pdata->ramp_delay = dev_read_u32_default(dev, "regulator-ramp-delay",
> > + 0);
> >
> > /* Those values are optional (-ENODATA if unset) */
> > if ((uc_pdata->min_uV != -ENODATA) &&
> > diff --git a/include/power/regulator.h b/include/power/regulator.h
> > index 5318ab3acece..c13fa1f336e5 100644
> > --- a/include/power/regulator.h
> > +++ b/include/power/regulator.h
> > @@ -149,6 +149,7 @@ enum regulator_flag {
> > * @max_uA* - maximum amperage (micro Amps)
> > * @always_on* - bool type, true or false
> > * @boot_on* - bool type, true or false
> > + * @ramp_delay - Time to settle down after voltage change (unit: uV/us)
>
> us/uV isn't it?
No, opposite.
>
> > * TODO(sjg at chromium.org): Consider putting the above two into @flags
>
> This comment needs updating or moving up.
Yes, thanks!
Best regards,
Krzysztof
More information about the U-Boot
mailing list