[PATCH v2] usb: cdns3: use VBUS Valid to determine role for dr_mode OTG
Siddharth Vadapalli
s-vadapalli at ti.com
Sat Feb 14 05:36:26 CET 2026
Hello Marek,
On Fri, 2026-02-13 at 16:04 +0100, Marek Vasut wrote:
> On 2/13/26 6:15 AM, Siddharth Vadapalli wrote:
>
> [...]
>
> > +++ b/drivers/usb/cdns3/core.c
> > @@ -392,6 +392,63 @@ static const struct udevice_id cdns3_ids[] = {
> > { },
> > };
> >
> > +/*
> > + * The VBUS Valid Bit in the OTG Status register can be used to determine
> > + * the role. When VBUS Valid is set, it indicates that a USB Host is supplying
> > + * power, so the Controller should assume the PERIPHERAL role. If it isn't set,
> > + * it indicates the absence of a USB Host, so the Controller should assume the
> > + * HOST role. If the OTG Status register is inaccessible, return an error.
> > + */
> > +static int cdns3_get_otg_mode(ofnode node
>
> Pass struct udevice *parent instead of node here ...
>
> > , enum usb_dr_mode *mode)
> > +{
> > + struct cdns3 cdns, *cdnsp;
> > + void __iomem *otg_regs;
> > + fdt_addr_t otg_addr;
> > + int otg_reg_index;
> > + int vbus;
> > +
> > + otg_reg_index = ofnode_stringlist_search(node, "reg-names", "otg");
> > + if (otg_reg_index < 0) {
> > + printf("%s: dr_mode is otg but otg register name is missing\n", __func__);
> > + return -ENOENT;
> > + }
> > +
> > + otg_addr = ofnode_get_addr_index(node, otg_reg_index);
> > + if (otg_addr == FDT_ADDR_T_NONE) {
> > + printf("%s: address of otg registers is unspecified\n", __func__);
> > + return -ENOENT;
> > + }
> > +
> > + otg_regs = map_physmem(otg_addr, 0, MAP_NOCACHE);
> > + if (!otg_regs) {
> > + printf("%s: failed to map otg registers\n", __func__);
> > + return -EINVAL;
> > + }
>
> ... and replace all that ^ with devfdt_remap_addr_name(parent, "otg") .
> That should work.
It doesn't work because the 'parent' node doesn't have the 'otg' registers.
It is the child node which has it. The device-tree nodes for parent and
child are:
usbss0: usb at 4104000 {
=> PARENT
bootph-all;
compatible = "ti,j721e-usb";
reg = <0x00 0x4104000 0x00 0x100>;
dma-coherent;
[TRIMMED]
usb0: usb at 6000000
{ => CHILD
bootph-all;
compatible = "cdns,usb3";
reg = <0x00 0x6000000 0x00 0x10000>,
<0x00 0x6010000 0x00 0x10000>,
<0x00 0x6020000 0x00 0x10000>;
reg-names = "otg", "xhci",
"dev"; => OTG Register is defined here
[TRIMMED]
};
The 'udevice' for the child node is created in the cdns3_bind() function
__after__ the function in this patch is invoked. Therefore, we don't yet
have the child device which is created by:
device_bind_driver_to_node(parent, driver, name, node,
&dev);
I did consider the possibility of using the standard APIs
(devfdt_remap_addr_name), but since the child device doesn't exist yet,
they cannot be used. Hence, I had to implement custom logic.
Regards,
Siddharth.
More information about the U-Boot
mailing list