[PATCH 1/3] usb: dwc2: override PHY input signals with usb role switch support

Martin Blumenstingl martin.blumenstingl at googlemail.com
Tue Jul 7 14:55:05 EDT 2020


Hi Amelie,

On Tue, Jul 7, 2020 at 6:13 PM Amelie DELAUNAY <amelie.delaunay at st.com> wrote:
>
> Hi Martin,
>
> On 7/4/20 7:42 PM, Martin Blumenstingl wrote:
> > Hello Amelie,
> >
> > thank you for this patch - I am hoping that it will help us on Amlogic
> > Meson8, Meson8b, Meson8m2 and GXBB SoCs as well.
> > On these SoCs the ID detection is performed by the PHY IP and needs to
> > be polled.
> > I think usb_role_switch is the perfect framework for this on dwc2 side.
> > For the PHY driver I'm going to implement the cable state using the
> > extcon framework and then having a new usb-conn-extcon driver. This is
> > just to give you an overview why I'm interested in this.
> >
>
> I'm wondering, why use extcon framework and not the usb role switch API
> ? This patch on dwc2 is tested on STM32MP157C-DK2 board with STUSB160x
> Type-C controller driver recently pushed with usb role switch. You can
> have a look here https://lore.kernel.org/patchwork/patch/1256238/.
one of the boards that I'm working on is for example the Odroid-C1. It
has a Micro-USB port and there's no Type-C controller present.

in the next few days I'll try to send my idea as RFC, but this is the
.dts I've come up with so far:
&usb0 {
    dr_mode = "otg";
    usb-role-switch;

    connector {
        compatible = "extcon-usb-b-connector", "usb-b-connector";
        type = "micro";
        extcon = <&usb0_phy>;
        vbus-supply = <&usb_vbus>;
    };
};

I did this for two reasons:
1. I think the PHY is not a connector and thus it's driver shouldn't
implement any connector specific logic (managing VBUS)
2. without the connector there would be a circular dependency: the USB
controller needs the PHY to initialize but the PHY would need the USB
controller so it can manage the role switch

(or in other words: the connector replaces the Type-C controller in this case)

> > [...]
> >> +static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role)
> >> +{
> >> +     struct dwc2_hsotg *hsotg = usb_role_switch_get_drvdata(sw);
> >> +     unsigned long flags;
> >> +
> >> +     /* Skip session not in line with dr_mode */
> >> +     if ((role == USB_ROLE_DEVICE && hsotg->dr_mode == USB_DR_MODE_HOST) ||
> >> +         (role == USB_ROLE_HOST && hsotg->dr_mode == USB_DR_MODE_PERIPHERAL))
> >> +             return -EINVAL;
> >> +
> >> +     /* Skip session if core is in test mode */
> >> +     if (role == USB_ROLE_NONE && hsotg->test_mode) {
> >> +             dev_dbg(hsotg->dev, "Core is in test mode\n");
> >> +             return -EBUSY;
> >> +     }
> >> +
> >> +     spin_lock_irqsave(&hsotg->lock, flags);
> > due to this spin_lock_irqsave() ...
> >
> >> +     if (role == USB_ROLE_HOST) {
> >> +             if (dwc2_ovr_avalid(hsotg, true))
> >> +                     goto unlock;
> >> +
> >> +             if (hsotg->dr_mode == USB_DR_MODE_OTG)
> >> +                     /*
> >> +                      * This will raise a Connector ID Status Change
> >> +                      * Interrupt - connID A
> >> +                      */
> >> +                     dwc2_force_mode(hsotg, true);
> > ... we cannot sleep in here. the call flow is:
> > dwc2_drd_role_sw_set
> >    spin_lock_irqsave
> >    dwc2_force_mode
> >      dwc2_wait_for_mode
> >        usleep_range
> >
>
> In fact, with the avalid or bvalid overriding + the debounce filter
> bypass, GINTSTS_CURMOD is already in the expected mode, so that we exit
> the loop directly, without running into usleep_range.
on my Amlogic SoC this is not the case:
The kernel complains because of that usleep_range from within the
spinlock context

Please let me know if/how I can help debug this.

[...]
> > +int dwc2_drd_init(struct dwc2_hsotg *hsotg)
> > +{
> > +       struct usb_role_switch_desc role_sw_desc = {0};
> > +       struct usb_role_switch *role_sw;
> > +       int ret;
> > +
> > +       if (!device_property_read_bool(hsotg->dev, "usb-role-switch"))
> > +               return 0;
> > should we also return early here if dr_mode != "otg"?
> >
>
> No, because when VBUS is not connected to the controller, you also need
> to get the usb_role_none from the usb-role-switch to catch the
> unattached state (also in Peripheral or Host only mode).
I see - thank you for the explanation!


Best regards,
Martin



More information about the linux-arm-kernel mailing list