* [PATCH 0/2] vf610: make the USB host port usable
@ 2026-08-19 14:35 Mehmet Fide
2026-08-19 14:35 ` [PATCH 1/2] dm: core: read the device tree into plat data after pinctrl Mehmet Fide
2026-08-19 14:35 ` [PATCH 2/2] usb: ehci-vf: enable the vbus supply of the port Mehmet Fide
0 siblings, 2 replies; 5+ messages in thread
From: Mehmet Fide @ 2026-08-19 14:35 UTC (permalink / raw)
To: Simon Glass, Marek Vasut; +Cc: Tom Rini, u-boot, Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
With the ehci-vf fixes sent so far the controller comes up and
enumerates its root hub, but a device plugged into the host port of a
Colibri VF50 or VF61 carrier is still never found. Two things are
missing.
The driver ignores the vbus-supply of the port, so the regulator that
switches VBUS is never enabled. That is patch 2.
Enabling it is not enough, because the pin the regulator drives never
becomes an output. device_probe() reads the device tree into plat data
before it applies the pinctrl state, so the fixed regulator asks for its
GPIO first and the pinctrl state of the same device then rewrites the
pad. On most SoCs that is harmless, the direction is in the GPIO block,
but on Vybrid the output buffer enable is a bit of that pad. Patch 1
moves the call back below the pinctrl step, where it was until 2019.
I first fixed this in the Vybrid GPIO driver, by asserting the direction
again whenever a value is driven, and dropped that in favour of patch 1:
the driver side does not help a pin that is only ever driven at request
time, and the ordering is the actual defect.
Patch 2 applies on top of
https://lore.kernel.org/u-boot/20260819093705.4143509-1-mehmet.fide@gmail.com/
Testing. test/py on sandbox, before and after patch 1: 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.
On a Colibri VF50 V1.2A on an Iris carrier, U-Boot 2026.07 from NAND:
with both patches "usb start" finds a USB stick, its partition table and
blocks read back, and Linux still boots with Ethernet, SD card and USB
working.
Mehmet Fide (2):
dm: core: read the device tree into plat data after pinctrl
usb: ehci-vf: enable the vbus supply of the port
drivers/core/device.c | 8 ++++----
drivers/usb/host/ehci-vf.c | 31 ++++++++++++++++++++++++++++++-
2 files changed, 34 insertions(+), 5 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] dm: core: read the device tree into plat data after pinctrl
2026-08-19 14:35 [PATCH 0/2] vf610: make the USB host port usable Mehmet Fide
@ 2026-08-19 14:35 ` Mehmet Fide
2026-08-25 12:56 ` Simon Glass
2026-08-19 14:35 ` [PATCH 2/2] usb: ehci-vf: enable the vbus supply of the port Mehmet Fide
1 sibling, 1 reply; 5+ messages in thread
From: Mehmet Fide @ 2026-08-19 14:35 UTC (permalink / raw)
To: Simon Glass, Marek Vasut; +Cc: Tom Rini, u-boot, Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
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 <mehmet.fide@screeningeagle.com>
---
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
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] usb: ehci-vf: enable the vbus supply of the port
2026-08-19 14:35 [PATCH 0/2] vf610: make the USB host port usable Mehmet Fide
2026-08-19 14:35 ` [PATCH 1/2] dm: core: read the device tree into plat data after pinctrl Mehmet Fide
@ 2026-08-19 14:35 ` Mehmet Fide
2026-08-19 19:52 ` Marek Vasut
1 sibling, 1 reply; 5+ messages in thread
From: Mehmet Fide @ 2026-08-19 14:35 UTC (permalink / raw)
To: Simon Glass, Marek Vasut; +Cc: Tom Rini, u-boot, Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
The driver never looks at the vbus-supply of its port, so on a board
where VBUS is switched by a regulator, as it is on the Colibri VF50 and
VF61 carriers, the port stays unpowered and no device is ever found.
Take the regulator the way ehci-mx6 does: look it up in probe, enable it
in host mode and disable it in device mode when the controller comes up,
and turn it off again when the controller is removed.
Tested on a Colibri VF50 V1.2A on an Iris carrier, U-Boot 2026.07 from
NAND, with a USB stick in the host port:
Colibri VFxx # usb start
Bus usb@400b4000: 2 USB Device(s) found
scanning usb for storage devices... 1 Storage Device(s) found
Colibri VFxx # usb storage
Device 0: Vendor: SanDisk Rev: DL17 Prod: SanDisk 3.2 Gen1
Type: Removable Hard Disk
Capacity: 61584.0 MB = 60.1 GB (126124032 x 512)
Reading the partition table and blocks off the stick works.
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
drivers/usb/host/ehci-vf.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index fb305569a15..4ac7f8bf53f 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -21,6 +21,7 @@
#include <asm/mach-imx/regs-usbphy.h>
#include <linux/delay.h>
#include <usb/ehci-ci.h>
+#include <power/regulator.h>
#include <linux/libfdt.h>
#include <fdtdec.h>
@@ -54,6 +55,7 @@ struct ehci_vf_priv_data {
struct anadig_reg __iomem *anatop_addr;
void __iomem *phy_addr;
void __iomem *misc_addr;
+ struct udevice *vbus_supply;
int portnr;
};
@@ -144,6 +146,16 @@ static int ehci_vf_common_init(struct ehci_vf_priv_data *priv)
usb_internal_phy_clock_gate(priv->phy_addr);
usb_phy_enable(priv->phy_addr, priv->ehci);
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->vbus_supply) {
+ ret = regulator_set_enable_if_allowed(priv->vbus_supply,
+ priv->init_type !=
+ USB_INIT_DEVICE);
+ if (ret && ret != -ENOSYS) {
+ printf("Error enabling VBUS supply (ret=%i)\n", ret);
+ return ret;
+ }
+ }
+
return 0;
}
@@ -288,6 +300,13 @@ static int ehci_usb_probe(struct udevice *dev)
struct ehci_hcor *hcor;
int ret;
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
+ ret = device_get_supply_regulator(dev, "vbus-supply",
+ &priv->vbus_supply);
+ if (ret)
+ debug("%s: no vbus supply\n", dev->name);
+ }
+
ret = ehci_vf_common_init(priv);
if (ret)
return ret;
@@ -315,12 +334,22 @@ static const struct udevice_id vf_usb_ids[] = {
{ }
};
+static int ehci_usb_remove(struct udevice *dev)
+{
+ struct ehci_vf_priv_data *priv = dev_get_priv(dev);
+
+ if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->vbus_supply)
+ regulator_set_enable_if_allowed(priv->vbus_supply, false);
+
+ return ehci_deregister(dev);
+}
+
U_BOOT_DRIVER(ehci_vf) = {
.name = "ehci_vf",
.id = UCLASS_USB,
.of_match = vf_usb_ids,
.probe = ehci_usb_probe,
- .remove = ehci_deregister,
+ .remove = ehci_usb_remove,
.ops = &ehci_usb_ops,
.of_to_plat = vf_usb_of_to_plat,
.plat_auto = sizeof(struct usb_plat),
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] usb: ehci-vf: enable the vbus supply of the port
2026-08-19 14:35 ` [PATCH 2/2] usb: ehci-vf: enable the vbus supply of the port Mehmet Fide
@ 2026-08-19 19:52 ` Marek Vasut
0 siblings, 0 replies; 5+ messages in thread
From: Marek Vasut @ 2026-08-19 19:52 UTC (permalink / raw)
To: Mehmet Fide, Simon Glass, Marek Vasut; +Cc: Tom Rini, u-boot, Mehmet Fide
On 8/19/26 4:35 PM, Mehmet Fide wrote:
[...]
> +static int ehci_usb_remove(struct udevice *dev)
> +{
> + struct ehci_vf_priv_data *priv = dev_get_priv(dev);
> +
> + if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->vbus_supply)
> + regulator_set_enable_if_allowed(priv->vbus_supply, false);
The test for DM_REGULATOR being enabled is already in
include/power/regulator.h, regulator_set_enable_if_allowed() will return
-ENOSYS if DM_REGULATOR is disabled. Your implementation has to check
for that, example:
drivers/adc/adc-uclass.c: ret =
regulator_set_enable_if_allowed(uc_pdata->vss_supply, true);
drivers/adc/adc-uclass.c- if (ret && ret != -ENOSYS) {
drivers/adc/adc-uclass.c- pr_err("%s: can't enable
vss-supply!", dev->name);
drivers/adc/adc-uclass.c- return ret;
drivers/adc/adc-uclass.c- }
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] dm: core: read the device tree into plat data after pinctrl
2026-08-19 14:35 ` [PATCH 1/2] dm: core: read the device tree into plat data after pinctrl Mehmet Fide
@ 2026-08-25 12:56 ` Simon Glass
0 siblings, 0 replies; 5+ messages in thread
From: Simon Glass @ 2026-08-25 12:56 UTC (permalink / raw)
To: Mehmet Fide; +Cc: Marek Vasut, Tom Rini, u-boot, Mehmet Fide
Hi Mehmet,
On Wed, 19 Aug 2026 at 08:35, Mehmet Fide <mehmet.fide@gmail.com> wrote:
>
> From: Mehmet Fide <mehmet.fide@screeningeagle.com>
>
> 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 <mehmet.fide@screeningeagle.com>
> ---
> 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
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-25 12:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-19 14:35 [PATCH 0/2] vf610: make the USB host port usable Mehmet Fide
2026-08-19 14:35 ` [PATCH 1/2] dm: core: read the device tree into plat data after pinctrl Mehmet Fide
2026-08-25 12:56 ` Simon Glass
2026-08-19 14:35 ` [PATCH 2/2] usb: ehci-vf: enable the vbus supply of the port Mehmet Fide
2026-08-19 19:52 ` Marek Vasut
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.