What is the best way to control smd_rpm_regulators at runtime?

Hi Everybody,

I am working with some hardware powered off the board’s built in regulator that is being controlled by smd_rpm_regulators in the kernel. I can successfully change voltages and whether or not they are always on or on at boot via the device tree. However, changing the device tree every time I’d like to do this is a bit cumbersome, and I would rather like to do this interactively whilst the board is powered on.

Is this possible? If so is there any sample code out there that would help me to construct an application that I can use to act upon these regulators?

So after some digging through the docs I saw that we can support device tree overlays for things on the i2c bus like the TSYS01 temperature sensor. I am wondering if I could create a dt-overlay that could override the settings for the on board regulators using the smd_rpm_regulators node seen in the parent apq8016-sbc.dtsi device tree file?

Am I going down the right path here?

Hi Rob,

AFAIK, there is no userspace interface to control regulators.
https://elixir.bootlin.com/linux/latest/source/Documentation/power/regulator/overview.txt
https://elixir.bootlin.com/linux/latest/source/Documentation/ABI/testing/sysfs-class-regulator

Device tree is not really designed for dynamic control but is a static description of the hardware.

I would suggest to create a mini platform driver responsible for managing the regulators (regulator consumer).
e.g. https://github.com/torvalds/linux/blob/master/drivers/regulator/userspace-consumer.c

Or try one of the patches that has been already proposed to kernel mailing lists to add control via sysfs:
https://patchwork.kernel.org/patch/9478055/
usage:

echo enabled > /sys/class/regulator/regulator.26/state

Hey Loic,

Thanks for your reply, I went right for that patch that you mentioned. It seems like the guys on the LKML really do not like the idea of userspace controllable regulators… But, I went for it anyway and it applied to my fork of linaro’s 4.14.15 kernel (Located here – https://github.com/RobGries/96b_4.14_kernel/tree/userspace-regulators).

Now It looks like the default regulators (l1 through l18) are not being populated in the sysfs directory /sys/class/regulator/. Do I need to add a directive to the device tree node for the regulator that I would like to control?

You probably needs other patches of the thread (e.g. https://patchwork.kernel.org/patch/9478053/) in order to extract DT properties and allow user-space change for the related regulator. But I suggest you in a first time to just remove the check for userspace_control and allow control unconditionally.

No, I do not explain this, l1 start at /sys/class/regulator/regulator.8 in my case, did you change a kernel config ?

I applied your suggested change to my branch and it seems like it is going further this time, but I now get a stack trace and it seems to be related to line 2300 of drivers/regulator/core.c when it warns about “unbalanced disables for l6”. It appears that the regulator is still enabled after getting the stack trace.

You can view the stack trace here on this gist - https://gist.github.com/RobGries/9380b93af75ac23a7e457f1f739ab484

What exactly is an unbalanced disable on a regulator? I’m unfamiliar with this terminology.

In case of regulator, unbalanced means you’re trying to disable a regulator which has not being enabled previously. Regulator subsystem maintains a counter (use_count) which is incremented each time a ‘consumer’ enable the regulator, several consumers can enable the same regulator. Then regulator needs to be disabled by all consumer (use_count=0) to be physically disabled.

In your case you are trying to disable a regulator which already has use_count=0, the regulator is considered non used. I think you have this problem because L6 is defined with regulator-always-on property in your DT, so no change is expected for this regulator, you can try to remove the prop, I did’nt had a look but there should be a reason to have this regulator ON by the way…