11
votes

I'm trying to control (on/off) a voltage regulator that is mapped to a GPIO pin and powers an external device. The device tree for the regulator has the following entry:

    reg_usb1_vbus: usb1_vbus {
        compatible = "regulator-fixed";
        regulator-name = "usb1_vbus";
        regulator-min-microvolt = <5000000>;
        regulator-max-microvolt = <5000000>;
        gpio = <&gpio3 28 0>;
        enable-active-high;
    };

As I read the documentation i got confused for it states:

Optional properties:

  • gpio: gpio to use for enable control

However, I can't export the sysfs interface of that GPIO and use it to control the power supply (just on/off) for the external device. In addition if I comment out the gpio = <&gpio3 28 0>; from the device tree, the external device gets no power (when it isn't commented the device is always powered).

The regulator has a sysfs interface exported:

80090000.usb-vbus      power                  suspend_standby_state
device                 state                  type
microvolts             subsystem              uevent
name                   suspend_disk_state
num_users              suspend_mem_state

however I can't write to any of the files.

What is the correct way to interpret the gpio: entry?

  • gpio to use for enable control

    In which case I'm missing a mapping between a pin on which I want to have the regulator voltage.

  • gpio which will have the voltage from the regulator to power some external unit

    In which case I'm missing a way to turn it on and off

2
The gpio DT entry would presumably be for an enable via HW. Once the driver acquires the specified GPIO for its use, it is no longer unused and you cannot export that GPIO through sysfs anymore. Apparently you're looking for a SW or CLI enable? Search for an existing instance of this GPIO in sysfs that you don't need to export. Look for a SW-controlled enable using an ioctl() call in the driver. Worst case would be to connect another GPIO to this HW enable?.sawdust
@sawdust Once the driver acquires the specified GPIO for its use That's what I'm trying to understand what is the directive for achieving this. The device tree documentations states gpio: gpio to use for enable control but I'm experiencing it as the directive to map the regulator with a GPIO pin.TheMeaningfulEngineer
It's a matter of resource allocation. Just like memory is allocated and freed, so are GPIO pins. Check the driver for this regulator. It probably retrieves the DT entry for its GPIO with a call to of_get_gpio() or of_property_read_u32(). The value is typically tested with gpio_is_valid(), and then it's allocated with gpio_request(). When you export a GPIO using sysfs, sysfs has to (try to) acquire the pin. What is in sysfs for this regulator, e.g. under /sys/class/regulator?sawdust
@sawdust Yes I'm experiencing that the driver is acquiring the GPIO and that's why it can't be exported through sysfs. Am I misinterpreting the documentation? I would interpret gpio to use for enable control as the GPIO pin with which i can control the regulator and not a pin on which the regulator output will be mapped.TheMeaningfulEngineer
I assume the former, that it's a GPIO to enable or disable the regulator. But then it is no longer a General Purpose I/O pin. It's now a specific-purpose pin, i.e. a regulator enable pin, owned by the driver. So you cannot try to use the sysfs interface for GPIO. But there's other interfaces in sysfs, such as regulators.sawdust

2 Answers

8
votes

I'm trying to control (on/off) a voltage regulator that is mapped to a GPIO pin and powers an external device.
...

What is the correct way to interpret the gpio: entry?

Seems like you're asking an XY question.
First the Y part regarding the GPIO.

The gpio DT entry you refer to would be for an enable/disable control by the regulator framework. It is intended for exclusive use by the regulator driver to control the (external?) regulator hardware. It is not intended for software control of the regulator outside the framework by the user (as you are trying to do).

This GPIO is defined as an output in drivers/regulator/core.c:

 static int regulator_ena_gpio_request(struct regulator_dev *rdev,
                                 const struct regulator_config *config)
 {
        ...
         ret = gpio_request_one(config->ena_gpio,
                                 GPIOF_DIR_OUT | config->ena_gpio_flags,
                                 rdev_get_name(rdev));
         ...
 }

The GPIO pin is not read for "enable control", but has its value set in regulator_ena_gpio_ctrl() in order to actively enable or disable the (external) regulator.

The inablity to export the same GPIO pin using sysfs when that pin is also declared in the Device Tree is easily explained. Once the driver acquires the specified GPIO for its use (through the DT), it is no longer unused, and you cannot export that GPIO through sysfs anymore. GPIOs are a managed resource, and need to be allocated and freed (by a driver or sysfs) just like any other resource such as memory. If you were able to export this GPIO that was also used by the driver, then you would be able to put the GPIO into a state that was inconsistent with what the driver was doing. That in turn would lead to an unstable or misbehaving code.

In which case I'm missing a mapping between a pin on which I want to have the regulator voltage.

The GPIO pin specified in the Device Tree is a logic (i.e. digital) output. It is not the regulator output, which would be an analog output.

You should consult the schematic for your board to confirm that this GPIO is connected to a control input of a regulator.


As to the X part regarding enabling/disabling the regulator:

Software control of the regulator's output is documented in Documentation/power/regulator/consumer.txt

A consumer driver can get access to its supply regulator by calling :-

regulator = regulator_get(dev, "Vcc");

A consumer can enable its power supply by calling:-

int regulator_enable(regulator);

A consumer can disable its supply when no longer needed by calling :-

int regulator_disable(regulator);

The 'consumer" is an electronic device that is supplied power by a regulator.

Apparently the intended framework is have the "consumer driver" own and control its regulator, and not allow an external interface (e.g. sysfs) to interfere with this "consumer driver". If you insist on having userland control, then you could implement an ioctl() or sysfs interface to the "consumer driver" (to avoid conflict/contention with the regulator driver).

In which case I'm missing a way to turn it on and off

What you're really looking for seems to be (upper-layer) power management, and that has its own framework, of which regulators is a lower layer (which is normally not accessible for user control). You should study Documentation/power/devices.txt.

0
votes

I am not extremely familiar with the regulator core in the kernel, but it seems to me that the regulator interface needs to give you access to the GPIO in a different way than the standad export GPIO method.

I have not looked into this, but it is possible the the regulator interface opens up a character device to userspace for control over the regulator. (Don't hold me to that)

I do see in the documentation and in the driver source code drivers/regulator/fixed.c that the GPIO is not a required DT attribute. You might be able to leave it out of the DT in which case the Driver will never acquire your GPIO, then you can manually control it through the standard export GPIO interface.