[PATCH v5 1/3] regulator: implement basic reference counter

Jonas Karlman jonas at kwiboo.se
Sun Apr 30 20:21:47 CEST 2023


Hi Tim,
On 2023-04-28 18:36, Tim Harvey wrote:
> On Fri, Apr 28, 2023 at 12:39 AM Eugen Hristev
> <eugen.hristev at collabora.com> wrote:
>>
>> On 4/28/23 02:39, Tim Harvey wrote:
>>> On Wed, Apr 19, 2023 at 6:45 AM Eugen Hristev
>>> <eugen.hristev at collabora.com> wrote:
>>>>
>>>> Some devices share a regulator supply, when the first one will request
>>>> regulator disable, the second device will have it's supply cut off before
>>>> graciously shutting down. Hence there will be timeouts and other failed
>>>> operations.
>>>> Implement a reference counter mechanism similar with what is done in
>>>> Linux, to keep track of enable and disable requests, and only disable the
>>>> regulator when the last of the consumers has requested shutdown.
>>>>
>>>> Signed-off-by: Eugen Hristev <eugen.hristev at collabora.com>
>>>> Reviewed-by: Simon Glass <sjg at chromium.org>
>>>> ---
>>>> Changes in v5:
>>>>   - none
>>>> Changes in v4:
>>>>   - add documentation for error codes
>>>> Changes in v3:
>>>>   - add error return codes
>>>> Changes in v2:
>>>>   - add info in header regarding the function
>>>>
>>>>   drivers/power/regulator/regulator_common.c | 22 ++++++++++++++++++++++
>>>>   drivers/power/regulator/regulator_common.h | 21 +++++++++++++++++++++
>>>>   2 files changed, 43 insertions(+)
>>>>
>>>> diff --git a/drivers/power/regulator/regulator_common.c b/drivers/power/regulator/regulator_common.c
>>>> index 93d8196b381e..484a4fc31ef7 100644
>>>> --- a/drivers/power/regulator/regulator_common.c
>>>> +++ b/drivers/power/regulator/regulator_common.c
>>>> @@ -73,6 +73,23 @@ int regulator_common_set_enable(const struct udevice *dev,
>>>>                  return 0;
>>>>          }
>>>>
>>>> +       /* If previously enabled, increase count */
>>>> +       if (enable && dev_pdata->enable_count > 0) {
>>>> +               dev_pdata->enable_count++;
>>>> +               return -EALREADY;
>>>> +       }
>>>> +
>>>> +       if (!enable) {
>>>> +               if (dev_pdata->enable_count > 1) {
>>>> +                       /* If enabled multiple times, decrease count */
>>>> +                       dev_pdata->enable_count--;
>>>> +                       return -EBUSY;
>>>> +               } else if (!dev_pdata->enable_count) {
>>>> +                       /* If already disabled, do nothing */
>>>> +                       return -EALREADY;
>>>> +               }
>>>> +       }
>>>> +
>>>
>>> Eugen,
>>>
>>> Thank you for working on this series!
>>
>> Hi Tim,
>>
>> Thank you for testing and having a look on my patches.
>>>
>>> I wonder if instead of returning a failure you should print an error
>>> here but return 0 in order to not break unbalanced regulator calls
>>
>> Initially I did that, but Simon forced me to return error as you see now.
> 
> Ok, I see that discussion here:
> https://patchwork.ozlabs.org/project/uboot/patch/20230328130127.20279-1-eugen.hristev@collabora.com/#3086660
> 
>>
>>> (like what is done in clk_disable()). I see that you have another
>>> patch in this series which handles htis for
>>> regulator_set_enable_if_allowed() but that doesn't cover drivers that
>>> call regulator_common_set_enable() directly such as
>>> drivers/power/regulator/fixed.c and
>>> drivers/power/regulator/gpio-regulator.c.
>>
>> I believe Jonas (in CC) fixed those with a patch, but at the moment I am
>> lost in providing you a link to it
> 
> Are you thinking of "pci: pcie_dw_rockchip: Use
> regulator_set_enable_if_allowed"
> https://patchwork.ozlabs.org/project/uboot/patch/20230422181943.889436-3-jonas@kwiboo.se/
> ?
> 
> I added some debug prints to regulator_set_enable and see:
> starting USB...
> Bus usb at 32e40000: regulator_set_enable regulator-usb-otg1 enable
> regulator_set_enable regulator-usb-otg1 enable ret=0
> Bus usb at 32e50000: regulator_set_enable regulator-usb-otg2 enable
> regulator_set_enable regulator-usb-otg2 enable ret=0
> regulator_set_enable regulator-usb-otg2 enable
> regulator_set_enable regulator-usb-otg2 enable ret=-114
> Error enabling VBUS supply (ret=-114)
> regulator_set_enable regulator-usb-otg2 disable
> regulator_set_enable regulator-usb-otg2 disable ret=-16
> probe failed, error -114
> 
> So clearly something is trying to enable regulator-usb-otg2 when it's
> already enabled but I don't think that should be considered an error
> and cause a failure.
> 
> Simon, is this what you were intending with your feedback?
> 
>>>
>>> I know there is an unbalanced call currently on imx8mm that this patch
>>> causes a failure where it previously did not:
>>> u-boot=> usb start && usb tree
>>> starting USB...
>>> Bus usb at 32e40000: Bus usb at 32e50000: Error enabling VBUS supply (ret=-114)
>>> probe failed, error -114
>>>
>>
>> That's a good catch.
>> I expected such things would happen if I would return error in those
>> cases, so it might be that this is not the only case.
>> If you are able to test that board, do you wish me to send you a patch
>> that changes the code to using regulator_set_enable_if_allowed() ?
>>
> 
> Yes, I can test. Are you thinking changing the calls to
> regulator_common_set_enable (used in
> drivers/power/regulator/fixed{gpio-regulator,regulator_common} to a
> wrapper calling regulator_common_set_enable_if_allowed instead? I
> think that would just be the same thing as removing the error as no
> callers of that function would be left.

This is nothing that should be changed in the fixed/gpio/common
regulator code. Such change should happen in the drivers that call the
regulator_set_enable function. In your case the usb driver that tries
to enable/disable the regulator.

> 
> Your series solves a necessary issue where a regulator_disable call
> would disable a regulator that was still being used by another
> consumer but I don't think it should break calls to regulator_enable
> just because another consumer is also using it.
> 

With this patch at least fixed/gpio regulators have a basic reference
counter and because of this the regulator_set_enable may now return a
more detailed errno, "0 on success or -errno val if fails".

The call to regulator_set_enable can be replaced with a call to
regulator_set_enable_if_allowed when the caller requires less strict
errors, "0 on success or if enabling is not supported or -errno val if
fails."

Another option could be to also relax the errors returned by
regulator_set_enable, and instead print an error message for the two new
errno.

Regards,
Jonas

> Best Regards,
> 
> Tim



More information about the U-Boot mailing list