Message ID | 20181030140305.71172-1-heikki.krogerus@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [RFC,1/1] usb: dwc3: drd: Register a USB role switch | expand |
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@linux.intel.com> > --- > 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); > } >
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); }
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@linux.intel.com> --- 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 --- drivers/usb/dwc3/core.h | 2 ++ drivers/usb/dwc3/drd.c | 45 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+)