Re: [PATCH v3 1/5] regulator: Allow regulators to verify enabled during enable()

From: Bjorn Andersson
Date: Thu May 28 2020 - 21:41:06 EST


On Thu 28 May 08:46 PDT 2020, Sumit Semwal wrote:

> Some regulators might need to verify that they have indeed been enabled
> after the enable() call is made and enable_time delay has passed.
>
> This is implemented by repeatedly checking is_enabled() upto
> poll_enabled_time, waiting for the already calculated enable delay in
> each iteration.
>
> Signed-off-by: Sumit Semwal <sumit.semwal@xxxxxxxxxx>
> ---
> drivers/regulator/core.c | 28 ++++++++++++++++++++++++++++
> include/linux/regulator/driver.h | 5 +++++
> 2 files changed, 33 insertions(+)
>
> diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
> index 7486f6e4e613..06199f182114 100644
> --- a/drivers/regulator/core.c
> +++ b/drivers/regulator/core.c
> @@ -2409,6 +2409,34 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
>
> _regulator_enable_delay(delay);

My interpretation of "enable_time" (i.e. the value of delay) is that it
denotes the maximum time it will take for the regulator to turn on, and
the purpose of this patch is to be able to handle cases where we can
poll the hardware to see if it completed earlier.

So I think you should flip the meaning of your two variables around,
making "delay" the total time to sleep and the newly introduced
"poll_enabled_time" the interval at which you check if the hardware
finished early.

Regards,
Bjorn

>
> + /* If set, poll upto poll_enabled_time uS to see if the regulator
> + * actually got enabled.
> + * For each iteration, wait for the enable_time delay calculated
> + * above already.
> + * If the regulator isn't enabled after poll_enabled_time has
> + * expired, return -ETIMEDOUT.
> + */
> + if (rdev->desc->poll_enabled_time) {
> + unsigned int time_remaining = rdev->desc->poll_enabled_time;
> +
> + while (time_remaining > 0) {
> + /* We've already waited for enable_time above;
> + * so we can start with immediate check of the
> + * status of the regulator.
> + */
> + if (rdev->desc->ops->is_enabled(rdev))
> + break;
> +
> + _regulator_enable_delay(delay);
> + time_remaining -= delay;
> + }
> +
> + if (time_remaining <= 0) {
> + rdev_err(rdev, "Enabled check failed.\n");
> + return -ETIMEDOUT;
> + }
> + }
> +
> trace_regulator_enable_complete(rdev_get_name(rdev));
>
> return 0;
> diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
> index 29d920516e0b..bb50e943010f 100644
> --- a/include/linux/regulator/driver.h
> +++ b/include/linux/regulator/driver.h
> @@ -322,6 +322,9 @@ enum regulator_type {
> * @enable_time: Time taken for initial enable of regulator (in uS).
> * @off_on_delay: guard time (in uS), before re-enabling a regulator
> *
> + * @poll_enabled_time: Maximum time (in uS) to poll if the regulator is
> + * actually enabled, after enable() call
> + *
> * @of_map_mode: Maps a hardware mode defined in a DeviceTree to a standard mode
> */
> struct regulator_desc {
> @@ -389,6 +392,8 @@ struct regulator_desc {
>
> unsigned int off_on_delay;
>
> + unsigned int poll_enabled_time;
> +
> unsigned int (*of_map_mode)(unsigned int mode);
> };
>
> --
> 2.26.2
>