Hi Mehmet,

On Wed, 19 Aug 2026 at 08:35, Mehmet Fide <[email protected]> wrote:
>
> From: Mehmet Fide <[email protected]>
>
> device_probe() calls device_of_to_plat() before it applies the "default"
> pinctrl state of the device, so a driver that acquires resources there
> sees them undone by the pinctrl state that follows.
>
> It has not always been that way. When the pinctrl uclass arrived in
> commit d90a5a30dec1 ("pinctrl: add pin control uclass support") the
> state was selected before ->ofdata_to_platdata() was called, and it
> stayed that way for four years. Commit 29f7d05a347a ("dm: core: Move
> ofdata_to_platdata() call earlier") then moved the call up so that the
> platform data would be read before the device is probed, which is
> reasonable in itself, but it also moved it above the pinctrl state,
> which nothing asked for.
>
> GPIOs are where this hurts. On most SoCs the direction of a pin lives in
> the GPIO block, so a pinctrl state cannot disturb it, but on Vybrid the
> output buffer enable is a bit of the pad register that pinctrl writes as
> well. A fixed regulator asks for its enable GPIO in of_to_plat(), so the
> pin is configured as an output and the pinctrl state of the same device
> then turns it back into an input. The USB host VBUS regulator of a
> Colibri VF50 is one of those: its pad reads 0x22ed once the regulator
> has been probed, the value from the device tree, output buffer disabled,
> and no USB device is ever powered.
>
> Move the call back below the pinctrl step. That is also the order Linux
> uses, and the order the board code of these boards used before the
> driver model: set the pin muxing up first, then take the pin. The
> pinctrl step itself cannot move up instead, because it relies on
> DM_FLAG_ACTIVATED having been set to break the recursion described above
> it.
>
> Nothing between the two positions needs plat data: the parent probe, the
> power domain and the pinctrl call all work off the device tree.
>
> Tested with test/py on sandbox, before and after: 11 failed, 414 passed,
> 210 skipped, 1 xfailed, 20 errors, the same failures both times, all of
> them from tools and images missing in my environment.
>
> Tested on a Colibri VF50 V1.2A on an Iris carrier, U-Boot 2026.07 from
> NAND: the pad of the VBUS pin reads 0x22ef after "usb start" instead of
> 0x22ed, a USB stick in the host port enumerates, and Linux still boots
> with Ethernet, SD card and USB working.
>
> Fixes: 29f7d05a347a ("dm: core: Move ofdata_to_platdata() call earlier")
> Signed-off-by: Mehmet Fide <[email protected]>
> ---
>  drivers/core/device.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/core/device.c b/drivers/core/device.c
> index 6024534ff93..ccdf0ab9220 100644
> --- a/drivers/core/device.c
> +++ b/drivers/core/device.c
> @@ -500,10 +500,6 @@ int device_probe(struct udevice *dev)
>         drv = dev->driver;
>         assert(drv);
>
> -       ret = device_of_to_plat(dev);
> -       if (ret)
> -               goto fail;
> -
>         /* Ensure all parents are probed */
>         if (dev->parent) {
>                 ret = device_probe(dev->parent);
> @@ -552,6 +548,10 @@ int device_probe(struct udevice *dev)
>                                   dev->name, ret, errno_str(ret));
>         }
>
> +       ret = device_of_to_plat(dev);
> +       if (ret)
> +               goto fail;
> +
>         if (CONFIG_IS_ENABLED(IOMMU) && dev->parent &&
>             (device_get_uclass_id(dev) != UCLASS_IOMMU)) {
>                 ret = dev_iommu_enable(dev);
> --
> 2.54.0
>

Firstly, we are going to need a sandbox test for this, preferably one
that gets a GPIO in the regulator, as you mention here (i.e. calls
regulator_common_of_to_plat()).

The problem is the grey area of what is supposed to be done in
of_to_plat(). The doc section is at [1] and perhaps it should be more
explicit. We really should not be probing devices in of_to_plat(). The
idea is to read from the device tree and store that information in the
plat data. Then it gets used during probe().

As to substance, I believe the 2019 change is correct - of_plat is a
phase separate to and before probe. There should be no need to probe a
parent in order to read a child's platdata.

So perhaps what is needed here is clearly documentation about what
should and should not be done in of_to_plat() and in particular a
function to read the GPIO info without actually requesting the GPIO,
so generic functions like regulator_common_of_to_plat() can do the
right thing.

Regards,
Simon

[1] 
https://docs.u-boot-project.org/en/latest/develop/driver-model/design.html#reading-ofdata

Reply via email to