Re: grumpy DWC3+UCSI, usb-role-switch semantics

From: Thinh Nguyen

Date: Fri Mar 13 2026 - 18:15:01 EST


On Fri, Mar 13, 2026, Konrad Dybcio wrote:
> On 3/11/26 8:21 PM, Thinh Nguyen wrote:
> > On Wed, Mar 11, 2026, Konrad Dybcio wrote:
> >> Hi,
> >>
> >> The description for the usb-role-switch property (usb-drd.yaml) states:
> >>
> >> Indicates that the device is capable of assigning the USB data role
> >> (USB host or USB device) for a given USB connector, such as Type-C,
> >> Type-B(micro). See connector/usb-connector.yaml.
> >>
> >> That to me sounds like a description of the capability of the on-SoC
> >> controller (i.e. should/could be set regardless of device specifics),
> >
> > That property description is misleading. We enable this property if we
> > want to use the usb role-switch framework. This has nothing to do with
> > the hardware capability. The description should correspond more closely
> > to its change log:
> >
> > 451d15a1731c ("dt-binding: usb: add usb-role-switch property")
> >
> >> however in this configuration:
> >>
> >> &usb {
> >> dr_mode = "host";
> >> usb-role-switch;
> >> };
> >>
> >> the role switch device is never registered on devices with a DWC3
> >> controller, since that's handled in dwc3_drd_init(), which is only called
> >> if dr_mode = "otg" (or absent since otg is the default).
> >>
> >>
> >> This notably causes:
> >>
> >> ucsi_init()
> >> -> ucsi_register_port()
> >> -> fwnode_usb_role_switch_get()
> >>
> >> to loop in -EPROBE_DEFER, since the 'usb-role-switch' property is present
> >> on the connected DWC3 core, but the rolesw device is never registered.
> >>
> >> Now, it seems like different drivers do this differently, e.g. DWC2 seems
> >> to always register a rolesw.
> >>
> >>
> >> How should we tackle this?
> >>
> >> FWIW I'd prefer (for maintainability reasons) to not have to set/remove
> >> 'usb-role-switch' separately for each board, depending on whether whatever is
> >> at the other end of the USB cables is rolesw-capable (since again, the controller
> >
> > We shouldn't do that. The usb-role-switch cannot just be inferred from
> > the dr_mode. The use of the usb role-switch framework needs to be
> > specified by the user. For example, for this particular scenario you
> > mentioned, the UCSI expects the role-switch handle. The dwc3 driver
> > wouldn't know that without the usb-role-switch property. Not every drd
> > platform uses the usb role-switch framework for role switching.
> >
> >> itself is), but if we go that route, I'd request that we explicitly forbid the
> >> combination of usb-role-switch && dr_mode=host/peripheral in bindings, so that
> >> the computer yells at me if I overlook that
> >>
> >
> > The dwc3 driver can be updated to register the role-switch device if the
> > usb-role-switch property is set. Additionally, the role-switching
> > condition would need to be revised to ensure it is constrained by the
> > dr_mode.
> >
> > It's a bit odd to be in host-only mode but also needs to use the
> > role-switch framework. I don't think the UCSI even uses role-switch
> > get_role? In anycase, the change shouldn't be an issue.
>
> Rethinking it again, we only register UCSI if there's a provider (in
> our case pmic-glink with UCSI_GLINK as one of its aux devices), and such
> a provider normally comes with a connector definition, which is logically
> always a Type-C one (the 'C' in 'UCSI'), so it (very likely) has some
> form of 'data-role' property (and if it doesn't, we don't enter the
> problematic paths?).
>
> That property may be further restricted to something else than 'dual',
> but the controller will (to my understanding) still get a role_sw
> notification (Type-C class .dr_set() normally ends up calling that one
> way or another)
>
> So, zooming out, the problem here simply seems to be that there is no
> reason at all to limit dr_mode if UCSI is at play..

The setting of dr_mode is independent of whether UCSI is at play. It's a
hardware capability property that ensure the controller would only
operate in the specified mode.

>
> If it isn't, something may still call role_switch_get() and fall into
> the same defer loop, but again it seems unlikely that it would be a
> valid configuration (I can only think of dr_mode used as a workaround
> for DR-capable HW that can't detect the desired role properly, paired
> with an overzealous driver that really wants a role_sw somehow consuming
> a reference to that controller)
>
> Hence, I think the way forward is just to stop setting dr_mode where
> it doesn't make logical sense and revisit if this turns out to be an
> issue in a "real" scenario
>

It's platform specific. The dwc3 driver has certain logic to determine
the controller capability, but the dr_mode property can override this.
If your platform does not need to specify the dr_mode and rely solely on
the UCSI connection detection/negotiation and/or the dwc3 capability
checks, then you can omit it.

Note that if your platform is DRD, on disconnect, the controller will
switch back to the default mode, which is typically peripheral. If we
set the dr_mode to host only, then we must make sure that the dwc3 never
switch to device mode.

So, as I mentioned previously, if your use case requires that we still
need to register the role-switch device while the dr_mode is not otg,
then we can make a change in dwc3 to do so.

BR,
Thinh