Hi, On 2018/10/30 22:03, Heikki Krogerus wrote: > The Type-C drivers use USB role switch API to inform the > system about the negotiated data role, so registering a role > switch in the DRD code in order to support platforms with > USB Type-C connectors. > > Signed-off-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx> > --- > Hi Chen Yu, > > This is related to your Hikey960 USB patches series [1]. I can't test > this patch, but I don't think this part should require anything else. > > And about the device graph you'll need for this and the other > components, I noticed that > > Documentation/devicetree/bindings/connector/usb-connector.txt > > has some nice examples. I believe your port controller device will be > one remote-endpoint for dwc3, and that hub/mux device another. > > cheers, > > [1] https://lkml.org/lkml/2018/10/27/178 > Thanks a lot for the patches! I will test the patches series on Hikey960. I will read the examples in Documentation/devicetree/bindings/connector/usb-connector.txt and try to use it in my HiKey960 patches. Thansks! > --- > drivers/usb/dwc3/core.h | 2 ++ > drivers/usb/dwc3/drd.c | 45 +++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 47 insertions(+) > > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index 5bfb62533e0f..9d2a236354f9 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -25,6 +25,7 @@ > #include <linux/usb/ch9.h> > #include <linux/usb/gadget.h> > #include <linux/usb/otg.h> > +#include <linux/usb/role.h> > #include <linux/ulpi/interface.h> > > #include <linux/phy/phy.h> > @@ -1053,6 +1054,7 @@ struct dwc3 { > struct extcon_dev *edev; > struct notifier_block edev_nb; > enum usb_phy_interface hsphy_mode; > + struct usb_role_switch *role_sw; > > u32 fladj; > u32 irq_gadget; > diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c > index 218371f985ca..1795ea2a4570 100644 > --- a/drivers/usb/dwc3/drd.c > +++ b/drivers/usb/dwc3/drd.c > @@ -463,6 +463,44 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) > return edev; > } > > +static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role) > +{ > + u32 mode; > + > + switch (role) { > + case USB_ROLE_HOST: > + mode = DWC3_GCTL_PRTCAP_HOST; > + break; > + case USB_ROLE_DEVICE: > + mode = DWC3_GCTL_PRTCAP_DEVICE; > + break; > + default: > + mode = DWC3_GCTL_PRTCAP_OTG; > + break; > + }; > + > + dwc3_set_mode(dev_get_drvdata(dev), mode); > + return 0; > +} > + > +static enum usb_role dwc3_usb_role_switch_get(struct device *dev) > +{ > + struct dwc3 *dwc = dev_get_drvdata(dev); > + unsigned long flags; > + enum usb_role role; > + > + spin_lock_irqsave(&dwc->lock, flags); > + role = dwc->current_otg_role; > + spin_unlock_irqrestore(&dwc->lock, flags); > + > + return role; > +} > + > +static const struct usb_role_switch_desc dwc3_role_switch = { > + .set = dwc3_usb_role_switch_set, > + .get = dwc3_usb_role_switch_get, > +}; > + > int dwc3_drd_init(struct dwc3 *dwc) > { > int ret, irq; > @@ -511,6 +549,11 @@ int dwc3_drd_init(struct dwc3 *dwc) > dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); > } > > + dwc->role_sw = usb_role_switch_register(dwc->dev, &dwc3_role_switch); > + if (ret) { > + dwc3_drd_exit(dwc); > + return PTR_ERR(dwc->role_sw); > + } > return 0; > } > > @@ -546,4 +589,6 @@ void dwc3_drd_exit(struct dwc3 *dwc) > > if (!dwc->edev) > free_irq(dwc->otg_irq, dwc); > + > + usb_role_switch_unregister(dwc->role_sw); > } >