HiKey960 USB support
v6 cover HiKey960 USB support
Just another round here trying to push forward a patch series submitted originally by Yu Chen to get HiKey960 dev-board's USB functionality working.
The full patchset (including dts changes not submitted here) can be found here:
https://git.linaro.org/people/john.stultz/android-dev.git/log/?id=950276ae1baab3a22836d1f89aeadbb08adf41e0
NOTE: I unfortunately don't have any deep knowledge of the hardware other then the previously submitted code and what I can intuit from testing. I tried to document the previously undocumented bindings, fixed up a few minor checkpatch issues and tried to address previous feedback as best I could.
I'd greatly appreciate any feedback or thoughts!
thanks
-john
New in v6:
* Felipe previously had disliked extending the dwc3 binding to allow for more flexible clock and resest lists, so in the last series I switched back to the dwc3-simple-of.c approach, but Rob pushed back on the last series, and with no reply from Felipe, I've switched back to this appraoch. Clear guidance would be appreciated here!
* Fixed build issue Reported-by: kbuild test robot <[email protected]>
John Stultz (5):
dt-bindings: usb: generic: Add role-switch-default-mode binding
usb: dwc3: Add support for role-switch-default-mode binding
dt-bindings: usb: dwc3: Allow clock list & resets to be more flexible
usb: dwc3: Rework clock initialization to be more flexible
usb: dwc3: Rework resets initialization to be more flexible
Yu Chen (3):
usb: dwc3: Registering a role switch in the DRD code.
dt-bindings: misc: Add bindings for HiSilicon usb hub and data role
switch functionality on HiKey960
misc: hisi_hikey_usb: Driver to support usb functionality of Hikey960
.../bindings/misc/hisilicon-hikey-usb.txt | 40 ++++ .../devicetree/bindings/usb/dwc3.txt | 5 +- .../devicetree/bindings/usb/generic.txt | 6 + drivers/misc/Kconfig | 6 + drivers/misc/Makefile | 1 + drivers/misc/hisi_hikey_usb.c | 178 ++++++++++++++++++ drivers/usb/dwc3/core.c | 22 +-- drivers/usb/dwc3/core.h | 6 + drivers/usb/dwc3/drd.c | 96 +++++++++- 9 files changed, 341 insertions(+), 19 deletions(-) create mode 100644 Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt create mode 100644 drivers/misc/hisi_hikey_usb.c
Signature · 1 line
2.17.1
PATCH v6 1/8 usb: dwc3: Registering a role switch in the DRD code.
From: Yu Chen <[email protected]>
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.
---
v2: Fix role_sw and role_switch_default_mode descriptions as
reported by kbuild test robot <[email protected]>
v3: Split out the role-switch-default-host logic into its own
patch
v5: Drop selecting CONFIG_USB_ROLE_SWITCH & ifdef dependent code
v6: Fix build issue Reported-by: kbuild test robot <[email protected]>
--- drivers/usb/dwc3/core.h | 3 ++ drivers/usb/dwc3/drd.c | 77 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-)
drivers/usb/dwc3/core.h +3 -0
@@ -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>
@@ -951,6 +952,7 @@ struct dwc3_scratchpad_array {* @hsphy_mode: UTMI phy mode, one of following: * - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW +* @role_sw: usb_role_switch handle * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY
@@ -1084,6 +1086,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;
drivers/usb/dwc3/drd.c +76 -1
95 lines not on this page · raw message
Signature · 1 line
2.17.1
Re: [PATCH v6 1/8] usb: dwc3: Registering a role switch in the DRD code.
Quoted 164 lines · John Stultz
From: Yu Chen <[email protected]>
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.
Cc Greg Kroah-Hartman <[email protected]>Cc Rob Herring <[email protected]>Cc Mark Rutland <[email protected]>CC ShuFan Lee <[email protected]>Cc Heikki Krogerus <[email protected]>Cc Suzuki K Poulose <[email protected]>Cc Chunfeng Yun <[email protected]>Cc Yu Chen <[email protected]>Cc Felipe Balbi <[email protected]>Cc Hans de Goede <[email protected]>Cc Andy Shevchenko <[email protected]>Cc Jun Li <[email protected]>Cc Valentin Schneider <[email protected]>Cc Jack Pham <[email protected]>Suggested-by Heikki Krogerus <[email protected]>Signed-off-by Yu Chen <[email protected]>Signed-off-by John Stultz <[email protected]>Change-Id Ibd89b7eb3e59688895a2d317f3515e6d2705c6f3---
v2: Fixrole_swandrole_switch_default_modedescriptions as
reported by kbuild test robot <[email protected]>v3: Split out the role-switch-default-host logic into its own
patchv5: Drop selecting
CONFIG_USB_ROLE_SWITCH& ifdef dependent codev6: Fix build issue Reported-by: kbuild test robot <[email protected]>
--- drivers/usb/dwc3/core.h | 3 ++ drivers/usb/dwc3/drd.c | 77 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-)drivers/usb/dwc3/core.h +3
-0@@ -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> @@ -951,6 +952,7 @@ struct dwc3_scratchpad_array {* @hsphy_mode: UTMI phy mode, one of following: * - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW +* @role_sw: usb_role_switch handle * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY @@ -1084,6 +1086,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;drivers/usb/dwc3/drd.c +73
-1@@ -476,6 +476,73 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)return edev; } +#ifdef CONFIG_USB_ROLE_SWITCH +#define ROLE_SWITCH 1 +static int dwc3_usb_role_switch_set (struct device *dev,enum usb_role role) +{ +struct dwc3 *dwc =dev_get_drvdata (dev); +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_DEVICE ; +break ; + } + +dwc3_set_mode (dwc, 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); +switch (dwc->current_dr_role) { +case DWC3_GCTL_PRTCAP_HOST : + role =USB_ROLE_HOST ; +break ; +case DWC3_GCTL_PRTCAP_DEVICE : + role =USB_ROLE_DEVICE ; +break ; +case DWC3_GCTL_PRTCAP_OTG : + role = dwc->current_otg_role; +break ; +default : + role =USB_ROLE_DEVICE ; +break ; + } +spin_unlock_irqrestore (&dwc->lock, flags); +return role; +} + +static int dwc3_setup_role_switch (struct dwc3 *dwc) +{ +struct usb_role_switch_desc dwc3_role_switch = {NULL }; + + dwc3_role_switch.fwnode =dev_fwnode (dwc->dev); + dwc3_role_switch.set = dwc3_usb_role_switch_set; + dwc3_role_switch.get = dwc3_usb_role_switch_get; + dwc->role_sw =usb_role_switch_register (dwc->dev, &dwc3_role_switch); +if (IS_ERR (dwc->role_sw)) +return PTR_ERR (dwc->role_sw); + +dwc3_set_mode (dwc,DWC3_GCTL_PRTCAP_DEVICE ); +return 0 ; +} +#else +#define ROLE_SWITCH 0 +#define dwc3_setup_role_switch (x) 0 +#endif +int dwc3_drd_init (struct dwc3 *dwc) {int ret, irq;@@ -484,7 +551,12 @@ int dwc3_drd_init(struct dwc3 *dwc)if (IS_ERR (dwc->edev))return PTR_ERR (dwc->edev); -if (dwc->edev) { +if (ROLE_SWITCH && +device_property_read_bool (dwc->dev,"usb-role-switch" )) { + ret =dwc3_setup_role_switch (dwc); +if (ret <0 ) +return ret; + }else if (dwc->edev) { dwc->edev_nb.notifier_call = dwc3_drd_notifier; ret =extcon_register_notifier (dwc->edev,EXTCON_USB_HOST , &dwc->edev_nb);
drivers/usb/dwc3/drd.c void dwc3_drd_exit(struct dwc3 *dwc) · line 611
Quoted 9 lines
drivers/usb/dwc3/drd.c +3
-0@@ -531,6 +603,9 @@ void dwc3_drd_exit(struct dwc3 *dwc) {unsigned long flags; +if (dwc->role_sw) +usb_role_switch_unregister (dwc->role_sw); +if (dwc->edev)extcon_unregister_notifier (dwc->edev,EXTCON_USB_HOST , &dwc->edev_nb);
This again I've used on the qcs404 and it works nicely.
Re: [PATCH v6 1/8] usb: dwc3: Registering a role switch in the DRD code.
In reply to John StultzQuoted 164 lines · John Stultz
From: Yu Chen <[email protected]>
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.
Cc Greg Kroah-Hartman <[email protected]>Cc Rob Herring <[email protected]>Cc Mark Rutland <[email protected]>CC ShuFan Lee <[email protected]>Cc Heikki Krogerus <[email protected]>Cc Suzuki K Poulose <[email protected]>Cc Chunfeng Yun <[email protected]>Cc Yu Chen <[email protected]>Cc Felipe Balbi <[email protected]>Cc Hans de Goede <[email protected]>Cc Andy Shevchenko <[email protected]>Cc Jun Li <[email protected]>Cc Valentin Schneider <[email protected]>Cc Jack Pham <[email protected]>Suggested-by Heikki Krogerus <[email protected]>Signed-off-by Yu Chen <[email protected]>Signed-off-by John Stultz <[email protected]>Change-Id Ibd89b7eb3e59688895a2d317f3515e6d2705c6f3---
v2: Fixrole_swandrole_switch_default_modedescriptions as
reported by kbuild test robot <[email protected]>v3: Split out the role-switch-default-host logic into its own
patchv5: Drop selecting
CONFIG_USB_ROLE_SWITCH& ifdef dependent codev6: Fix build issue Reported-by: kbuild test robot <[email protected]>
--- drivers/usb/dwc3/core.h | 3 ++ drivers/usb/dwc3/drd.c | 77 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-)drivers/usb/dwc3/core.h +3
-0@@ -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> @@ -951,6 +952,7 @@ struct dwc3_scratchpad_array {* @hsphy_mode: UTMI phy mode, one of following: * - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW +* @role_sw: usb_role_switch handle * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY @@ -1084,6 +1086,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;drivers/usb/dwc3/drd.c +73
-1@@ -476,6 +476,73 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)return edev; } +#ifdef CONFIG_USB_ROLE_SWITCH +#define ROLE_SWITCH 1 +static int dwc3_usb_role_switch_set (struct device *dev,enum usb_role role) +{ +struct dwc3 *dwc =dev_get_drvdata (dev); +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_DEVICE ; +break ; + } + +dwc3_set_mode (dwc, 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); +switch (dwc->current_dr_role) { +case DWC3_GCTL_PRTCAP_HOST : + role =USB_ROLE_HOST ; +break ; +case DWC3_GCTL_PRTCAP_DEVICE : + role =USB_ROLE_DEVICE ; +break ; +case DWC3_GCTL_PRTCAP_OTG : + role = dwc->current_otg_role; +break ; +default : + role =USB_ROLE_DEVICE ; +break ; + } +spin_unlock_irqrestore (&dwc->lock, flags); +return role; +} + +static int dwc3_setup_role_switch (struct dwc3 *dwc) +{ +struct usb_role_switch_desc dwc3_role_switch = {NULL }; + + dwc3_role_switch.fwnode =dev_fwnode (dwc->dev); + dwc3_role_switch.set = dwc3_usb_role_switch_set; + dwc3_role_switch.get = dwc3_usb_role_switch_get; + dwc->role_sw =usb_role_switch_register (dwc->dev, &dwc3_role_switch); +if (IS_ERR (dwc->role_sw)) +return PTR_ERR (dwc->role_sw); + +dwc3_set_mode (dwc,DWC3_GCTL_PRTCAP_DEVICE ); +return 0 ; +} +#else +#define ROLE_SWITCH 0 +#define dwc3_setup_role_switch (x) 0 +#endif +int dwc3_drd_init (struct dwc3 *dwc) {int ret, irq;@@ -484,7 +551,12 @@ int dwc3_drd_init(struct dwc3 *dwc)if (IS_ERR (dwc->edev))return PTR_ERR (dwc->edev); -if (dwc->edev) { +if (ROLE_SWITCH && +device_property_read_bool (dwc->dev,"usb-role-switch" )) { + ret =dwc3_setup_role_switch (dwc); +if (ret <0 ) +return ret; + }else if (dwc->edev) { dwc->edev_nb.notifier_call = dwc3_drd_notifier; ret =extcon_register_notifier (dwc->edev,EXTCON_USB_HOST , &dwc->edev_nb);
drivers/usb/dwc3/drd.c void dwc3_drd_exit(struct dwc3 *dwc) · line 611
Quoted 9 lines
drivers/usb/dwc3/drd.c +3
-0@@ -531,6 +603,9 @@ void dwc3_drd_exit(struct dwc3 *dwc) {unsigned long flags; +if (dwc->role_sw) +usb_role_switch_unregister (dwc->role_sw); +if (dwc->edev)extcon_unregister_notifier (dwc->edev,EXTCON_USB_HOST , &dwc->edev_nb);
Try again ;)
PATCH v6 2/8 dt-bindings: usb: generic: Add role-switch-default-mode binding
In reply to John StultzAdd binding to configure the default role the controller assumes is host mode when the usb role is USB_ROLE_NONE.
---
v5: Switch to string rather then a bool
--- Documentation/devicetree/bindings/usb/generic.txt | 6 ++++++ 1 file changed, 6 insertions(+)
Documentation/devicetree/bindings/usb/generic.txt +6 -0
@@ -34,6 +34,12 @@ Optional properties: 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.txt. + - role-switch-default-mode: indicating if usb-role-switch is enabled, the + device default operation mode of controller while usb + role is USB_ROLE_NONE. Valid arguments are "host" and + "peripheral". Defaults to "peripheral" if not + specified. + This is an attribute to a USB controller such as:
Signature · 1 line
2.17.1
PATCH v6 3/8 usb: dwc3: Add support for role-switch-default-mode binding
In reply to John StultzSupport the new role-switch-default-mode binding for configuring the default role the controller assumes as when the usb role is USB_ROLE_NONE
This patch was split out from a larger patch originally by Yu Chen <[email protected]>
---
v3: Split this patch out from addition of usb-role-switch
handling
v5: Reworked to use string based role-switch-default-mode
--- drivers/usb/dwc3/core.h | 3 +++ drivers/usb/dwc3/drd.c | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-)
drivers/usb/dwc3/core.h +3 -0
@@ -953,6 +953,8 @@ struct dwc3_scratchpad_array {* - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW * @role_sw: usb_role_switch handle +* @role_switch_default_mode: default operation mode of controller while +* usb role is USB_ROLE_NONE. * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY
@@ -1087,6 +1089,7 @@ struct dwc3 {struct notifier_block edev_nb;enum usb_phy_interface hsphy_mode;struct usb_role_switch *role_sw; +enum usb_dr_mode role_switch_default_mode;u32 fladj;u32 irq_gadget;
drivers/usb/dwc3/drd.c +22 -3
@@ -491,7 +491,10 @@ static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role) mode =DWC3_GCTL_PRTCAP_DEVICE ;break ;default : - mode =DWC3_GCTL_PRTCAP_DEVICE ; +if (dwc->role_switch_default_mode ==USB_DR_MODE_HOST ) + mode =DWC3_GCTL_PRTCAP_HOST ; +else + mode =DWC3_GCTL_PRTCAP_DEVICE ;break ; }
@@ -517,7 +520,10 @@ static enum usb_role dwc3_usb_role_switch_get(struct device *dev) role = dwc->current_otg_role;break ;default : - role =USB_ROLE_DEVICE ; +if (dwc->role_switch_default_mode ==USB_DR_MODE_HOST ) + role =USB_ROLE_HOST ; +else + role =USB_ROLE_DEVICE ;break ; }spin_unlock_irqrestore (&dwc->lock, flags);
@@ -527,6 +533,19 @@ static enum usb_role dwc3_usb_role_switch_get(struct device *dev)static int dwc3_setup_role_switch (struct dwc3 *dwc) {struct usb_role_switch_desc dwc3_role_switch = {NULL }; +const char *str; +u32 mode; +int ret; + + ret =device_property_read_string (dwc->dev,"role-switch-default-mode" , + &str); +if (ret >=0 && !strncmp (str,"host" ,strlen ("host" ))) { + dwc->role_switch_default_mode =USB_DR_MODE_HOST ; + mode =DWC3_GCTL_PRTCAP_HOST ; + }else { + dwc->role_switch_default_mode =USB_DR_MODE_PERIPHERAL ; + mode =DWC3_GCTL_PRTCAP_DEVICE ; + } dwc3_role_switch.fwnode =dev_fwnode (dwc->dev); dwc3_role_switch.set = dwc3_usb_role_switch_set;
@@ -535,7 +554,7 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)if (IS_ERR (dwc->role_sw))return PTR_ERR (dwc->role_sw); -dwc3_set_mode (dwc,DWC3_GCTL_PRTCAP_DEVICE ); +dwc3_set_mode (dwc, mode); return 0; }#else
Signature · 1 line
2.17.1
Re: [PATCH v6 3/8] usb: dwc3: Add support for role-switch-default-mode binding
Quoted 105 lines · John Stultz
Support the new role-switch-default-mode binding for configuring the default role the controller assumes as when the usb role is
USB_ROLE_NONEThis patch was split out from a larger patch originally by Yu Chen <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>Cc Rob Herring <[email protected]>Cc Mark Rutland <[email protected]>CC ShuFan Lee <[email protected]>Cc Heikki Krogerus <[email protected]>Cc Suzuki K Poulose <[email protected]>Cc Chunfeng Yun <[email protected]>Cc Yu Chen <[email protected]>Cc Felipe Balbi <[email protected]>Cc Hans de Goede <[email protected]>Cc Andy Shevchenko <[email protected]>Cc Jun Li <[email protected]>Cc Valentin Schneider <[email protected]>Cc Jack Pham <[email protected]>Signed-off-by John Stultz <[email protected]>Change-Id Ic6e4df1109b350deaecdc69f667d49ce91d599f3---
v3: Split this patch out from addition of usb-role-switch
handling
v5: Reworked to use string based role-switch-default-mode--- drivers/usb/dwc3/core.h | 3 +++ drivers/usb/dwc3/drd.c | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-)drivers/usb/dwc3/core.h +3
-0@@ -953,6 +953,8 @@ struct dwc3_scratchpad_array {* - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW * @role_sw: usb_role_switch handle +* @role_switch_default_mode: default operation mode of controller while +* usb role is USB_ROLE_NONE. * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY @@ -1087,6 +1089,7 @@ struct dwc3 {struct notifier_block edev_nb;enum usb_phy_interface hsphy_mode;struct usb_role_switch *role_sw; +enum usb_dr_mode role_switch_default_mode;u32 fladj;u32 irq_gadget;drivers/usb/dwc3/drd.c +21
-2@@ -491,7 +491,10 @@ static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role) mode =DWC3_GCTL_PRTCAP_DEVICE ;break ;default : - mode =DWC3_GCTL_PRTCAP_DEVICE ; +if (dwc->role_switch_default_mode ==USB_DR_MODE_HOST ) + mode =DWC3_GCTL_PRTCAP_HOST ; +else + mode =DWC3_GCTL_PRTCAP_DEVICE ;break ; }@@ -517,7 +520,10 @@ static enum usb_role dwc3_usb_role_switch_get(struct device *dev) role = dwc->current_otg_role;break ;default : - role =USB_ROLE_DEVICE ; +if (dwc->role_switch_default_mode ==USB_DR_MODE_HOST ) + role =USB_ROLE_HOST ; +else + role =USB_ROLE_DEVICE ;break ; }spin_unlock_irqrestore (&dwc->lock, flags);@@ -527,6 +533,19 @@ static enum usb_role dwc3_usb_role_switch_get(struct device *dev)static int dwc3_setup_role_switch (struct dwc3 *dwc) {struct usb_role_switch_desc dwc3_role_switch = {NULL }; +const char *str; +u32 mode; +int ret; + + ret =device_property_read_string (dwc->dev,"role-switch-default-mode" , + &str); +if (ret >=0 && !strncmp (str,"host" ,strlen ("host" ))) { + dwc->role_switch_default_mode =USB_DR_MODE_HOST ; + mode =DWC3_GCTL_PRTCAP_HOST ; + }else { + dwc->role_switch_default_mode =USB_DR_MODE_PERIPHERAL ; + mode =DWC3_GCTL_PRTCAP_DEVICE ; + } dwc3_role_switch.fwnode =dev_fwnode (dwc->dev); dwc3_role_switch.set = dwc3_usb_role_switch_set;
drivers/usb/dwc3/drd.c static int dwc3_setup_role_switch(struct dwc3 *dwc) · line 560
Quoted 8 lines
drivers/usb/dwc3/drd.c +1
-1@@ -535,7 +554,7 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)if (IS_ERR (dwc->role_sw))return PTR_ERR (dwc->role_sw); -dwc3_set_mode (dwc,DWC3_GCTL_PRTCAP_DEVICE ); +dwc3_set_mode (dwc, mode); return 0; }#else
I've used this on a qcs404 - it works for me.
Re: [PATCH v6 3/8] usb: dwc3: Add support for role-switch-default-mode binding
In reply to John StultzQuoted 105 lines · John Stultz
Support the new role-switch-default-mode binding for configuring the default role the controller assumes as when the usb role is
USB_ROLE_NONEThis patch was split out from a larger patch originally by Yu Chen <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>Cc Rob Herring <[email protected]>Cc Mark Rutland <[email protected]>CC ShuFan Lee <[email protected]>Cc Heikki Krogerus <[email protected]>Cc Suzuki K Poulose <[email protected]>Cc Chunfeng Yun <[email protected]>Cc Yu Chen <[email protected]>Cc Felipe Balbi <[email protected]>Cc Hans de Goede <[email protected]>Cc Andy Shevchenko <[email protected]>Cc Jun Li <[email protected]>Cc Valentin Schneider <[email protected]>Cc Jack Pham <[email protected]>Signed-off-by John Stultz <[email protected]>Change-Id Ic6e4df1109b350deaecdc69f667d49ce91d599f3---
v3: Split this patch out from addition of usb-role-switch
handling
v5: Reworked to use string based role-switch-default-mode--- drivers/usb/dwc3/core.h | 3 +++ drivers/usb/dwc3/drd.c | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-)drivers/usb/dwc3/core.h +3
-0@@ -953,6 +953,8 @@ struct dwc3_scratchpad_array {* - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW * @role_sw: usb_role_switch handle +* @role_switch_default_mode: default operation mode of controller while +* usb role is USB_ROLE_NONE. * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY @@ -1087,6 +1089,7 @@ struct dwc3 {struct notifier_block edev_nb;enum usb_phy_interface hsphy_mode;struct usb_role_switch *role_sw; +enum usb_dr_mode role_switch_default_mode;u32 fladj;u32 irq_gadget;drivers/usb/dwc3/drd.c +21
-2@@ -491,7 +491,10 @@ static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role) mode =DWC3_GCTL_PRTCAP_DEVICE ;break ;default : - mode =DWC3_GCTL_PRTCAP_DEVICE ; +if (dwc->role_switch_default_mode ==USB_DR_MODE_HOST ) + mode =DWC3_GCTL_PRTCAP_HOST ; +else + mode =DWC3_GCTL_PRTCAP_DEVICE ;break ; }@@ -517,7 +520,10 @@ static enum usb_role dwc3_usb_role_switch_get(struct device *dev) role = dwc->current_otg_role;break ;default : - role =USB_ROLE_DEVICE ; +if (dwc->role_switch_default_mode ==USB_DR_MODE_HOST ) + role =USB_ROLE_HOST ; +else + role =USB_ROLE_DEVICE ;break ; }spin_unlock_irqrestore (&dwc->lock, flags);@@ -527,6 +533,19 @@ static enum usb_role dwc3_usb_role_switch_get(struct device *dev)static int dwc3_setup_role_switch (struct dwc3 *dwc) {struct usb_role_switch_desc dwc3_role_switch = {NULL }; +const char *str; +u32 mode; +int ret; + + ret =device_property_read_string (dwc->dev,"role-switch-default-mode" , + &str); +if (ret >=0 && !strncmp (str,"host" ,strlen ("host" ))) { + dwc->role_switch_default_mode =USB_DR_MODE_HOST ; + mode =DWC3_GCTL_PRTCAP_HOST ; + }else { + dwc->role_switch_default_mode =USB_DR_MODE_PERIPHERAL ; + mode =DWC3_GCTL_PRTCAP_DEVICE ; + } dwc3_role_switch.fwnode =dev_fwnode (dwc->dev); dwc3_role_switch.set = dwc3_usb_role_switch_set;
drivers/usb/dwc3/drd.c static int dwc3_setup_role_switch(struct dwc3 *dwc) · line 560
Quoted 8 lines
drivers/usb/dwc3/drd.c +1
-1@@ -535,7 +554,7 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)if (IS_ERR (dwc->role_sw))return PTR_ERR (dwc->role_sw); -dwc3_set_mode (dwc,DWC3_GCTL_PRTCAP_DEVICE ); +dwc3_set_mode (dwc, mode); return 0; }#else
PATCH v6 4/8 dt-bindings: usb: dwc3: Allow clock list & resets to be more flexible
In reply to John StultzRather then adding another device specific binding to support hikey960, Rob Herring suggested we expand the current dwc3 binding to allow for variable numbers of clocks and resets.
--- Documentation/devicetree/bindings/usb/dwc3.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/usb/dwc3.txt +3 -2
@@ -7,7 +7,8 @@ Required properties: - compatible: must be "snps,dwc3" - reg : Address and length of the register set for the device - interrupts: Interrupts used by the dwc3 controller. - - clock-names: should contain "ref", "bus_early", "suspend" + - clock-names: list of clock names. Ideally should be "ref", + "bus_early", "suspend" but may be less or more. - clocks: list of phandle and clock specifier pairs corresponding to entries in the clock-names property.
@@ -36,7 +37,7 @@ Optional properties: - phys: from the *Generic PHY* bindings - phy-names: from the *Generic PHY* bindings; supported names are "usb2-phy" or "usb3-phy". - - resets: a single pair of phandle and reset specifier + - resets: set of phandle and reset specifier pairs - snps,usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable - snps,dis-start-transfer-quirk: when set, disable isoc START TRANSFER command
Signature · 1 line
2.17.1
PATCH v6 5/8 usb: dwc3: Rework clock initialization to be more flexible
In reply to John StultzThe dwc3 core binding specifies three clocks:
ref, bus_early, and suspend
which are all controlled in the driver together.
However some variants of the hardware my not have all three clks, or some may have more. Usually this was handled by using the dwc3-of-simple glue driver, but that resulted in a proliferation of bindings for for every variant, when the only difference was the clocks and resets lists.
So this patch reworks the reading of the clks from the dts to use devm_clk_bulk_get_all() will will fetch all the clocks specified in the dts together.
This patch was recommended by Rob Herring <[email protected]> as an alternative to creating multiple bindings for each variant of hardware.
---
v3: Rework dwc3 core rather then adding another dwc-of-simple
binding.
v6: Re-introduce this patch, on Rob's suggestion
--- drivers/usb/dwc3/core.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-)
drivers/usb/dwc3/core.c +5 -15
@@ -289,12 +289,6 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)return 0 ; } -static const struct clk_bulk_data dwc3_core_clks[] = { - { .id ="ref" }, - { .id ="bus_early" }, - { .id ="suspend" }, -}; -/* * dwc3_frame_length_adjustment - Adjusts frame length if required * @dwc3: Pointer to our controller context structure
@@ -1438,11 +1432,6 @@ static int dwc3_probe(struct platform_device *pdev)if (!dwc)return -ENOMEM ; - dwc->clks =devm_kmemdup (dev, dwc3_core_clks,sizeof (dwc3_core_clks), -GFP_KERNEL ); -if (!dwc->clks) -return -ENOMEM ; - dwc->dev = dev; res =platform_get_resource (pdev,IORESOURCE_MEM ,0 );
@@ -1478,17 +1467,18 @@ static int dwc3_probe(struct platform_device *pdev)return PTR_ERR (dwc->reset);if (dev->of_node) { - dwc->num_clks =ARRAY_SIZE (dwc3_core_clks); - - ret =devm_clk_bulk_get (dev, dwc->num_clks, dwc->clks); + ret =devm_clk_bulk_get_all (dev, &dwc->clks);if (ret == -EPROBE_DEFER )return ret;/* * Clocks are optional, but new DT platforms should support all * clocks as required by the DT-binding. */ -if (ret) +if (ret <0 ) dwc->num_clks =0 ; +else + dwc->num_clks = ret; + } ret =reset_control_deassert (dwc->reset);
Signature · 1 line
2.17.1
PATCH v6 6/8 usb: dwc3: Rework resets initialization to be more flexible
In reply to John StultzThe dwc3 core binding specifies one reset.
However some variants of the hardware may have more. Previously this was handled by using the dwc3-of-simple glue driver, but that resulted in a proliferation of bindings for for every variant, when the only difference was the clocks and resets lists.
So this patch reworks the reading of the resets to fetch all the resets specified in the dts together.
This patch was recommended by Rob Herring <[email protected]> as an alternative to creating multiple bindings for each variant of hardware.
---
v3: Rework dwc3 core rather then adding another dwc-of-simple
binding.
v6: Re-introduce this patch, on Rob's suggestion
--- drivers/usb/dwc3/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/dwc3/core.c +1 -1
@@ -1462,7 +1462,7 @@ static int dwc3_probe(struct platform_device *pdev)dwc3_get_properties (dwc); - dwc->reset =devm_reset_control_get_optional_shared (dev,NULL ); + dwc->reset =devm_reset_control_array_get (dev, true, true);if (IS_ERR (dwc->reset))return PTR_ERR (dwc->reset);
Signature · 1 line
2.17.1
PATCH v6 7/8 dt-bindings: misc: Add bindings for HiSilicon usb hub and data role switch functionality on HiKey960
In reply to John StultzFrom: Yu Chen <[email protected]>
This patch adds binding documentation to support usb hub and usb data role switch of Hisilicon HiKey960 Board.
---
v3: Reworked as usb-role-switch intermediary
--- .../bindings/misc/hisilicon-hikey-usb.txt | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt new file +40 -0
@@ -0,0 +1,40 @@ +Support usb hub and usb data role switch of Hisilicon HiKey960 Board. + +----------------------------- + +Required properties: +- compatible: "hisilicon,gpio_hubv1" +- typec-vbus-gpios: gpio to control the vbus of typeC port +- otg-switch-gpios: gpio to switch DP & DM between the hub and typeC port +- hub-vdd33-en-gpios: gpio to enable the power of hub +- pinctrl-names: pin configuration state name ("default") +- pinctrl-0: pinctrl config +- usb-role-switch: flags the driver as a role switch provider +- ports: two endpoints to connect the usb core role switch provider + to the usb-c tcpm driver. + +Example +----- + hisi_hikey_usb: hisi_hikey_usb { + compatible = "hisilicon,gpio_hubv1"; + typec-vbus-gpios = <&gpio25 2 GPIO_ACTIVE_HIGH>; + otg-switch-gpios = <&gpio25 6 GPIO_ACTIVE_HIGH>; + hub-vdd33-en-gpios = <&gpio5 6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usbhub5734_pmx_func>; + usb-role-switch; + + port { + #address-cells = <1>; + #size-cells = <0>; + + hikey_usb_ep0: endpoint@0 { + reg = <0>; + remote-endpoint = <&dwc3_role_switch>; + }; + hikey_usb_ep1: endpoint@1 { + reg = <1>; + remote-endpoint = <&rt1711h_ep>; + }; + }; + };
Signature · 1 line
2.17.1
PATCH v6 8/8 misc: hisi_hikey_usb: Driver to support usb functionality of Hikey960
In reply to John StultzFrom: Yu Chen <[email protected]>
The HiKey960 has a fairly complex USB configuration due to it needing to support a USB-C port for host/device mode and multiple USB-A ports in host mode using a single USB controller.
See schematics here:
https://github.com/96boards/documentation/raw/master/consumer/hikey/hikey960/hardware-docs/HiKey960_Schematics.pdf
This driver acts as a usb-role-switch intermediary, intercepting the role switch notifications from the tcpm code, and passing them on to the dwc3 core.
In doing so, it also controls the onboard hub and power gpios in order to properly route the data lines between the USB-C port and the onboard hub to the USB-A ports.
NOTE: It was noted that controlling the TYPEC_VBUS_POWER_OFF and TYPEC_VBUS_POWER_ON values here is not reccomended. I'm looking for a way to remove that bit from the logic here, but wanted to still get feedback on this approach.
[jstultz: Major rework to make the driver a usb-role-switch
intermediary]
---
v3:
* Major rework to make the driver a usb-role-switch intermediary rather then trying to do notifier callbacks from the role switch logic
--- drivers/misc/Kconfig | 6 ++ drivers/misc/Makefile | 1 + drivers/misc/hisi_hikey_usb.c | 178 ++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 drivers/misc/hisi_hikey_usb.c
drivers/misc/Kconfig +6 -0
@@ -465,6 +465,12 @@ config PVPANIC a paravirtualized device provided by QEMU; it lets a virtual machine (guest) communicate panic events to the host. +config HISI_HIKEY_USB + tristate "USB functionality of HiSilicon Hikey Platform" + depends on OF && GPIOLIB + help + If you say yes here you get support for usb functionality of HiSilicon Hikey Platform. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig"
drivers/misc/Makefile +1 -0
@@ -57,3 +57,4 @@ obj-y += cardreader/ obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_HABANA_AI) += habanalabs/ obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o +obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o
drivers/misc/hisi_hikey_usb.c new file +178 -0
178 lines not on this page · raw message
Signature · 1 line
2.17.1
Greg Kroah-Hartman
maintainerRe: [PATCH v6 8/8] misc: hisi_hikey_usb: Driver to support usb functionality of Hikey960
Quoted 39 lines · John Stultz
From: Yu Chen <[email protected]>
The HiKey960 has a fairly complex USB configuration due to it needing to support a USB-C port for host/device mode and multiple USB-A ports in host mode using a single USB controller.
See schematics here:
https://github.com/96boards/documentation/raw/master/consumer/hikey/hikey960/hardware-docs/HiKey960_Schematics.pdfThis driver acts as a usb-role-switch intermediary, intercepting the role switch notifications from the tcpm code, and passing them on to the dwc3 core.
In doing so, it also controls the onboard hub and power gpios in order to properly route the data lines between the USB-C port and the onboard hub to the USB-A ports.
NOTE: It was noted that controlling the
TYPEC_VBUS_POWER_OFFandTYPEC_VBUS_POWER_ONvalues here is not reccomended. I'm looking for a way to remove that bit from the logic here, but wanted to still get feedback on this approach.Cc Greg Kroah-Hartman <[email protected]>Cc Rob Herring <[email protected]>Cc Mark Rutland <[email protected]>CC ShuFan Lee <[email protected]>Cc Heikki Krogerus <[email protected]>Cc Suzuki K Poulose <[email protected]>Cc Chunfeng Yun <[email protected]>Cc Yu Chen <[email protected]>Cc Felipe Balbi <[email protected]>Cc Hans de Goede <[email protected]>Cc Andy Shevchenko <[email protected]>Cc Jun Li <[email protected]>Cc Valentin Schneider <[email protected]>Cc Jack Pham <[email protected]>Signed-off-by Yu Chen <[email protected]>
Quoted 4 lines
[jstultz: Major rework to make the driver a usb-role-switch
intermediary]Signed-off-by John Stultz <[email protected]>Change-Id Icf381520abd46d083750d01f91e478321560fbf9
Checkpatch is your friend :)