Re: [PATCH 1/2] dm: core: read the device tree into plat data after pinctrl
Simon Glass <[email protected]>
| Newsgroups | org.u-boot-project.lists.u-boot |
|---|---|
| Message-ID | <CAFLszTh924Zt-a7bJAQaSXHhi+MGrT6-0UTsyt-P7s5DD3bw4w@mail.gmail.com> |
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