* [PATCH v4 0/6] usb: ehci-vf: make the USB host port usable
@ 2026-10-07 14:45 Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 1/6] usb: ehci-vf: take the controller index from the device tree Mehmet Fide
` (5 more replies)
0 siblings, 6 replies; 10+ messages in thread
From: Mehmet Fide @ 2026-10-07 14:45 UTC (permalink / raw)
To: Marek Vasut, Simon Glass
Cc: Tom Rini, Fabio Estevam, Stefan Agner, Francesco Dolcini, u-boot,
Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
"usb start" on a Colibri VF50 or VF61 kills U-Boot with a data abort,
and even with that fixed the host port stays unpowered. This series
brings the two threads sent in August together on top of next, where
the regulator GPIO change they waited for has landed:
- patch 1 fixes the data abort: the controller index came from a
sequence number that the usbphy aliases push past the driver's tables
- patches 2 to 5 drop the dead non-DM path and the empty bind hook,
add ofnode_get_alias_seq() and take the PHY, usbmisc and anatop bases
from the device tree instead of the tables
- patch 6 enables the vbus-supply of the port
Patches 2 to 5 are the follow-up Marek asked for in his review of
patch 1: the PHY and usbmisc tables are gone, and the port index that
is left, for board_ehci_hcd_init() and the anatop registers, comes
from the alias of the PHY node.
v4:
- rebased on next; the dm core change that moved of_to_plat() after
pinctrl is gone, the regulator GPIO is now claimed at probe time
upstream ("gpio: add a way to parse a GPIO now and request it later"
and its users), which is what the vbus patch needed
- the data abort fix joins the series as patch 1, the register base
patch depends on it
- the checkpatch warnings in patch 4 are in the body it moves, which is
unchanged; its one check is the DM_TEST layout every test in
test/dm/ofnode.c uses
- patch 6 enables VBUS in the reset hook only, as ehci-mx6 does; v3
enabled it there and in the shared init, so the regulator counted two
enables per probe and "usb stop" never switched VBUS off
- patch 4 gains a test and no longer documents -ENOENT for a missing
alias, the live tree returns -ENODEV
- patch 5 drops two comments that repeated its commit message
- reworded the commit messages of patches 1, 5 and 6
v2 of the register base series:
https://lore.kernel.org/u-boot/20260820071511.1036506-1-mehmet.fide@gmail.com/
v3 of the vbus series:
https://lore.kernel.org/u-boot/20260820102523.1076815-1-mehmet.fide@gmail.com/
the data abort fix:
https://lore.kernel.org/u-boot/20260818151236.2891878-1-mehmet.fide@gmail.com/
Tested on a Colibri VF50 V1.2A on the Iris carrier, colibri_vf_defconfig
on next (ed869863c7e): "usb start" finds a USB stick behind the host
port at usb@400b4000 and reads the same data before and after
"usb reset", VBUS goes on at "usb start" and off at "usb stop", also
after repeated resets, and Linux takes the port over when U-Boot boots
it without "usb stop". An earlier build also brought up the host port
on a Colibri VF61 V1.2B. The five ARCH_VF610 boards build at every
patch, and "ut dm" on sandbox gives the same result as on next, plus
the new test on the live and the flat tree.
Mehmet Fide (6):
usb: ehci-vf: take the controller index from the device tree
usb: ehci-vf: remove the code path for a build without DM_USB
usb: ehci-vf: drop the empty bind hook
dm: core: add ofnode_get_alias_seq()
usb: ehci-vf: take the register bases from the device tree
usb: ehci-vf: enable the vbus supply of the port
drivers/core/ofnode.c | 20 ++++
drivers/core/read.c | 20 +---
drivers/usb/host/ehci-vf.c | 187 +++++++++++++++++--------------------
include/dm/ofnode.h | 13 +++
include/dm/read.h | 8 +-
test/dm/ofnode.c | 20 ++++
6 files changed, 144 insertions(+), 124 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4 1/6] usb: ehci-vf: take the controller index from the device tree
2026-10-07 14:45 [PATCH v4 0/6] usb: ehci-vf: make the USB host port usable Mehmet Fide
@ 2026-10-07 14:45 ` Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 2/6] usb: ehci-vf: remove the code path for a build without DM_USB Mehmet Fide
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Mehmet Fide @ 2026-10-07 14:45 UTC (permalink / raw)
To: Marek Vasut, Simon Glass
Cc: Tom Rini, Fabio Estevam, Stefan Agner, Francesco Dolcini, u-boot,
Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
"usb start" on a Colibri VF50 or VF61 ends in a data abort and a
watchdog reset.
vf_usb_of_to_plat() takes the controller index from dev_seq(), but the
usbphy0 and usbphy1 aliases count as "usb" aliases when the uclass
numbers its devices, so the two controllers get 2 and 3 and index past
the two entries of phy_bases[] and nc_reg_bases[]. usb_oc_config() then
writes through an address read from beyond the table.
Follow the fsl,usbphy phandle, as ehci-mx6 does, and map the PHY node to
the index of the table instead of trusting the sequence number.
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
Changes in v4:
- sent alone before, now patch 1 of the series
- reworded the commit message, no code change
- the test note moved here: on a Colibri VF50 V1.2A on an Iris carrier,
"usb start" brings up the controller instead of resetting the board
drivers/usb/host/ehci-vf.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 96d1363a76e..32fe05920d0 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -221,8 +221,23 @@ static int vf_usb_of_to_plat(struct udevice *dev)
const void *dt_blob = gd->fdt_blob;
int node = dev_of_offset(dev);
const char *mode;
+ fdt_addr_t phy_addr;
+ ofnode phy_node;
+ int i;
- priv->portnr = dev_seq(dev);
+ phy_node = ofnode_parse_phandle(dev_ofnode(dev), "fsl,usbphy", 0);
+ if (!ofnode_valid(phy_node))
+ return -EINVAL;
+
+ phy_addr = ofnode_get_addr(phy_node);
+ for (i = 0; i < ARRAY_SIZE(phy_bases); i++) {
+ if (phy_addr == phy_bases[i])
+ break;
+ }
+ if (i == ARRAY_SIZE(phy_bases))
+ return -EINVAL;
+
+ priv->portnr = i;
priv->ehci = dev_read_addr_ptr(dev);
mode = fdt_getprop(dt_blob, node, "dr_mode", NULL);
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 2/6] usb: ehci-vf: remove the code path for a build without DM_USB
2026-10-07 14:45 [PATCH v4 0/6] usb: ehci-vf: make the USB host port usable Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 1/6] usb: ehci-vf: take the controller index from the device tree Mehmet Fide
@ 2026-10-07 14:45 ` Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 3/6] usb: ehci-vf: drop the empty bind hook Mehmet Fide
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Mehmet Fide @ 2026-10-07 14:45 UTC (permalink / raw)
To: Marek Vasut, Simon Glass
Cc: Tom Rini, Fabio Estevam, Stefan Agner, Francesco Dolcini, u-boot,
Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
USB_EHCI_HCD selects DM_USB, so the !CONFIG_IS_ENABLED(DM_USB) branch of
this driver can never be selected. It also cannot compile: ehci_hcd_init()
calls ehci_vf_common_init() with one argument while the function takes
two, so the branch has been dead since the controller was added as a
second parameter.
Remove it, together with the board_usb_phy_mode() hook that no board
implements and nothing else calls.
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
Changes in v4:
- none, rebased on next
drivers/usb/host/ehci-vf.c | 49 --------------------------------------
1 file changed, 49 deletions(-)
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 32fe05920d0..5d27318de62 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -128,11 +128,6 @@ static void usb_oc_config(int index)
setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
}
-int __weak board_usb_phy_mode(int port)
-{
- return 0;
-}
-
int __weak board_ehci_hcd_init(int port)
{
return 0;
@@ -155,49 +150,6 @@ int ehci_vf_common_init(struct usb_ehci *ehci, int index)
return 0;
}
-#if !CONFIG_IS_ENABLED(DM_USB)
-int ehci_hcd_init(int index, enum usb_init_type init,
- struct ehci_hccr **hccr, struct ehci_hcor **hcor)
-{
- struct usb_ehci *ehci;
- enum usb_init_type type;
- int ret;
-
- if (index >= ARRAY_SIZE(nc_reg_bases))
- return -EINVAL;
-
- ehci = (struct usb_ehci *)nc_reg_bases[index];
-
- ret = ehci_vf_common_init(index);
- if (ret)
- return ret;
-
- *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
- *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
- HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
-
- type = board_usb_phy_mode(index);
- if (type != init)
- return -ENODEV;
-
- if (init == USB_INIT_DEVICE) {
- setbits_le32(&ehci->usbmode, CM_DEVICE);
- writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
- setbits_le32(&ehci->portsc, USB_EN);
- } else if (init == USB_INIT_HOST) {
- setbits_le32(&ehci->usbmode, CM_HOST);
- writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
- setbits_le32(&ehci->portsc, USB_EN);
- }
-
- return 0;
-}
-
-int ehci_hcd_stop(int index)
-{
- return 0;
-}
-#else
/* Possible port types (dual role mode) */
enum dr_mode {
DR_MODE_NONE = 0,
@@ -372,4 +324,3 @@ U_BOOT_DRIVER(ehci_vf) = {
.priv_auto = sizeof(struct ehci_vf_priv_data),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
-#endif
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 3/6] usb: ehci-vf: drop the empty bind hook
2026-10-07 14:45 [PATCH v4 0/6] usb: ehci-vf: make the USB host port usable Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 1/6] usb: ehci-vf: take the controller index from the device tree Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 2/6] usb: ehci-vf: remove the code path for a build without DM_USB Mehmet Fide
@ 2026-10-07 14:45 ` Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 4/6] dm: core: add ofnode_get_alias_seq() Mehmet Fide
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Mehmet Fide @ 2026-10-07 14:45 UTC (permalink / raw)
To: Marek Vasut, Simon Glass
Cc: Tom Rini, Fabio Estevam, Stefan Agner, Francesco Dolcini, u-boot,
Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
vf_usb_bind() only returns 0. Its comment describes a hack that keeps
the second controller from taking sequence number 0, but no such code
is there, and an empty .bind cannot influence the numbering the uclass
does. Remove it.
Fixes: 0885cdb9d154 ("usb: host: ehci-vf: Migrate Vybrid USB to driver model")
Fixes: b27347f425f7 ("usb: Update for new sequence numbers")
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
Changes in v4:
- none, rebased on next
drivers/usb/host/ehci-vf.c | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 5d27318de62..e5f9ec0fdbb 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -261,20 +261,6 @@ static const struct ehci_ops vf_ehci_ops = {
.init_after_reset = vf_init_after_reset
};
-static int vf_usb_bind(struct udevice *dev)
-{
- /*
- * Without this hack, if we return ENODEV for USB Controller 0, on
- * probe for the next controller, USB Controller 1 will be given a
- * sequence number of 0. This conflicts with our requirement of
- * sequence numbers while initialising the peripherals.
- *
- * FIXME: Check that this still works OK with the new sequence numbers
- */
-
- return 0;
-}
-
static int ehci_usb_probe(struct udevice *dev)
{
struct usb_plat *plat = dev_get_plat(dev);
@@ -315,7 +301,6 @@ U_BOOT_DRIVER(ehci_vf) = {
.name = "ehci_vf",
.id = UCLASS_USB,
.of_match = vf_usb_ids,
- .bind = vf_usb_bind,
.probe = ehci_usb_probe,
.remove = ehci_deregister,
.ops = &ehci_usb_ops,
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 4/6] dm: core: add ofnode_get_alias_seq()
2026-10-07 14:45 [PATCH v4 0/6] usb: ehci-vf: make the USB host port usable Mehmet Fide
` (2 preceding siblings ...)
2026-10-07 14:45 ` [PATCH v4 3/6] usb: ehci-vf: drop the empty bind hook Mehmet Fide
@ 2026-10-07 14:45 ` Mehmet Fide
2026-10-09 6:47 ` Simon Glass
2026-10-07 14:45 ` [PATCH v4 5/6] usb: ehci-vf: take the register bases from the device tree Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 6/6] usb: ehci-vf: enable the vbus supply of the port Mehmet Fide
5 siblings, 1 reply; 10+ messages in thread
From: Mehmet Fide @ 2026-10-07 14:45 UTC (permalink / raw)
To: Marek Vasut, Simon Glass
Cc: Tom Rini, Fabio Estevam, Stefan Agner, Francesco Dolcini, u-boot,
Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
The sequence number an aliases entry gives a node can only be looked up
for a device, through dev_read_alias_seq(). A driver that has to know
the number of a node it does not own, one it reached through a phandle
for instance, has no livetree call for it and is left with fdtdec.
Move the body of dev_read_alias_seq() to the ofnode level and let both
of its variants call it. No functional change, so the moved lines keep
the ENOTSUPP return, the #if and the fdtdec call they had, which is what
checkpatch complains about here.
A test checks the lookup on the live and on the flat tree.
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
Changes in v4:
- added a test, run on the live and on the flat tree
- the kernel-doc no longer promises -ENOENT for a missing alias, the
live tree returns -ENODEV
drivers/core/ofnode.c | 20 ++++++++++++++++++++
drivers/core/read.c | 20 ++------------------
include/dm/ofnode.h | 13 +++++++++++++
include/dm/read.h | 8 ++------
test/dm/ofnode.c | 20 ++++++++++++++++++++
5 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index b5d13c43db1..81d91ce5476 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -1233,6 +1233,26 @@ ofnode ofnode_get_aliases_node(const char *name)
return ofnode_path(prop);
}
+int ofnode_get_alias_seq(ofnode node, const char *stem, int *seqp)
+{
+ int ret = -ENOTSUPP;
+
+ if (ofnode_is_np(node)) {
+ ret = of_alias_get_id(ofnode_to_np(node), stem);
+ if (ret >= 0) {
+ *seqp = ret;
+ ret = 0;
+ }
+ } else {
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+ ret = fdtdec_get_alias_seq(ofnode_to_fdt(node), stem,
+ ofnode_to_offset(node), seqp);
+#endif
+ }
+
+ return ret;
+}
+
int ofnode_get_child_count(ofnode parent)
{
ofnode child;
diff --git a/drivers/core/read.c b/drivers/core/read.c
index ba48862f44b..985f6128d97 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -356,24 +356,8 @@ const void *dev_read_prop_by_prop(struct ofprop *prop,
int dev_read_alias_seq(const struct udevice *dev, int *devnump)
{
- ofnode node = dev_ofnode(dev);
- const char *uc_name = dev->uclass->uc_drv->name;
- int ret = -ENOTSUPP;
-
- if (ofnode_is_np(node)) {
- ret = of_alias_get_id(ofnode_to_np(node), uc_name);
- if (ret >= 0) {
- *devnump = ret;
- ret = 0;
- }
- } else {
-#if CONFIG_IS_ENABLED(OF_CONTROL)
- ret = fdtdec_get_alias_seq(gd->fdt_blob, uc_name,
- ofnode_to_offset(node), devnump);
-#endif
- }
-
- return ret;
+ return ofnode_get_alias_seq(dev_ofnode(dev),
+ dev->uclass->uc_drv->name, devnump);
}
int dev_read_u32_array(const struct udevice *dev, const char *propname,
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index c905e86b283..e13271a824f 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -1180,6 +1180,19 @@ const void *ofnode_read_aliases_prop(const char *propname, int *sizep);
*/
ofnode ofnode_get_aliases_node(const char *propname);
+/**
+ * ofnode_get_alias_seq() - get the sequence number of a node from its alias
+ *
+ * The aliases node can name a node with a stem and a number, such as
+ * "serial2". This looks the node up and returns the number.
+ *
+ * @node: Node to look for
+ * @stem: Alias stem, e.g. "serial"
+ * @seqp: Returns the sequence number of the alias, if found
+ * Return: 0 if a sequence number was found, -ve if not
+ */
+int ofnode_get_alias_seq(ofnode node, const char *stem, int *seqp);
+
struct display_timing;
/**
* ofnode_decode_display_timing() - decode display timings
diff --git a/include/dm/read.h b/include/dm/read.h
index 12dcde6645c..d0c17c3d343 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -1168,12 +1168,8 @@ static inline const void *dev_read_prop_by_prop(struct ofprop *prop,
static inline int dev_read_alias_seq(const struct udevice *dev, int *devnump)
{
-#if CONFIG_IS_ENABLED(OF_CONTROL)
- return fdtdec_get_alias_seq(gd->fdt_blob, dev->uclass->uc_drv->name,
- dev_of_offset(dev), devnump);
-#else
- return -ENOTSUPP;
-#endif
+ return ofnode_get_alias_seq(dev_ofnode(dev),
+ dev->uclass->uc_drv->name, devnump);
}
static inline int dev_read_u32_array(const struct udevice *dev,
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index 0f60c2a6281..07c1965dd34 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -523,6 +523,26 @@ static int dm_test_ofnode_read_aliases(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_read_aliases, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+/* test ofnode_get_alias_seq() */
+static int dm_test_ofnode_get_alias_seq(struct unit_test_state *uts)
+{
+ int seq;
+
+ ut_assertok(ofnode_get_alias_seq(ofnode_path("/i2c@0"), "i2c", &seq));
+ ut_asserteq(0, seq);
+
+ ut_assertok(ofnode_get_alias_seq(ofnode_path("/some-bus/c-test@1"),
+ "testfdt", &seq));
+ ut_asserteq(12, seq);
+
+ ut_assert(ofnode_get_alias_seq(ofnode_path("/i2c@0"), "spi", &seq) < 0);
+ ut_assert(ofnode_get_alias_seq(ofnode_path("/some-bus"), "testfdt",
+ &seq) < 0);
+
+ return 0;
+}
+DM_TEST(dm_test_ofnode_get_alias_seq, UTF_SCAN_FDT);
+
static int dm_test_ofnode_get_child_count(struct unit_test_state *uts)
{
ofnode node, child_node;
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 5/6] usb: ehci-vf: take the register bases from the device tree
2026-10-07 14:45 [PATCH v4 0/6] usb: ehci-vf: make the USB host port usable Mehmet Fide
` (3 preceding siblings ...)
2026-10-07 14:45 ` [PATCH v4 4/6] dm: core: add ofnode_get_alias_seq() Mehmet Fide
@ 2026-10-07 14:45 ` Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 6/6] usb: ehci-vf: enable the vbus supply of the port Mehmet Fide
5 siblings, 0 replies; 10+ messages in thread
From: Mehmet Fide @ 2026-10-07 14:45 UTC (permalink / raw)
To: Marek Vasut, Simon Glass
Cc: Tom Rini, Fabio Estevam, Stefan Agner, Francesco Dolcini, u-boot,
Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
The driver keeps its own tables of PHY and controller base addresses
and reaches the anatop block through a hardcoded address, although the
device tree describes all three: the controller points at its PHY and
usbmisc nodes, and the PHY at its anatop.
Read them from there and drop the tables. The port number stays only
for the choice between PLL3 and PLL7, which the device tree does not
express, and now comes from the alias of the PHY node.
The usbmisc node already starts at the non-core registers, so the
driver no longer adds an offset to reach them.
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
Changes in v4:
- rebased on next
- dropped two comments that repeated the commit message
- reworded the commit message and took the note on the previous version
out of it
drivers/usb/host/ehci-vf.c | 135 ++++++++++++++++++++-----------------
1 file changed, 72 insertions(+), 63 deletions(-)
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index e5f9ec0fdbb..b1cfad14b09 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -22,12 +22,9 @@
#include <linux/delay.h>
#include <usb/ehci-ci.h>
#include <linux/libfdt.h>
-#include <fdtdec.h>
#include "ehci.h"
-#define USB_NC_REG_OFFSET 0x00000800
-
#define ANADIG_PLL_CTRL_EN_USB_CLKS (1 << 6)
#define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */
@@ -39,28 +36,33 @@
DECLARE_GLOBAL_DATA_PTR;
-static const unsigned phy_bases[] = {
- USB_PHY0_BASE_ADDR,
- USB_PHY1_BASE_ADDR,
+/* Possible port types (dual role mode) */
+enum dr_mode {
+ DR_MODE_NONE = 0,
+ DR_MODE_HOST, /* supports host operation */
+ DR_MODE_DEVICE, /* supports device operation */
+ DR_MODE_OTG, /* supports both */
};
-static const unsigned nc_reg_bases[] = {
- USBC0_BASE_ADDR,
- USBC1_BASE_ADDR,
+struct ehci_vf_priv_data {
+ struct ehci_ctrl ctrl;
+ struct usb_ehci *ehci;
+ struct gpio_desc cdet_gpio;
+ enum usb_init_type init_type;
+ enum dr_mode dr_mode;
+ struct anadig_reg __iomem *anatop_addr;
+ void __iomem *phy_addr;
+ void __iomem *misc_addr;
+ int portnr;
};
-static void usb_internal_phy_clock_gate(int index)
+static void usb_internal_phy_clock_gate(void __iomem *phy_reg)
{
- void __iomem *phy_reg;
-
- phy_reg = (void __iomem *)phy_bases[index];
clrbits_le32(phy_reg + USBPHY_CTRL, USBPHY_CTRL_CLKGATE);
}
-static void usb_power_config(int index)
+static void usb_power_config(struct anadig_reg __iomem *anadig, int index)
{
- struct anadig_reg __iomem *anadig =
- (struct anadig_reg __iomem *)ANADIG_BASE_ADDR;
void __iomem *pll_ctrl;
switch (index) {
@@ -83,13 +85,11 @@ static void usb_power_config(int index)
}
}
-static void usb_phy_enable(int index, struct usb_ehci *ehci)
+static void usb_phy_enable(void __iomem *phy_reg, struct usb_ehci *ehci)
{
- void __iomem *phy_reg;
void __iomem *phy_ctrl;
void __iomem *usb_cmd;
- phy_reg = (void __iomem *)phy_bases[index];
phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
usb_cmd = (void __iomem *)&ehci->usbcmd;
@@ -118,12 +118,8 @@ static void usb_phy_enable(int index, struct usb_ehci *ehci)
USBPHY_CTRL_ENUTMILEVEL3);
}
-static void usb_oc_config(int index)
+static void usb_oc_config(void __iomem *ctrl)
{
- void __iomem *ctrl;
-
- ctrl = (void __iomem *)(nc_reg_bases[index] + USB_NC_REG_OFFSET);
-
setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
}
@@ -133,63 +129,76 @@ int __weak board_ehci_hcd_init(int port)
return 0;
}
-int ehci_vf_common_init(struct usb_ehci *ehci, int index)
+static int ehci_vf_common_init(struct ehci_vf_priv_data *priv)
{
int ret;
/* Do board specific initialisation */
- ret = board_ehci_hcd_init(index);
+ ret = board_ehci_hcd_init(priv->portnr);
if (ret)
return ret;
- usb_power_config(index);
- usb_oc_config(index);
- usb_internal_phy_clock_gate(index);
- usb_phy_enable(index, ehci);
+ usb_power_config(priv->anatop_addr, priv->portnr);
+ usb_oc_config(priv->misc_addr);
+ usb_internal_phy_clock_gate(priv->phy_addr);
+ usb_phy_enable(priv->phy_addr, priv->ehci);
return 0;
}
-/* Possible port types (dual role mode) */
-enum dr_mode {
- DR_MODE_NONE = 0,
- DR_MODE_HOST, /* supports host operation */
- DR_MODE_DEVICE, /* supports device operation */
- DR_MODE_OTG, /* supports both */
-};
-
-struct ehci_vf_priv_data {
- struct ehci_ctrl ctrl;
- struct usb_ehci *ehci;
- struct gpio_desc cdet_gpio;
- enum usb_init_type init_type;
- enum dr_mode dr_mode;
- u32 portnr;
-};
-
-static int vf_usb_of_to_plat(struct udevice *dev)
+static int vf_parse_dt_addrs(struct udevice *dev)
{
struct ehci_vf_priv_data *priv = dev_get_priv(dev);
- const void *dt_blob = gd->fdt_blob;
- int node = dev_of_offset(dev);
- const char *mode;
- fdt_addr_t phy_addr;
- ofnode phy_node;
- int i;
+ ofnode phy_node, misc_node, anatop_node;
+ fdt_addr_t addr;
+ int ret;
phy_node = ofnode_parse_phandle(dev_ofnode(dev), "fsl,usbphy", 0);
if (!ofnode_valid(phy_node))
return -EINVAL;
- phy_addr = ofnode_get_addr(phy_node);
- for (i = 0; i < ARRAY_SIZE(phy_bases); i++) {
- if (phy_addr == phy_bases[i])
- break;
- }
- if (i == ARRAY_SIZE(phy_bases))
+ misc_node = ofnode_parse_phandle(dev_ofnode(dev), "fsl,usbmisc", 0);
+ if (!ofnode_valid(misc_node))
+ return -EINVAL;
+
+ anatop_node = ofnode_parse_phandle(phy_node, "fsl,anatop", 0);
+ if (!ofnode_valid(anatop_node))
+ return -EINVAL;
+
+ ret = ofnode_get_alias_seq(phy_node, dev->uclass->uc_drv->name,
+ &priv->portnr);
+ if (ret)
+ return ret;
+
+ addr = ofnode_get_addr(phy_node);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+ priv->phy_addr = (void __iomem *)addr;
+
+ addr = ofnode_get_addr(misc_node);
+ if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
+ priv->misc_addr = (void __iomem *)addr;
- priv->portnr = i;
+ addr = ofnode_get_addr(anatop_node);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+ priv->anatop_addr = (struct anadig_reg __iomem *)addr;
+
+ return 0;
+}
+
+static int vf_usb_of_to_plat(struct udevice *dev)
+{
+ struct ehci_vf_priv_data *priv = dev_get_priv(dev);
+ const void *dt_blob = gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ const char *mode;
+ int ret;
+
+ ret = vf_parse_dt_addrs(dev);
+ if (ret)
+ return ret;
priv->ehci = dev_read_addr_ptr(dev);
mode = fdt_getprop(dt_blob, node, "dr_mode", NULL);
@@ -241,7 +250,7 @@ static int vf_init_after_reset(struct ehci_ctrl *dev)
struct usb_ehci *ehci = priv->ehci;
int ret;
- ret = ehci_vf_common_init(priv->ehci, priv->portnr);
+ ret = ehci_vf_common_init(priv);
if (ret)
return ret;
@@ -270,7 +279,7 @@ static int ehci_usb_probe(struct udevice *dev)
struct ehci_hcor *hcor;
int ret;
- ret = ehci_vf_common_init(ehci, priv->portnr);
+ ret = ehci_vf_common_init(priv);
if (ret)
return ret;
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v4 6/6] usb: ehci-vf: enable the vbus supply of the port
2026-10-07 14:45 [PATCH v4 0/6] usb: ehci-vf: make the USB host port usable Mehmet Fide
` (4 preceding siblings ...)
2026-10-07 14:45 ` [PATCH v4 5/6] usb: ehci-vf: take the register bases from the device tree Mehmet Fide
@ 2026-10-07 14:45 ` Mehmet Fide
5 siblings, 0 replies; 10+ messages in thread
From: Mehmet Fide @ 2026-10-07 14:45 UTC (permalink / raw)
To: Marek Vasut, Simon Glass
Cc: Tom Rini, Fabio Estevam, Stefan Agner, Francesco Dolcini, u-boot,
Mehmet Fide
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
The driver never enables the vbus-supply of its port, so on boards that
switch VBUS through a regulator, such as the Colibri VF50 and VF61
carriers, the port stays unpowered and no device is found.
Do what ehci-mx6 does: look the regulator up in probe, enable it in
host mode, disable it in device mode, and turn it off on remove. A
missing vbus-supply or a build without DM_REGULATOR is fine; any other
lookup error fails the probe instead of leaving the port dead.
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
Changes in v4:
- enable VBUS in the reset hook only, as ehci-mx6 does: enabling it in
the shared init as well counted two enables per probe, so "usb stop"
never switched it off
- the dm core patch it needed is dropped, next claims the regulator
GPIO at probe time
- reworded the commit message
drivers/usb/host/ehci-vf.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index b1cfad14b09..7b8aeaecf38 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 "ehci.h"
@@ -53,6 +54,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;
};
@@ -254,6 +256,13 @@ static int vf_init_after_reset(struct ehci_ctrl *dev)
if (ret)
return ret;
+ ret = regulator_set_enable_if_allowed(priv->vbus_supply,
+ type != USB_INIT_DEVICE);
+ if (ret && ret != -ENOSYS) {
+ printf("Error enabling VBUS supply (ret=%i)\n", ret);
+ return ret;
+ }
+
if (type == USB_INIT_DEVICE)
return 0;
@@ -279,6 +288,15 @@ static int ehci_usb_probe(struct udevice *dev)
struct ehci_hcor *hcor;
int ret;
+ ret = device_get_supply_regulator(dev, "vbus-supply",
+ &priv->vbus_supply);
+ if (ret == -ENOENT || ret == -ENOSYS) {
+ debug("%s: no vbus supply\n", dev->name);
+ } else if (ret) {
+ printf("Error getting VBUS supply (ret=%i)\n", ret);
+ return ret;
+ }
+
ret = ehci_vf_common_init(priv);
if (ret)
return ret;
@@ -306,12 +324,21 @@ 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);
+
+ 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.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v4 4/6] dm: core: add ofnode_get_alias_seq()
2026-10-07 14:45 ` [PATCH v4 4/6] dm: core: add ofnode_get_alias_seq() Mehmet Fide
@ 2026-10-09 6:47 ` Simon Glass
2026-10-09 9:05 ` Mehmet Fide
0 siblings, 1 reply; 10+ messages in thread
From: Simon Glass @ 2026-10-09 6:47 UTC (permalink / raw)
To: mehmet.fide
Cc: Marek Vasut, Simon Glass, Tom Rini, Fabio Estevam, Stefan Agner,
Francesco Dolcini, u-boot, Mehmet Fide
Hi Mehmet,
On 2026-10-07T14:45:38, Mehmet Fide <mehmet.fide@gmail.com> wrote:
> dm: core: add ofnode_get_alias_seq()
>
> The sequence number an aliases entry gives a node can only be looked up
> for a device, through dev_read_alias_seq(). A driver that has to know
> the number of a node it does not own, one it reached through a phandle
> for instance, has no livetree call for it and is left with fdtdec.
>
> Move the body of dev_read_alias_seq() to the ofnode level and let both
> of its variants call it. No functional change, so the moved lines keep
> the ENOTSUPP return, the #if and the fdtdec call they had, which is what
> checkpatch complains about here.
The checkpatch remark is for reviewers, not the commit log. Ideally
this would go below the --- line
>
> A test checks the lookup on the live and on the flat tree.
>
> Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
>
> drivers/core/ofnode.c | 20 ++++++++++++++++++++
> drivers/core/read.c | 20 ++------------------
> include/dm/ofnode.h | 13 +++++++++++++
> include/dm/read.h | 8 ++------
> test/dm/ofnode.c | 20 ++++++++++++++++++++
> 5 files changed, 57 insertions(+), 24 deletions(-)
> diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
> @@ -1233,6 +1233,26 @@ ofnode ofnode_get_aliases_node(const char *name)
> + if (ofnode_is_np(node)) {
> + ret = of_alias_get_id(ofnode_to_np(node), stem);
> + if (ret >= 0) {
> + *seqp = ret;
> + ret = 0;
> + }
> + } else {
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> + ret = fdtdec_get_alias_seq(ofnode_to_fdt(node), stem,
> + ofnode_to_offset(node), seqp);
> +#endif
The two branches handle the stem differently. of_alias_get_id() does a
strcmp() against the stem split off by of_alias_scan(), so the stem
must match exactly. fdtdec_get_alias_seq() just does strncmp(name,
base, base_len) and then trailing_strtol(), so any alias starting with
the stem matches. For example,
ofnode_get_alias_seq(ofnode_path("/some-bus"), "test", &seq) returns 0
with seq = 3 on the flat tree (from testbus3) but -ENODEV on the live
tree.
This was mostly hidden while the only caller passed a uclass name for
the device's own node. Now that the function is public and works on
any node it matters, and patch 5 depends on it: it passes
dev->uclass->uc_drv->name, i.e. 'usb', for the PHY node whose alias is
'usbphy0'. That works on colibri_vf with the flat tree only because of
the prefix match, and would fail with OF_LIVE. I think patch 5 should
pass 'usbphy'.
Please can you also say in the header comment that the stem must match
exactly, and add a negative test with a prefix stem like the one
above, so the two implementations are tested against each other?
Making fdtdec_get_alias_seq() check that the stem is followed by a
digit would be a separate fix, but worth doing. What do you think?
> diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
> @@ -523,6 +523,26 @@ static int dm_test_ofnode_read_aliases(struct unit_test_state *uts)
> + ut_assert(ofnode_get_alias_seq(ofnode_path("/i2c@0"), "spi", &seq) < 0);
> + ut_assert(ofnode_get_alias_seq(ofnode_path("/some-bus"), "testfdt",
> + &seq) < 0);
Since the flat path now uses ofnode_to_fdt() rather than gd->fdt_blob,
it would be good to also check a node in another tree, i.e. a variant
using oftree_path() with UTF_OTHER_FDT, like the other *_ot tests in
this file.
Regards,
Simon
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 4/6] dm: core: add ofnode_get_alias_seq()
2026-10-09 6:47 ` Simon Glass
@ 2026-10-09 9:05 ` Mehmet Fide
2026-10-12 14:23 ` Simon Glass
0 siblings, 1 reply; 10+ messages in thread
From: Mehmet Fide @ 2026-10-09 9:05 UTC (permalink / raw)
To: Simon Glass
Cc: Marek Vasut, Tom Rini, Fabio Estevam, Stefan Agner,
Francesco Dolcini, u-boot, Mehmet Fide
Hi Simon,
On 2026-10-09, Simon Glass wrote:
> The checkpatch remark is for reviewers, not the commit log. Ideally
> this would go below the --- line
Will do.
> The two branches handle the stem differently. of_alias_get_id() does a
> strcmp() against the stem split off by of_alias_scan(), so the stem
> must match exactly. fdtdec_get_alias_seq() just does strncmp(name,
> base, base_len) and then trailing_strtol(), so any alias starting with
> the stem matches.
Yes, and that prefix match is also what started this series: with
"usb" as the stem, fdtdec_get_alias_highest_id() counts usbphy0 and
usbphy1 as usb aliases, which is why the two controllers ended up with
seq 2 and 3 and indexed past the two-entry tables (patch 1). So I
agree it is worth fixing, and in both functions: a stem matches an
alias only when what follows it is the number. It is a separate patch
with tests for both lookups, but it has to come ahead of this one in
v5: the negative test you ask for below ("test" on /some-bus) can only
pass on the flat tree once the prefix match is gone. The series still
follows the PHY phandle (patch 1), which does not depend on how the
aliases are numbered.
> I think patch 5 should pass 'usbphy'.
Yes, that was wrong, v5 passes "usbphy". The header comment will say
the stem must match exactly, and the test gets the negative case with
a prefix stem ("test" on /some-bus) so the two implementations are
checked against each other.
> Since the flat path now uses ofnode_to_fdt() rather than gd->fdt_blob,
> it would be good to also check a node in another tree, i.e. a variant
> using oftree_path() with UTF_OTHER_FDT, like the other *_ot tests in
> this file.
Agreed for the flat tree, that is exactly what the ofnode_to_fdt()
change is for. On the live tree there is a gap though: of_alias_scan()
only runs for the control tree, and the other tree of the tests comes
from unflatten_device_tree() alone, so of_alias_get_id() cannot know
its aliases. I see two ways: (a) the live branch of
ofnode_get_alias_seq() handles a node outside the control tree itself,
by walking that tree's /aliases (the control tree keeps the fast list
lookup), so the _ot test runs in both modes like its neighbours; (b)
the _ot test is flat-only (UTF_FLAT_TREE) and the comment says why.
I would do (a) unless you prefer to keep the livetree side as it is.
Regards,
Mehmet
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4 4/6] dm: core: add ofnode_get_alias_seq()
2026-10-09 9:05 ` Mehmet Fide
@ 2026-10-12 14:23 ` Simon Glass
0 siblings, 0 replies; 10+ messages in thread
From: Simon Glass @ 2026-10-12 14:23 UTC (permalink / raw)
To: Mehmet Fide
Cc: Marek Vasut, Tom Rini, Fabio Estevam, Stefan Agner,
Francesco Dolcini, u-boot, Mehmet Fide
Hi Mehmet,
On Fri, 9 Oct 2026 at 10:06, Mehmet Fide <mehmet.fide@gmail.com> wrote:
>
> Hi Simon,
>
> On 2026-10-09, Simon Glass wrote:
> > The checkpatch remark is for reviewers, not the commit log. Ideally
> > this would go below the --- line
>
> Will do.
>
> > The two branches handle the stem differently. of_alias_get_id() does a
> > strcmp() against the stem split off by of_alias_scan(), so the stem
> > must match exactly. fdtdec_get_alias_seq() just does strncmp(name,
> > base, base_len) and then trailing_strtol(), so any alias starting with
> > the stem matches.
>
> Yes, and that prefix match is also what started this series: with
> "usb" as the stem, fdtdec_get_alias_highest_id() counts usbphy0 and
> usbphy1 as usb aliases, which is why the two controllers ended up with
> seq 2 and 3 and indexed past the two-entry tables (patch 1). So I
> agree it is worth fixing, and in both functions: a stem matches an
> alias only when what follows it is the number. It is a separate patch
> with tests for both lookups, but it has to come ahead of this one in
> v5: the negative test you ask for below ("test" on /some-bus) can only
> pass on the flat tree once the prefix match is gone. The series still
> follows the PHY phandle (patch 1), which does not depend on how the
> aliases are numbered.
>
> > I think patch 5 should pass 'usbphy'.
>
> Yes, that was wrong, v5 passes "usbphy". The header comment will say
> the stem must match exactly, and the test gets the negative case with
> a prefix stem ("test" on /some-bus) so the two implementations are
> checked against each other.
>
> > Since the flat path now uses ofnode_to_fdt() rather than gd->fdt_blob,
> > it would be good to also check a node in another tree, i.e. a variant
> > using oftree_path() with UTF_OTHER_FDT, like the other *_ot tests in
> > this file.
>
> Agreed for the flat tree, that is exactly what the ofnode_to_fdt()
> change is for. On the live tree there is a gap though: of_alias_scan()
> only runs for the control tree, and the other tree of the tests comes
> from unflatten_device_tree() alone, so of_alias_get_id() cannot know
> its aliases. I see two ways: (a) the live branch of
> ofnode_get_alias_seq() handles a node outside the control tree itself,
> by walking that tree's /aliases (the control tree keeps the fast list
> lookup), so the _ot test runs in both modes like its neighbours; (b)
> the _ot test is flat-only (UTF_FLAT_TREE) and the comment says why.
> I would do (a) unless you prefer to keep the livetree side as it is.
Sounds reasonable to me.
Regards,
Simon
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-10-12 14:24 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-07 14:45 [PATCH v4 0/6] usb: ehci-vf: make the USB host port usable Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 1/6] usb: ehci-vf: take the controller index from the device tree Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 2/6] usb: ehci-vf: remove the code path for a build without DM_USB Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 3/6] usb: ehci-vf: drop the empty bind hook Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 4/6] dm: core: add ofnode_get_alias_seq() Mehmet Fide
2026-10-09 6:47 ` Simon Glass
2026-10-09 9:05 ` Mehmet Fide
2026-10-12 14:23 ` Simon Glass
2026-10-07 14:45 ` [PATCH v4 5/6] usb: ehci-vf: take the register bases from the device tree Mehmet Fide
2026-10-07 14:45 ` [PATCH v4 6/6] usb: ehci-vf: enable the vbus supply of the port Mehmet Fide
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.