Re: [PATCH] usb: mtu3: fix missing include of mtu3_dr.h
On Thu, 2019-10-17 at 18:27 +0100, Ben Dooks (Codethink) wrote: > The declarations of ssusb_gadget_{init,exit} are > in the mtu3_dr.h file but the code does that implements > them does not include this. Add the include to fix the > following sparse warnigns: > > drivers/usb/mtu3/mtu3_core.c:825:5: warning: symbol 'ssusb_gadget_init' was > not declared. Should it be static? > drivers/usb/mtu3/mtu3_core.c:925:6: warning: symbol 'ssusb_gadget_exit' was > not declared. Should it be static? > > Signed-off-by: Ben Dooks > --- > Cc: Chunfeng Yun > Cc: Greg Kroah-Hartman > Cc: linux-usb@vger.kernel.org > Cc: linux-arm-ker...@lists.infradead.org > Cc: linux-media...@lists.infradead.org > --- > drivers/usb/mtu3/mtu3_core.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c > index c3d5c1206eec..9dd02160cca9 100644 > --- a/drivers/usb/mtu3/mtu3_core.c > +++ b/drivers/usb/mtu3/mtu3_core.c > @@ -16,6 +16,7 @@ > #include > > #include "mtu3.h" > +#include "mtu3_dr.h" > #include "mtu3_debug.h" > #include "mtu3_trace.h" Acked-by: Chunfeng Yun Thanks a lot >
Re: [PATCH 3/3] net: cdc_ncm: Add ACPI MAC address pass through functionality
On Thu, 2019-09-05 at 21:01 +, charles.h...@dellteam.com wrote: > This change adds support to cdc_ncm for ACPI MAC address pass through > functionality that also exists in the Realtek r8152 driver. This is in > support of Dell's Universal Dock D6000, to give it the same feature > capability as is currently available in Windows and advertized on Dell's > product web site. > > Signed-off-by: Charles Hyde > Cc: Mario Limonciello > Cc: chip.program...@gmail.com > Cc: Oliver Neukum > Cc: "Rafael J. Wysocki" > Cc: Len Brown > Cc: linux-usb@vger.kernel.org > Cc: linux-a...@vger.kernel.org > --- > drivers/net/usb/cdc_ncm.c | 74 +-- > 1 file changed, 64 insertions(+), 10 deletions(-) > > diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c > index 85093579612f..e0152d44f5af 100644 > --- a/drivers/net/usb/cdc_ncm.c > +++ b/drivers/net/usb/cdc_ncm.c > @@ -52,6 +52,7 @@ > #include > #include > #include > +#include > > #if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM) > static bool prefer_mbim = true; > @@ -833,6 +834,45 @@ static const struct net_device_ops cdc_ncm_netdev_ops = { > .ndo_validate_addr = eth_validate_addr, > }; > > +static int get_ethernet_addr(struct usb_interface *intf) > +{ > + struct sockaddr sa; > + struct usbnet *dev = usb_get_intfdata(intf); > + struct cdc_ncm_ctx *ctx; > + int ret = 0; > + > + if (!dev) > + return 0; > + > + ctx = (struct cdc_ncm_ctx *)dev->data[0]; > + if (!ctx->ether_desc) > + return 0; > + > + ret = cdc_ncm_get_ethernet_address(dev, ctx); > + if (ret) { > + dev_dbg(&intf->dev, "failed to get mac address\n"); > + return ret; > + } > + > + /* Check for a Dell Universal Dock D6000 before checking if ACPI > + * supports MAC address pass through. > + */ > + if (strstr(dev->udev->product, "D6000")) { > + sa.sa_family = dev->net->type; > + if (get_acpi_mac_passthru(sa.sa_data)) { > + if (!memcmp(dev->net->dev_addr, sa.sa_data, > + ETH_ALEN)) { > + if (!cdc_ncm_set_ethernet_address(dev, &sa)) How about use one if-statement instead of these three if-statement? > + memcpy(dev->net->dev_addr, sa.sa_data, > +ETH_ALEN); > + } > + } > + } > + dev_info(&intf->dev, "MAC-Address: %pM\n", dev->net->dev_addr); > + > + return 0; > +} > + > int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 > data_altsetting, int drvflags) > { > struct cdc_ncm_ctx *ctx; > @@ -983,14 +1023,8 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct > usb_interface *intf, u8 data_ > usb_set_intfdata(ctx->data, dev); > usb_set_intfdata(ctx->control, dev); > > - if (ctx->ether_desc) { > - temp = usbnet_get_ethernet_addr(dev, > ctx->ether_desc->iMACAddress); > - if (temp) { > - dev_dbg(&intf->dev, "failed to get mac address\n"); > - goto error2; > - } > - dev_info(&intf->dev, "MAC-Address: %pM\n", dev->net->dev_addr); > - } > + if (get_ethernet_addr(intf)) > + goto error2; > > /* finish setting up the device specific data */ > cdc_ncm_setup(dev); > @@ -1716,6 +1750,25 @@ static void cdc_ncm_status(struct usbnet *dev, struct > urb *urb) > } > } > > +static int cdc_ncm_resume(struct usb_interface *intf) > +{ > + int ret; > + > + ret = usbnet_resume(intf); > + if (ret == 0) > + get_ethernet_addr(intf); > + > + return ret; > +} > + > +static int cdc_ncm_post_reset(struct usb_interface *intf) > +{ > + /* reset the MAC address in case of policy change */ > + get_ethernet_addr(intf); > + > + return 0; > +} > + > static const struct driver_info cdc_ncm_info = { > .description = "CDC NCM", > .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET > @@ -1848,8 +1901,9 @@ static struct usb_driver cdc_ncm_driver = { > .probe = usbnet_probe, > .disconnect = usbnet_disconnect, > .suspend = usbnet_suspend, > - .resume = usbnet_resume, > - .reset_resume = usbnet_resume, > + .resume = cdc_ncm_resume, > + .reset_resume = cdc_ncm_resume, > + .post_reset = cdc_ncm_post_reset, > .supports_autosuspend = 1, > .disable_hub_initiated_lpm = 1, > };
Re: [PATCH next v10 03/11] dt-bindings: usb: add binding for USB GPIO based connection detection driver
On Tue, 2019-08-27 at 13:31 -0500, Rob Herring wrote: > On Fri, Aug 23, 2019 at 03:57:13PM +0800, Chunfeng Yun wrote: > > It's used to support dual role switch via GPIO when use Type-B > > receptacle, typically the USB ID pin is connected to an input > > GPIO, and also used to enable/disable device when the USB Vbus > > pin is connected to an input GPIO. > > > > Signed-off-by: Chunfeng Yun > > --- > > v9~v10 no changes > > > > v8 changes: > > 1. rename the title > > 2. change the compatible as "linux,usb-conn-gpio" instead of > > "linux,typeb-conn-gpio" > > I don't think that is an improvement. How about 'gpio-usb-b-connector' > to be consistent. Ok > > > > > v7 changes: > > 1. add description for device only mode > > > > v6 changes: > > 1. remove status and port nodes in example > > 2. make vbus-supply as optional property > > > > v5 changes: > > 1. treat type-B connector as child device of USB controller's, but not > > as a separate virtual device, suggested by Rob > > 2. put connector's port node under connector node, suggested by Rob > > > > v4 no changes > > > > v3 changes: > > 1. treat type-B connector as a virtual device, but not child device of > > USB controller's > > > > v2 changes: > > 1. new patch to make binding clear suggested by Hans > > --- > > .../devicetree/bindings/usb/usb-conn-gpio.txt | 31 +++ > > 1 file changed, 31 insertions(+) > > create mode 100644 Documentation/devicetree/bindings/usb/usb-conn-gpio.txt > > > > diff --git a/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt > > b/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt > > new file mode 100644 > > index ..d4d107fedc22 > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt > > @@ -0,0 +1,31 @@ > > +USB GPIO Based Connection Detection > > + > > +This is typically used to switch dual role mode from the USB ID pin > > connected > > +to an input GPIO, and also used to enable/disable device mode from the USB > > +Vbus pin connected to an input GPIO. > > + > > +Required properties: > > +- compatible : should include "linux,usb-conn-gpio" and "usb-b-connector". > > +- id-gpios, vbus-gpios : input gpios, either one of them must be present, > > + and both can be present as well. > > + see connector/usb-connector.txt > > + > > +Optional properties: > > +- vbus-supply : can be present if needed when supports dual role mode. > > + see connector/usb-connector.txt > > + > > +- Sub-nodes: > > + - port : can be present. > > + see graph.txt > > + > > +Example: > > + > > +&mtu3 { > > + connector { > > + compatible = "linux,usb-conn-gpio", "usb-b-connector"; > > + label = "micro-USB"; > > 'label' is for a human identifying a particular connector when there are > multiple (of the same type). So not a great example here. Got it, will remove it Thanks a lot > > > + type = "micro"; > > + id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>; > > + vbus-supply = <&usb_p0_vbus>; > > + }; > > +}; > > -- > > 2.23.0 > >
[PATCH next v10 05/11] usb: roles: Introduce stubs for the exiting functions in role.h
From: Yu Chen This patch adds stubs for the exiting functions while CONFIG_USB_ROLE_SWITCH does not enabled. Cc: Greg Kroah-Hartman Cc: Heikki Krogerus Cc: Hans de Goede Cc: Andy Shevchenko Cc: John Stultz Reviewed-by: Heikki Krogerus Signed-off-by: Yu Chen Signed-off-by: Chunfeng Yun --- v8~v10 no changes v7: add Signed-off-by Chunfeng v6: merge this patch [1] into this series to add new API [1] https://patchwork.kernel.org/patch/10909971/ --- include/linux/usb/role.h | 30 ++ 1 file changed, 30 insertions(+) diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h index c05ffa6abda9..da2b9641b877 100644 --- a/include/linux/usb/role.h +++ b/include/linux/usb/role.h @@ -42,6 +42,8 @@ struct usb_role_switch_desc { bool allow_userspace_control; }; + +#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); struct usb_role_switch *usb_role_switch_get(struct device *dev); @@ -51,5 +53,33 @@ struct usb_role_switch * usb_role_switch_register(struct device *parent, const struct usb_role_switch_desc *desc); void usb_role_switch_unregister(struct usb_role_switch *sw); +#else +static inline int usb_role_switch_set_role(struct usb_role_switch *sw, + enum usb_role role) +{ + return 0; +} + +static inline enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) +{ + return USB_ROLE_NONE; +} + +static inline struct usb_role_switch *usb_role_switch_get(struct device *dev) +{ + return ERR_PTR(-ENODEV); +} + +static inline void usb_role_switch_put(struct usb_role_switch *sw) { } + +static inline struct usb_role_switch * +usb_role_switch_register(struct device *parent, +const struct usb_role_switch_desc *desc) +{ + return ERR_PTR(-ENODEV); +} + +static inline void usb_role_switch_unregister(struct usb_role_switch *sw) { } +#endif #endif /* __LINUX_USB_ROLE_H */ -- 2.23.0
[PATCH next v10 02/11] dt-bindings: connector: add optional properties for Type-B
Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for usb-b-connector Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring --- v6~v10 no changes v5 changes: 1. add reviewed by Rob v4 no changes v3 changes: 1. add GPIO direction, and use fixed-regulator for GPIO controlled VBUS regulator suggested by Rob; v2 changes: 1. describe more clear for vbus-gpios and vbus-supply suggested by Hans --- .../bindings/connector/usb-connector.txt | 14 ++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt index cef556d4e5ee..d357987181ee 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.txt +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt @@ -17,6 +17,20 @@ Optional properties: - self-powered: Set this property if the usb device that has its own power source. +Optional properties for usb-b-connector: +- id-gpios: an input gpio for USB ID pin. +- vbus-gpios: an input gpio for USB VBUS pin, used to detect presence of + VBUS 5V. + see gpio/gpio.txt. +- vbus-supply: a phandle to the regulator for USB VBUS if needed when host + mode or dual role mode is supported. + Particularly, if use an output GPIO to control a VBUS regulator, should + model it as a regulator. + see regulator/fixed-regulator.yaml +- pinctrl-names : a pinctrl state named "default" is optional +- pinctrl-0 : pin control group + see pinctrl/pinctrl-bindings.txt + Optional properties for usb-c-connector: - power-role: should be one of "source", "sink" or "dual"(DRP) if typec connector has power support. -- 2.23.0
[PATCH next v10 00/11] add USB GPIO based connection detection driver
Because the USB Connector is introduced and the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated, meanwhile there is no available common driver when use Type-B connector, typically using an input GPIO to detect USB ID pin. This patch series introduce a USB GPIO based connection detection driver and try to replace the function provided by extcon-usb-gpio driver. v10 changes: 1. revert commit log changes of [06/11] and [07/11] v9 changes: 1. replace signed-off-by by suggested-by Heikki 2. add reviewed-by Linus 3. use class_find_device_by_fwnode() introduced by series [1] [1]: https://lore.kernel.org/patchwork/patch/1103630/ [v3,1/7] drivers: Introduce device lookup variants by name they are already in: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/log/drivers/base/core.c?h=driver-core-next v8 changes: 1. rename the driver's name suggested by Heikki 2. move the driver from usb/roles/ into usb/common/ suggested by Heikki 3. introduce Kconfig for usb common core to add the new driver 4. modify binding of the driver 5. rename the subject title v7 changes: 1. [5/10]: add signed-off-by Chunfeng 2. [6/10]: add signed-off-by Chunfeng 3. [6/10]: depends on linux-next of Rafael's tree [1] 4. [7/10]: add signed-off-by Chunfeng and tested-by Biju 5. [9/10]: add tested-by Nagarjuna, and remove DEV_PMS_OPS suggested by Andy [1] https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git/log/?h=linux-next v6 changes: 1. merge [1] and [2] into this series 2. don't use graph anymore to find usb-role-switch 3. abandon [3] and introduce three patches (6, 7, 8 in this series) to rebuild APIs getting usb-role-switch [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ [2]: [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ [3]: [PATCH v5 4/6] usb: roles: add API to get usb_role_switch by node v5 changes: 1. remove linux/of.h and put usb_role_switch when error happens, suggested by Biju 2. treat Type-B connector as USB controller's child, but not as a virtual device, suggested by Rob 3. provide and use generic property "usb-role-switch", see [1], suggested by Rob Note: this series still depends on [2] [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ [2]: [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v4 changes: 1. use switch_fwnode_match() to find fwnode suggested by Heikki 2. assign fwnode member of usb_role_switch struct suggested by Heikki 3. make [4/6] depend on [2] 3. remove linux/gpio.h suggested by Linus 4. put node when error happens [4/6] usb: roles: add API to get usb_role_switch by node [2] [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v3 changes: 1. add GPIO direction, and use fixed-regulator for GPIO controlled VBUS regulator suggested by Rob; 2. rebuild fwnode_usb_role_switch_get() suggested by Andy and Heikki 3. treat the type-B connector as a virtual device; 4. change file name of driver again 5. select USB_ROLE_SWITCH in mtu3/Kconfig suggested by Heikki 6. rename ssusb_mode_manual_switch() to ssusb_mode_switch() v2 changes: 1. make binding clear, and add a extra compatible suggested by Hans Chunfeng Yun (8): dt-binding: usb: add usb-role-switch property dt-bindings: connector: add optional properties for Type-B dt-bindings: usb: add binding for USB GPIO based connection detection driver dt-bindings: usb: mtu3: add properties about USB Role Switch usb: roles: get usb-role-switch from parent usb: common: create Kconfig file usb: common: add USB GPIO based connection detection driver usb: mtu3: register a USB Role Switch for dual role mode Heikki Krogerus (2): device connection: Add fwnode_connection_find_match() usb: roles: Add fwnode_usb_role_switch_get() function Yu Chen (1): usb: roles: Introduce stubs for the exiting functions in role.h .../bindings/connector/usb-connector.txt | 14 + .../devicetree/bindings/usb/generic.txt | 4 + .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 + .../devicetree/bindings/usb/usb-conn-gpio.txt | 31 ++ drivers/base/devcon.c | 43 ++- drivers/usb/Kconfig | 35 +-- drivers/usb/common/Kconfig| 51 drivers/usb/common/Makefile | 1 + drivers/usb/common/usb-conn-gpio.c| 284 ++ drivers/usb/mtu3/Kconfig | 1 + drivers/usb/mtu3/mtu3.h | 5 + drivers/usb/mtu3/mtu3
[PATCH next v10 03/11] dt-bindings: usb: add binding for USB GPIO based connection detection driver
It's used to support dual role switch via GPIO when use Type-B receptacle, typically the USB ID pin is connected to an input GPIO, and also used to enable/disable device when the USB Vbus pin is connected to an input GPIO. Signed-off-by: Chunfeng Yun --- v9~v10 no changes v8 changes: 1. rename the title 2. change the compatible as "linux,usb-conn-gpio" instead of "linux,typeb-conn-gpio" v7 changes: 1. add description for device only mode v6 changes: 1. remove status and port nodes in example 2. make vbus-supply as optional property v5 changes: 1. treat type-B connector as child device of USB controller's, but not as a separate virtual device, suggested by Rob 2. put connector's port node under connector node, suggested by Rob v4 no changes v3 changes: 1. treat type-B connector as a virtual device, but not child device of USB controller's v2 changes: 1. new patch to make binding clear suggested by Hans --- .../devicetree/bindings/usb/usb-conn-gpio.txt | 31 +++ 1 file changed, 31 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/usb-conn-gpio.txt diff --git a/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt b/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt new file mode 100644 index ..d4d107fedc22 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt @@ -0,0 +1,31 @@ +USB GPIO Based Connection Detection + +This is typically used to switch dual role mode from the USB ID pin connected +to an input GPIO, and also used to enable/disable device mode from the USB +Vbus pin connected to an input GPIO. + +Required properties: +- compatible : should include "linux,usb-conn-gpio" and "usb-b-connector". +- id-gpios, vbus-gpios : input gpios, either one of them must be present, + and both can be present as well. + see connector/usb-connector.txt + +Optional properties: +- vbus-supply : can be present if needed when supports dual role mode. + see connector/usb-connector.txt + +- Sub-nodes: + - port : can be present. + see graph.txt + +Example: + +&mtu3 { + connector { + compatible = "linux,usb-conn-gpio", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb_p0_vbus>; + }; +}; -- 2.23.0
[PATCH next v10 06/11] device connection: Add fwnode_connection_find_match()
From: Heikki Krogerus The fwnode_connection_find_match() function is exactly the same as device_connection_find_match(), except it takes struct fwnode_handle as parameter instead of struct device. That allows locating device connections before the device entries have been created. Signed-off-by: Heikki Krogerus Signed-off-by: Chunfeng Yun --- v10: revert changes of v9 v9: replace signed-off-by by suggested-by Heikki v8: no changes v7: rebased on Rafael's tree [1] (after rc4), provided by Heikki [1] https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git/log/?h=linux-next v6: new patch --- drivers/base/devcon.c | 43 ++ include/linux/device.h | 10 +++--- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c index 1d488dc5dd0c..14e2178e09f8 100644 --- a/drivers/base/devcon.c +++ b/drivers/base/devcon.c @@ -12,9 +12,6 @@ static DEFINE_MUTEX(devcon_lock); static LIST_HEAD(devcon_list); -typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, - void *data); - static void * fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id, void *data, devcon_match_fn_t match) @@ -60,6 +57,34 @@ fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id, return NULL; } +/** + * fwnode_connection_find_match - Find connection from a device node + * @fwnode: Device node with the connection + * @con_id: Identifier for the connection + * @data: Data for the match function + * @match: Function to check and convert the connection description + * + * Find a connection with unique identifier @con_id between @fwnode and another + * device node. @match will be used to convert the connection description to + * data the caller is expecting to be returned. + */ +void *fwnode_connection_find_match(struct fwnode_handle *fwnode, + const char *con_id, void *data, + devcon_match_fn_t match) +{ + void *ret; + + if (!fwnode || !match) + return NULL; + + ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); + if (ret) + return ret; + + return fwnode_devcon_match(fwnode, con_id, data, match); +} +EXPORT_SYMBOL_GPL(fwnode_connection_find_match); + /** * device_connection_find_match - Find physical connection to a device * @dev: Device with the connection @@ -83,15 +108,9 @@ void *device_connection_find_match(struct device *dev, const char *con_id, if (!match) return NULL; - if (fwnode) { - ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); - if (ret) - return ret; - - ret = fwnode_devcon_match(fwnode, con_id, data, match); - if (ret) - return ret; - } + ret = fwnode_connection_find_match(fwnode, con_id, data, match); + if (ret) + return ret; mutex_lock(&devcon_lock); diff --git a/include/linux/device.h b/include/linux/device.h index 8ae3f4b47293..93626476c9ae 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1009,10 +1009,14 @@ struct device_connection { struct list_headlist; }; +typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, + void *data); + +void *fwnode_connection_find_match(struct fwnode_handle *fwnode, + const char *con_id, void *data, + devcon_match_fn_t match); void *device_connection_find_match(struct device *dev, const char *con_id, - void *data, - void *(*match)(struct device_connection *con, - int ep, void *data)); + void *data, devcon_match_fn_t match); struct device *device_connection_find(struct device *dev, const char *con_id); -- 2.23.0
[PATCH next v10 10/11] usb: common: add USB GPIO based connection detection driver
Due to the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated when use Type-B connector. This patch introduces a USB GPIO based connection detection driver, used to support Type-B connector which typically uses an input GPIO to detect USB ID pin, and try to replace the function provided by the extcon-usb-gpio driver Signed-off-by: Chunfeng Yun Tested-by: Nagarjuna Kristam Reviewed-by: Linus Walleij --- v10 no changes v9 changes: 1. add reviewed-by Linus v8 changes: 1. rename the driver name and usb new compatible suggested by Heikki 2. move the driver into usb/common from usb/roles suggested by Heikki v7 changes: 1. remove macro DEV_PMS_OPS suggested by Andy 2. add tested-by Nagarjuna v6 changes: 1. get usb-role-swtich by usb_role_switch_get() v5 changes: 1. put usb_role_switch when error happens suggested by Biju 2. don't treat bype-B connector as a virtual device suggested by Rob v4 changes: 1. remove linux/gpio.h suggested by Linus 2. put node when error happens v3 changes: 1. treat bype-B connector as a virtual device; 2. change file name again v2 changes: 1. file name is changed 2. use new compatible --- drivers/usb/common/Kconfig | 13 ++ drivers/usb/common/Makefile| 1 + drivers/usb/common/usb-conn-gpio.c | 284 + 3 files changed, 298 insertions(+) create mode 100644 drivers/usb/common/usb-conn-gpio.c diff --git a/drivers/usb/common/Kconfig b/drivers/usb/common/Kconfig index 848545b099cf..d611477aae41 100644 --- a/drivers/usb/common/Kconfig +++ b/drivers/usb/common/Kconfig @@ -36,3 +36,16 @@ config USB_ULPI_BUS To compile this driver as a module, choose M here: the module will be called ulpi. +config USB_CONN_GPIO + tristate "USB GPIO Based Connection Detection Driver" + depends on GPIOLIB + select USB_ROLE_SWITCH + help + The driver supports USB role switch between host and device via GPIO + based USB cable detection, used typically if an input GPIO is used + to detect USB ID pin, and another input GPIO may be also used to detect + Vbus pin at the same time, it also can be used to enable/disable + device if an input GPIO is only used to detect Vbus pin. + + To compile the driver as a module, choose M here: the module will + be called usb-conn-gpio.ko diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile index 0a7c45e85481..8227ffc2cf0b 100644 --- a/drivers/usb/common/Makefile +++ b/drivers/usb/common/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_USB_COMMON) += usb-common.o usb-common-y += common.o usb-common-$(CONFIG_USB_LED_TRIG) += led.o +obj-$(CONFIG_USB_CONN_GPIO)+= usb-conn-gpio.o obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o obj-$(CONFIG_USB_ULPI_BUS) += ulpi.o diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c new file mode 100644 index ..e4935e99f295 --- /dev/null +++ b/drivers/usb/common/usb-conn-gpio.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * USB GPIO Based Connection Detection Driver + * + * Copyright (C) 2019 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USB_GPIO_DEB_MS20 /* ms */ +#define USB_GPIO_DEB_US((USB_GPIO_DEB_MS) * 1000) /* us */ + +#define USB_CONN_IRQF \ + (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT) + +struct usb_conn_info { + struct device *dev; + struct usb_role_switch *role_sw; + enum usb_role last_role; + struct regulator *vbus; + struct delayed_work dw_det; + unsigned long debounce_jiffies; + + struct gpio_desc *id_gpiod; + struct gpio_desc *vbus_gpiod; + int id_irq; + int vbus_irq; +}; + +/** + * "DEVICE" = VBUS and "HOST" = !ID, so we have: + * Both "DEVICE" and "HOST" can't be set as active at the same time + * so if "HOST" is active (i.e. ID is 0) we keep "DEVICE" inactive + * even if VBUS is on. + * + * Role | ID | VBUS + * + * [1] DEVICE| H | H + * [2] NONE | H | L + * [3] HOST | L | H + * [4] HOST | L | L + * + * In case we have only one of these signals: + * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1 + * - ID only - we want to distinguish between [1] and [4], so VBUS = ID + */ +static void usb_conn_detect_cable(struct work_struct *work) +{ + struct usb_conn_info *info; + enum usb_role role; + int id, vbus, ret; + + info = container_of
[PATCH next v10 04/11] dt-bindings: usb: mtu3: add properties about USB Role Switch
Now the USB Role Switch is supported, so add properties about it, and modify some description related. Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring --- v6~v10 no changes v5 changes: 1. modify decription about extcon and vbus-supply properties 2. make this patch depend on [1] [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ v4 no changes v3 no changes v2 changes: 1. fix typo 2. refer new binding about connector property --- .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 ++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt index 3382b5cb471d..3a8300205cdb 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt @@ -28,8 +28,13 @@ Optional properties: parent's address space - extcon : external connector for vbus and idpin changes detection, needed when supports dual-role mode. + it's considered valid for compatibility reasons, not allowed for + new bindings, and use "usb-role-switch" property instead. - vbus-supply : reference to the VBUS regulator, needed when supports dual-role mode. + it's considered valid for compatibility reasons, not allowed for + new bindings, and put into a usb-connector node. + see connector/usb-connector.txt. - pinctrl-names : a pinctrl state named "default" is optional, and need be defined if auto drd switch is enabled, that means the property dr_mode is set as "otg", and meanwhile the property "mediatek,enable-manual-drd" @@ -39,6 +44,8 @@ Optional properties: - maximum-speed : valid arguments are "super-speed", "high-speed" and "full-speed"; refer to usb/generic.txt + - usb-role-switch : use USB Role Switch to support dual-role switch, but + not extcon; see usb/generic.txt. - enable-manual-drd : supports manual dual-role switch via debugfs; usually used when receptacle is TYPE-A and also wants to support dual-role mode. @@ -61,6 +68,9 @@ The xhci should be added as subnode to mtu3 as shown in the following example if host mode is enabled. The DT binding details of xhci can be found in: Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +The port would be added as subnode if use "usb-role-switch" property. + see graph.txt + Example: ssusb: usb@11271000 { compatible = "mediatek,mt8173-mtu3"; -- 2.23.0
[PATCH next v10 08/11] usb: roles: get usb-role-switch from parent
when the USB host controller is the parent of the connector, usually type-B, sometimes don't need the graph, so we should check whether it's parent registers usb-role-switch or not firstly, and get it if exists. Suggested-by: Heikki Krogerus Signed-off-by: Chunfeng Yun --- v10: no changes v9: 1. replace signed-off-by by suggested-by Heikki 2. use class_find_device_by_fwnode() v8: no changes v7: add signed-off-by Chunfeng v6: new patch --- drivers/usb/roles/class.c | 25 + 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 2abb6fe384ca..94b4e7db2b94 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -102,6 +102,19 @@ static void *usb_role_switch_match(struct device_connection *con, int ep, return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); } +static struct usb_role_switch * +usb_role_switch_is_parent(struct fwnode_handle *fwnode) +{ + struct fwnode_handle *parent = fwnode_get_parent(fwnode); + struct device *dev; + + if (!parent || !fwnode_property_present(parent, "usb-role-switch")) + return NULL; + + dev = class_find_device_by_fwnode(role_class, parent); + return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); +} + /** * usb_role_switch_get - Find USB role switch linked with the caller * @dev: The caller device @@ -113,8 +126,10 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) { struct usb_role_switch *sw; - sw = device_connection_find_match(dev, "usb-role-switch", NULL, - usb_role_switch_match); + sw = usb_role_switch_is_parent(dev_fwnode(dev)); + if (!sw) + sw = device_connection_find_match(dev, "usb-role-switch", NULL, + usb_role_switch_match); if (!IS_ERR_OR_NULL(sw)) WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); @@ -134,8 +149,10 @@ struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) { struct usb_role_switch *sw; - sw = fwnode_connection_find_match(fwnode, "usb-role-switch", NULL, - usb_role_switch_match); + sw = usb_role_switch_is_parent(fwnode); + if (!sw) + sw = fwnode_connection_find_match(fwnode, "usb-role-switch", + NULL, usb_role_switch_match); if (!IS_ERR_OR_NULL(sw)) WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); -- 2.23.0
[PATCH next v10 07/11] usb: roles: Add fwnode_usb_role_switch_get() function
From: Heikki Krogerus The fwnode_usb_role_switch_get() function is exactly the same as usb_role_switch_get(), except that it takes struct fwnode_handle as parameter instead of struct device. Signed-off-by: Heikki Krogerus Signed-off-by: Chunfeng Yun Tested-by: Biju Das --- v10: revert changes of v9 v9: replace signed-off-by by suggested-by Heikki v8: no changes v7: add signed-off-by Chunfeng and tested-by Biju v6: new patch --- drivers/usb/roles/class.c | 20 include/linux/usb/role.h | 7 +++ 2 files changed, 27 insertions(+) diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 0526efbc4922..2abb6fe384ca 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -123,6 +123,26 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) } EXPORT_SYMBOL_GPL(usb_role_switch_get); +/** + * fwnode_usb_role_switch_get - Find USB role switch linked with the caller + * @fwnode: The caller device node + * + * This is similar to the usb_role_switch_get() function above, but it searches + * the switch using fwnode instead of device entry. + */ +struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) +{ + struct usb_role_switch *sw; + + sw = fwnode_connection_find_match(fwnode, "usb-role-switch", NULL, + usb_role_switch_match); + if (!IS_ERR_OR_NULL(sw)) + WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); + + return sw; +} +EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get); + /** * usb_role_switch_put - Release handle to a switch * @sw: USB Role Switch diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h index da2b9641b877..2d77f97df72d 100644 --- a/include/linux/usb/role.h +++ b/include/linux/usb/role.h @@ -47,6 +47,7 @@ struct usb_role_switch_desc { int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); struct usb_role_switch *usb_role_switch_get(struct device *dev); +struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *node); void usb_role_switch_put(struct usb_role_switch *sw); struct usb_role_switch * @@ -70,6 +71,12 @@ static inline struct usb_role_switch *usb_role_switch_get(struct device *dev) return ERR_PTR(-ENODEV); } +static inline struct usb_role_switch * +fwnode_usb_role_switch_get(struct fwnode_handle *node) +{ + return ERR_PTR(-ENODEV); +} + static inline void usb_role_switch_put(struct usb_role_switch *sw) { } static inline struct usb_role_switch * -- 2.23.0
[PATCH next v10 01/11] dt-binding: usb: add usb-role-switch property
Add a property usb-role-switch to tell the driver that use USB Role Switch framework to handle the role switch, it's useful when the driver has already supported other ways, such as extcon framework etc. Cc: Biju Das Cc: Yu Chen Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring Reviewed-by: Heikki Krogerus --- v7~v10: no changes v6: 1. merge into this series patch 2. add Reviewed-by (no v4, v5) v3: add property type, modify description suggested by Heikki v2: describe it in terms of h/w functionality suggested by Rob v1: the property is discussed in: [v2,2/7] dt-bindings: usb: renesas_usb3: add usb-role-switch property https://patchwork.kernel.org/patch/10852497/ Mediatek and Hisilicon also try to use it: [v4,3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch https://patchwork.kernel.org/patch/10918385/ [v4,6/6] usb: mtu3: register a USB Role Switch for dual role mode https://patchwork.kernel.org/patch/10918367/ [v6,10/13] usb: dwc3: Registering a role switch in the DRD code https://patchwork.kernel.org/patch/10909981/ --- Documentation/devicetree/bindings/usb/generic.txt | 4 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt index 0a74ab8dfdc2..cf5a1ad456e6 100644 --- a/Documentation/devicetree/bindings/usb/generic.txt +++ b/Documentation/devicetree/bindings/usb/generic.txt @@ -30,6 +30,10 @@ Optional properties: optional for OTG device. - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is optional for OTG device. + - usb-role-switch: boolean, 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.txt. This is an attribute to a USB controller such as: -- 2.23.0
[PATCH next v10 09/11] usb: common: create Kconfig file
Create Kconfig file for USB common core, and move USB_LED_TRIG and USB_ULPI_BUS configs into the new file from the parent Kconfig, it will help to add new configs later. Signed-off-by: Chunfeng Yun --- v9~v10: no changes v8: new patch --- drivers/usb/Kconfig| 35 +-- drivers/usb/common/Kconfig | 38 ++ 2 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 drivers/usb/common/Kconfig diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 6e59d370ef81..7bf94e65ed2f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -36,8 +36,7 @@ menuconfig USB_SUPPORT if USB_SUPPORT -config USB_COMMON - tristate +source "drivers/usb/common/Kconfig" config USB_ARCH_HAS_HCD def_bool y @@ -175,36 +174,4 @@ source "drivers/usb/typec/Kconfig" source "drivers/usb/roles/Kconfig" -config USB_LED_TRIG - bool "USB LED Triggers" - depends on LEDS_CLASS && LEDS_TRIGGERS - select USB_COMMON - help - This option adds LED triggers for USB host and/or gadget activity. - - Say Y here if you are working on a system with led-class supported - LEDs and you want to use them as activity indicators for USB host or - gadget. - -config USB_ULPI_BUS - tristate "USB ULPI PHY interface support" - select USB_COMMON - help - UTMI+ Low Pin Interface (ULPI) is specification for a commonly used - USB 2.0 PHY interface. The ULPI specification defines a standard set - of registers that can be used to detect the vendor and product which - allows ULPI to be handled as a bus. This module is the driver for that - bus. - - The ULPI interfaces (the buses) are registered by the drivers for USB - controllers which support ULPI register access and have ULPI PHY - attached to them. The ULPI PHY drivers themselves are normal PHY - drivers. - - ULPI PHYs provide often functions such as ADP sensing/probing (OTG - protocol) and USB charger detection. - - To compile this driver as a module, choose M here: the module will - be called ulpi. - endif # USB_SUPPORT diff --git a/drivers/usb/common/Kconfig b/drivers/usb/common/Kconfig new file mode 100644 index ..848545b099cf --- /dev/null +++ b/drivers/usb/common/Kconfig @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 + +config USB_COMMON + tristate + + +config USB_LED_TRIG + bool "USB LED Triggers" + depends on LEDS_CLASS && LEDS_TRIGGERS + select USB_COMMON + help + This option adds LED triggers for USB host and/or gadget activity. + + Say Y here if you are working on a system with led-class supported + LEDs and you want to use them as activity indicators for USB host or + gadget. + +config USB_ULPI_BUS + tristate "USB ULPI PHY interface support" + select USB_COMMON + help + UTMI+ Low Pin Interface (ULPI) is specification for a commonly used + USB 2.0 PHY interface. The ULPI specification defines a standard set + of registers that can be used to detect the vendor and product which + allows ULPI to be handled as a bus. This module is the driver for that + bus. + + The ULPI interfaces (the buses) are registered by the drivers for USB + controllers which support ULPI register access and have ULPI PHY + attached to them. The ULPI PHY drivers themselves are normal PHY + drivers. + + ULPI PHYs provide often functions such as ADP sensing/probing (OTG + protocol) and USB charger detection. + + To compile this driver as a module, choose M here: the module will + be called ulpi. + -- 2.23.0
[PATCH next v10 11/11] usb: mtu3: register a USB Role Switch for dual role mode
Because extcon is not allowed for new bindings, and the dual role switch is supported by USB Role Switch, especially for Type-C drivers, so register a USB Role Switch to support the new way Signed-off-by: Chunfeng Yun --- v5~v10 no changes v4 changes: 1. assign fwnode member of usb_role_switch struct suggested by Heikki v3 changes: 1. select USB_ROLE_SWITCH in Kconfig suggested by Heikki 2. rename ssusb_mode_manual_switch() to ssusb_mode_switch() v2 no changes --- drivers/usb/mtu3/Kconfig| 1 + drivers/usb/mtu3/mtu3.h | 5 drivers/usb/mtu3/mtu3_debugfs.c | 4 +-- drivers/usb/mtu3/mtu3_dr.c | 48 - drivers/usb/mtu3/mtu3_dr.h | 6 ++--- drivers/usb/mtu3/mtu3_plat.c| 3 ++- 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig index 928c2cd6fc00..bf98fd36341d 100644 --- a/drivers/usb/mtu3/Kconfig +++ b/drivers/usb/mtu3/Kconfig @@ -44,6 +44,7 @@ config USB_MTU3_DUAL_ROLE bool "Dual Role mode" depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3)) depends on (EXTCON=y || EXTCON=USB_MTU3) + select USB_ROLE_SWITCH help This is the default mode of working of MTU3 controller where both host and gadget features are enabled. diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 76ecf12fdf62..6087be236a35 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -199,6 +199,9 @@ struct mtu3_gpd_ring { * @id_nb : notifier for iddig(idpin) detection * @id_work : work of iddig detection notifier * @id_event : event of iddig detecion notifier +* @role_sw : use USB Role Switch to support dual-role switch, can't use +* extcon at the same time, and extcon is deprecated. +* @role_sw_used : true when the USB Role Switch is used. * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not * @manual_drd_enabled: it's true when supports dual-role device by debugfs * to switch host/device modes depending on user input. @@ -212,6 +215,8 @@ struct otg_switch_mtk { struct notifier_block id_nb; struct work_struct id_work; unsigned long id_event; + struct usb_role_switch *role_sw; + bool role_sw_used; bool is_u3_drd; bool manual_drd_enabled; }; diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c index 62c57ddc554e..c96e5dab0a48 100644 --- a/drivers/usb/mtu3/mtu3_debugfs.c +++ b/drivers/usb/mtu3/mtu3_debugfs.c @@ -453,9 +453,9 @@ static ssize_t ssusb_mode_write(struct file *file, const char __user *ubuf, return -EFAULT; if (!strncmp(buf, "host", 4) && !ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 1); + ssusb_mode_switch(ssusb, 1); } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 0); + ssusb_mode_switch(ssusb, 0); } else { dev_err(ssusb->dev, "wrong or duplicated setting\n"); return -EINVAL; diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 5fcb71af875a..08e18448e8b8 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -7,6 +7,8 @@ * Author: Chunfeng Yun */ +#include + #include "mtu3.h" #include "mtu3_dr.h" #include "mtu3_debug.h" @@ -280,7 +282,7 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) * This is useful in special cases, such as uses TYPE-A receptacle but also * wants to support dual-role mode. */ -void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) +void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; @@ -318,6 +320,47 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb, mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value); } +static int ssusb_role_sw_set(struct device *dev, enum usb_role role) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + bool to_host = false; + + if (role == USB_ROLE_HOST) + to_host = true; + + if (to_host ^ ssusb->is_host) + ssusb_mode_switch(ssusb, to_host); + + return 0; +} + +static enum usb_role ssusb_role_sw_get(struct device *dev) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + enum usb_role role; + + role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE; + + return role; +} + +static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx) +{ + struct usb_role_switch_desc role_sx_desc = { 0 }; + struct ssusb_mtk *ssusb = + container_of(otg_sx, struct ssusb_mtk, otg_switch); + + if (!otg_sx->
[RESEND PATCH v2 2/2] usb: xhci-mtk: add an optional xhci_ck clock
Some SoCs may have an optional clock xhci_ck (125M or 200M), it usually uses the same PLL as sys_ck, so support it. Signed-off-by: Chunfeng Yun --- v2 no changes --- drivers/usb/host/xhci-mtk.c | 13 + drivers/usb/host/xhci-mtk.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 026fe18972d3..b18a6baef204 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -216,6 +216,10 @@ static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk) return PTR_ERR(mtk->sys_clk); } + mtk->xhci_clk = devm_clk_get_optional(dev, "xhci_ck"); + if (IS_ERR(mtk->xhci_clk)) + return PTR_ERR(mtk->xhci_clk); + mtk->ref_clk = devm_clk_get_optional(dev, "ref_ck"); if (IS_ERR(mtk->ref_clk)) return PTR_ERR(mtk->ref_clk); @@ -244,6 +248,12 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) goto sys_clk_err; } + ret = clk_prepare_enable(mtk->xhci_clk); + if (ret) { + dev_err(mtk->dev, "failed to enable xhci_clk\n"); + goto xhci_clk_err; + } + ret = clk_prepare_enable(mtk->mcu_clk); if (ret) { dev_err(mtk->dev, "failed to enable mcu_clk\n"); @@ -261,6 +271,8 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) dma_clk_err: clk_disable_unprepare(mtk->mcu_clk); mcu_clk_err: + clk_disable_unprepare(mtk->xhci_clk); +xhci_clk_err: clk_disable_unprepare(mtk->sys_clk); sys_clk_err: clk_disable_unprepare(mtk->ref_clk); @@ -272,6 +284,7 @@ static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk) { clk_disable_unprepare(mtk->dma_clk); clk_disable_unprepare(mtk->mcu_clk); + clk_disable_unprepare(mtk->xhci_clk); clk_disable_unprepare(mtk->sys_clk); clk_disable_unprepare(mtk->ref_clk); } diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h index 8be8c5f7ff62..5ac458b7d2e0 100644 --- a/drivers/usb/host/xhci-mtk.h +++ b/drivers/usb/host/xhci-mtk.h @@ -139,6 +139,7 @@ struct xhci_hcd_mtk { struct regulator *vusb33; struct regulator *vbus; struct clk *sys_clk;/* sys and mac clock */ + struct clk *xhci_clk; struct clk *ref_clk; struct clk *mcu_clk; struct clk *dma_clk; -- 2.23.0
[RESEND PATCH v2 1/2] dt-bindings: usb: mtk-xhci: add an optional xhci_ck clock
Add a new optional clock xhci_ck Signed-off-by: Chunfeng Yun --- v2 changes: 1. add the new clock at the end, suggested by Rob --- Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt index 266c2d917a28..f3e4acecabe8 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt @@ -30,7 +30,8 @@ Required properties: the following ones are optional: "ref_ck": reference clock used by low power mode etc, "mcu_ck": mcu_bus clock for register access, - "dma_ck": dma_bus clock for data transfer by DMA + "dma_ck": dma_bus clock for data transfer by DMA, + "xhci_ck": controller clock - phys : see usb-hcd.txt in the current directory @@ -100,7 +101,7 @@ Required properties: - clocks : a list of phandle + clock-specifier pairs, one for each entry in clock-names - clock-names : must contain "sys_ck", and the following ones are optional: - "ref_ck", "mcu_ck" and "dma_ck" + "ref_ck", "mcu_ck" and "dma_ck", "xhci_ck" Optional properties: - vbus-supply : reference to the VBUS regulator; -- 2.23.0
Re: [PATCH next v9 07/11] usb: roles: Add fwnode_usb_role_switch_get() function
On Tue, 2019-08-13 at 16:01 +0300, Heikki Krogerus wrote: > On Tue, Aug 13, 2019 at 07:27:10PM +0800, Chunfeng Yun wrote: > > From: Heikki Krogerus > > > > The fwnode_usb_role_switch_get() function is exactly the > > same as usb_role_switch_get(), except that it takes struct > > fwnode_handle as parameter instead of struct device. > > > > Suggested-by: Heikki Krogerus > > Why is my SoB replaced with Suggested-by tag in this patch? Sorry, my mistake, I misunderstand what you mean, you suggest use Suggested-by in [v8 08/11], but I replaced it all for [06, 07, 08], will abandon the changes of [06,07] in next version. > > thanks, >
Re: [PATCH] usb: typec: fusb302: Call fusb302_debugfs_init earlier
On Tue, 2019-08-13 at 13:52 +0300, Heikki Krogerus wrote: > Hi Hans, > > On Tue, Aug 13, 2019 at 12:15:24PM +0200, Hans de Goede wrote: > > tcpm_register_port() will call some of the fusb302 code's callbacks > > wich in turn will call fusb302_log(). So we need to call > > fusb302_debugfs_init() before we call tcpm_register_port(). <...> > > > > Signed-off-by: Hans de Goede > > --- > > drivers/usb/typec/tcpm/fusb302.c | 3 ++- > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/usb/typec/tcpm/fusb302.c > > b/drivers/usb/typec/tcpm/fusb302.c > > index ccfc7e91e7a3..04c76b9d0065 100644 > > --- a/drivers/usb/typec/tcpm/fusb302.c > > +++ b/drivers/usb/typec/tcpm/fusb302.c > > @@ -1759,6 +1759,7 @@ static int fusb302_probe(struct i2c_client *client, > > INIT_WORK(&chip->irq_work, fusb302_irq_work); > > INIT_DELAYED_WORK(&chip->bc_lvl_handler, fusb302_bc_lvl_handler_work); > > init_tcpc_dev(&chip->tcpc_dev); > > + fusb302_debugfs_init(chip); > > > > if (client->irq) { > > chip->gpio_int_n_irq = client->irq; > > @@ -1784,7 +1785,6 @@ static int fusb302_probe(struct i2c_client *client, > > goto tcpm_unregister_port; > > } > > enable_irq_wake(chip->gpio_int_n_irq); > > - fusb302_debugfs_init(chip); > > i2c_set_clientdata(client, chip); > > That leaves the rootdir variable pointing to something again for > example if a failure happens (like -EPROBE_AGAIN) during probe (the > "fusb302" directory is removed, but the rootdir static variable still > points to something). > > Let's just create that rootdir directory during driver init. I don't > really understand why should we only create it when/if the first > instance of fusb302 is registered. I think something like this would > work: > > diff --git a/drivers/usb/typec/tcpm/fusb302.c > b/drivers/usb/typec/tcpm/fusb302.c > index c524088246ee..7a950a6e5f0d 100644 > --- a/drivers/usb/typec/tcpm/fusb302.c > +++ b/drivers/usb/typec/tcpm/fusb302.c > @@ -212,9 +212,6 @@ static struct dentry *rootdir; > static void fusb302_debugfs_init(struct fusb302_chip *chip) > { > mutex_init(&chip->logbuffer_lock); > - if (!rootdir) > - rootdir = debugfs_create_dir("fusb302", NULL); > - > chip->dentry = debugfs_create_file(dev_name(chip->dev), >S_IFREG | 0444, rootdir, >chip, &fusb302_debug_fops); > @@ -223,7 +220,6 @@ static void fusb302_debugfs_init(struct fusb302_chip > *chip) > static void fusb302_debugfs_exit(struct fusb302_chip *chip) > { > debugfs_remove(chip->dentry); > - debugfs_remove(rootdir); > } > > #else > @@ -1863,7 +1859,24 @@ static struct i2c_driver fusb302_driver = { > .remove = fusb302_remove, > .id_table = fusb302_i2c_device_id, > }; > -module_i2c_driver(fusb302_driver); > + > +static int __init fusb302_init(void) > +{ > + rootdir = debugfs_create_dir("fusb302", NULL); > + if (IS_ERR(rootdir)) > + return PTR_ERR(rootdir); This doesn't support multi-instance? > + > + return i2c_add_driver(&fusb302_driver); > +} > + > +static void __exit fusb302_exit(void) > +{ > + i2c_del_driver(&fusb302_driver); > + debugfs_remove(rootdir); > +} > + > +module_init(fusb302_init); > +module_exit(fusb302_exit); > > MODULE_AUTHOR("Yueyao Zhu "); > MODULE_DESCRIPTION("Fairchild FUSB302 Type-C Chip Driver"); > > > If it's OK, could you include that into this patch? > > thanks, >
[PATCH next v9 05/11] usb: roles: Introduce stubs for the exiting functions in role.h
From: Yu Chen This patch adds stubs for the exiting functions while CONFIG_USB_ROLE_SWITCH does not enabled. Cc: Greg Kroah-Hartman Cc: Heikki Krogerus Cc: Hans de Goede Cc: Andy Shevchenko Cc: John Stultz Reviewed-by: Heikki Krogerus Signed-off-by: Yu Chen Signed-off-by: Chunfeng Yun --- v8~v9 no changes v7: add Signed-off-by Chunfeng v6: merge this patch [1] into this series to add new API [1] https://patchwork.kernel.org/patch/10909971/ --- include/linux/usb/role.h | 30 ++ 1 file changed, 30 insertions(+) diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h index c05ffa6abda9..da2b9641b877 100644 --- a/include/linux/usb/role.h +++ b/include/linux/usb/role.h @@ -42,6 +42,8 @@ struct usb_role_switch_desc { bool allow_userspace_control; }; + +#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); struct usb_role_switch *usb_role_switch_get(struct device *dev); @@ -51,5 +53,33 @@ struct usb_role_switch * usb_role_switch_register(struct device *parent, const struct usb_role_switch_desc *desc); void usb_role_switch_unregister(struct usb_role_switch *sw); +#else +static inline int usb_role_switch_set_role(struct usb_role_switch *sw, + enum usb_role role) +{ + return 0; +} + +static inline enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) +{ + return USB_ROLE_NONE; +} + +static inline struct usb_role_switch *usb_role_switch_get(struct device *dev) +{ + return ERR_PTR(-ENODEV); +} + +static inline void usb_role_switch_put(struct usb_role_switch *sw) { } + +static inline struct usb_role_switch * +usb_role_switch_register(struct device *parent, +const struct usb_role_switch_desc *desc) +{ + return ERR_PTR(-ENODEV); +} + +static inline void usb_role_switch_unregister(struct usb_role_switch *sw) { } +#endif #endif /* __LINUX_USB_ROLE_H */ -- 2.22.0
[PATCH next v9 01/11] dt-binding: usb: add usb-role-switch property
Add a property usb-role-switch to tell the driver that use USB Role Switch framework to handle the role switch, it's useful when the driver has already supported other ways, such as extcon framework etc. Cc: Biju Das Cc: Yu Chen Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring Reviewed-by: Heikki Krogerus --- v7~v9: no changes v6: 1. merge into this series patch 2. add Reviewed-by (no v4, v5) v3: add property type, modify description suggested by Heikki v2: describe it in terms of h/w functionality suggested by Rob v1: the property is discussed in: [v2,2/7] dt-bindings: usb: renesas_usb3: add usb-role-switch property https://patchwork.kernel.org/patch/10852497/ Mediatek and Hisilicon also try to use it: [v4,3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch https://patchwork.kernel.org/patch/10918385/ [v4,6/6] usb: mtu3: register a USB Role Switch for dual role mode https://patchwork.kernel.org/patch/10918367/ [v6,10/13] usb: dwc3: Registering a role switch in the DRD code https://patchwork.kernel.org/patch/10909981/ --- Documentation/devicetree/bindings/usb/generic.txt | 4 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt index 0a74ab8dfdc2..cf5a1ad456e6 100644 --- a/Documentation/devicetree/bindings/usb/generic.txt +++ b/Documentation/devicetree/bindings/usb/generic.txt @@ -30,6 +30,10 @@ Optional properties: optional for OTG device. - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is optional for OTG device. + - usb-role-switch: boolean, 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.txt. This is an attribute to a USB controller such as: -- 2.22.0
[PATCH next v9 08/11] usb: roles: get usb-role-switch from parent
when the USB host controller is the parent of the connector, usually type-B, sometimes don't need the graph, so we should check whether it's parent registers usb-role-switch or not firstly, and get it if exists. Suggested-by: Heikki Krogerus Signed-off-by: Chunfeng Yun --- v9: 1. replace signed-off-by by suggested-by Heikki 2. use class_find_device_by_fwnode() v8: no changes v7: add signed-off-by Chunfeng v6: new patch --- drivers/usb/roles/class.c | 25 + 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 2abb6fe384ca..94b4e7db2b94 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -102,6 +102,19 @@ static void *usb_role_switch_match(struct device_connection *con, int ep, return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); } +static struct usb_role_switch * +usb_role_switch_is_parent(struct fwnode_handle *fwnode) +{ + struct fwnode_handle *parent = fwnode_get_parent(fwnode); + struct device *dev; + + if (!parent || !fwnode_property_present(parent, "usb-role-switch")) + return NULL; + + dev = class_find_device_by_fwnode(role_class, parent); + return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); +} + /** * usb_role_switch_get - Find USB role switch linked with the caller * @dev: The caller device @@ -113,8 +126,10 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) { struct usb_role_switch *sw; - sw = device_connection_find_match(dev, "usb-role-switch", NULL, - usb_role_switch_match); + sw = usb_role_switch_is_parent(dev_fwnode(dev)); + if (!sw) + sw = device_connection_find_match(dev, "usb-role-switch", NULL, + usb_role_switch_match); if (!IS_ERR_OR_NULL(sw)) WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); @@ -134,8 +149,10 @@ struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) { struct usb_role_switch *sw; - sw = fwnode_connection_find_match(fwnode, "usb-role-switch", NULL, - usb_role_switch_match); + sw = usb_role_switch_is_parent(fwnode); + if (!sw) + sw = fwnode_connection_find_match(fwnode, "usb-role-switch", + NULL, usb_role_switch_match); if (!IS_ERR_OR_NULL(sw)) WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); -- 2.22.0
[PATCH next v9 10/11] usb: common: add USB GPIO based connection detection driver
Due to the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated when use Type-B connector. This patch introduces a USB GPIO based connection detection driver, used to support Type-B connector which typically uses an input GPIO to detect USB ID pin, and try to replace the function provided by the extcon-usb-gpio driver Signed-off-by: Chunfeng Yun Tested-by: Nagarjuna Kristam Reviewed-by: Linus Walleij --- v9 changes: 1. add reviewed-by Linus v8 changes: 1. rename the driver name and usb new compatible suggested by Heikki 2. move the driver into usb/common from usb/roles suggested by Heikki v7 changes: 1. remove macro DEV_PMS_OPS suggested by Andy 2. add tested-by Nagarjuna v6 changes: 1. get usb-role-swtich by usb_role_switch_get() v5 changes: 1. put usb_role_switch when error happens suggested by Biju 2. don't treat bype-B connector as a virtual device suggested by Rob v4 changes: 1. remove linux/gpio.h suggested by Linus 2. put node when error happens v3 changes: 1. treat bype-B connector as a virtual device; 2. change file name again v2 changes: 1. file name is changed 2. use new compatible --- drivers/usb/common/Kconfig | 13 ++ drivers/usb/common/Makefile| 1 + drivers/usb/common/usb-conn-gpio.c | 284 + 3 files changed, 298 insertions(+) create mode 100644 drivers/usb/common/usb-conn-gpio.c diff --git a/drivers/usb/common/Kconfig b/drivers/usb/common/Kconfig index 848545b099cf..d611477aae41 100644 --- a/drivers/usb/common/Kconfig +++ b/drivers/usb/common/Kconfig @@ -36,3 +36,16 @@ config USB_ULPI_BUS To compile this driver as a module, choose M here: the module will be called ulpi. +config USB_CONN_GPIO + tristate "USB GPIO Based Connection Detection Driver" + depends on GPIOLIB + select USB_ROLE_SWITCH + help + The driver supports USB role switch between host and device via GPIO + based USB cable detection, used typically if an input GPIO is used + to detect USB ID pin, and another input GPIO may be also used to detect + Vbus pin at the same time, it also can be used to enable/disable + device if an input GPIO is only used to detect Vbus pin. + + To compile the driver as a module, choose M here: the module will + be called usb-conn-gpio.ko diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile index 0a7c45e85481..8227ffc2cf0b 100644 --- a/drivers/usb/common/Makefile +++ b/drivers/usb/common/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_USB_COMMON) += usb-common.o usb-common-y += common.o usb-common-$(CONFIG_USB_LED_TRIG) += led.o +obj-$(CONFIG_USB_CONN_GPIO)+= usb-conn-gpio.o obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o obj-$(CONFIG_USB_ULPI_BUS) += ulpi.o diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c new file mode 100644 index ..e4935e99f295 --- /dev/null +++ b/drivers/usb/common/usb-conn-gpio.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * USB GPIO Based Connection Detection Driver + * + * Copyright (C) 2019 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USB_GPIO_DEB_MS20 /* ms */ +#define USB_GPIO_DEB_US((USB_GPIO_DEB_MS) * 1000) /* us */ + +#define USB_CONN_IRQF \ + (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT) + +struct usb_conn_info { + struct device *dev; + struct usb_role_switch *role_sw; + enum usb_role last_role; + struct regulator *vbus; + struct delayed_work dw_det; + unsigned long debounce_jiffies; + + struct gpio_desc *id_gpiod; + struct gpio_desc *vbus_gpiod; + int id_irq; + int vbus_irq; +}; + +/** + * "DEVICE" = VBUS and "HOST" = !ID, so we have: + * Both "DEVICE" and "HOST" can't be set as active at the same time + * so if "HOST" is active (i.e. ID is 0) we keep "DEVICE" inactive + * even if VBUS is on. + * + * Role | ID | VBUS + * + * [1] DEVICE| H | H + * [2] NONE | H | L + * [3] HOST | L | H + * [4] HOST | L | L + * + * In case we have only one of these signals: + * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1 + * - ID only - we want to distinguish between [1] and [4], so VBUS = ID + */ +static void usb_conn_detect_cable(struct work_struct *work) +{ + struct usb_conn_info *info; + enum usb_role role; + int id, vbus, ret; + + info = container_of(to_delayed_work(work), +
[PATCH next v9 09/11] usb: common: create Kconfig file
Create Kconfig file for USB common core, and move USB_LED_TRIG and USB_ULPI_BUS configs into the new file from the parent Kconfig, it will help to add new configs later. Signed-off-by: Chunfeng Yun --- v9 no changes v8: new patch --- drivers/usb/Kconfig| 35 +-- drivers/usb/common/Kconfig | 38 ++ 2 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 drivers/usb/common/Kconfig diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 6e59d370ef81..7bf94e65ed2f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -36,8 +36,7 @@ menuconfig USB_SUPPORT if USB_SUPPORT -config USB_COMMON - tristate +source "drivers/usb/common/Kconfig" config USB_ARCH_HAS_HCD def_bool y @@ -175,36 +174,4 @@ source "drivers/usb/typec/Kconfig" source "drivers/usb/roles/Kconfig" -config USB_LED_TRIG - bool "USB LED Triggers" - depends on LEDS_CLASS && LEDS_TRIGGERS - select USB_COMMON - help - This option adds LED triggers for USB host and/or gadget activity. - - Say Y here if you are working on a system with led-class supported - LEDs and you want to use them as activity indicators for USB host or - gadget. - -config USB_ULPI_BUS - tristate "USB ULPI PHY interface support" - select USB_COMMON - help - UTMI+ Low Pin Interface (ULPI) is specification for a commonly used - USB 2.0 PHY interface. The ULPI specification defines a standard set - of registers that can be used to detect the vendor and product which - allows ULPI to be handled as a bus. This module is the driver for that - bus. - - The ULPI interfaces (the buses) are registered by the drivers for USB - controllers which support ULPI register access and have ULPI PHY - attached to them. The ULPI PHY drivers themselves are normal PHY - drivers. - - ULPI PHYs provide often functions such as ADP sensing/probing (OTG - protocol) and USB charger detection. - - To compile this driver as a module, choose M here: the module will - be called ulpi. - endif # USB_SUPPORT diff --git a/drivers/usb/common/Kconfig b/drivers/usb/common/Kconfig new file mode 100644 index ..848545b099cf --- /dev/null +++ b/drivers/usb/common/Kconfig @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 + +config USB_COMMON + tristate + + +config USB_LED_TRIG + bool "USB LED Triggers" + depends on LEDS_CLASS && LEDS_TRIGGERS + select USB_COMMON + help + This option adds LED triggers for USB host and/or gadget activity. + + Say Y here if you are working on a system with led-class supported + LEDs and you want to use them as activity indicators for USB host or + gadget. + +config USB_ULPI_BUS + tristate "USB ULPI PHY interface support" + select USB_COMMON + help + UTMI+ Low Pin Interface (ULPI) is specification for a commonly used + USB 2.0 PHY interface. The ULPI specification defines a standard set + of registers that can be used to detect the vendor and product which + allows ULPI to be handled as a bus. This module is the driver for that + bus. + + The ULPI interfaces (the buses) are registered by the drivers for USB + controllers which support ULPI register access and have ULPI PHY + attached to them. The ULPI PHY drivers themselves are normal PHY + drivers. + + ULPI PHYs provide often functions such as ADP sensing/probing (OTG + protocol) and USB charger detection. + + To compile this driver as a module, choose M here: the module will + be called ulpi. + -- 2.22.0
[PATCH next v9 07/11] usb: roles: Add fwnode_usb_role_switch_get() function
From: Heikki Krogerus The fwnode_usb_role_switch_get() function is exactly the same as usb_role_switch_get(), except that it takes struct fwnode_handle as parameter instead of struct device. Suggested-by: Heikki Krogerus Signed-off-by: Chunfeng Yun Tested-by: Biju Das --- v9: replace signed-off-by by suggested-by Heikki v8: no changes v7: add signed-off-by Chunfeng and tested-by Biju v6: new patch --- drivers/usb/roles/class.c | 20 include/linux/usb/role.h | 7 +++ 2 files changed, 27 insertions(+) diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 0526efbc4922..2abb6fe384ca 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -123,6 +123,26 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) } EXPORT_SYMBOL_GPL(usb_role_switch_get); +/** + * fwnode_usb_role_switch_get - Find USB role switch linked with the caller + * @fwnode: The caller device node + * + * This is similar to the usb_role_switch_get() function above, but it searches + * the switch using fwnode instead of device entry. + */ +struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) +{ + struct usb_role_switch *sw; + + sw = fwnode_connection_find_match(fwnode, "usb-role-switch", NULL, + usb_role_switch_match); + if (!IS_ERR_OR_NULL(sw)) + WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); + + return sw; +} +EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get); + /** * usb_role_switch_put - Release handle to a switch * @sw: USB Role Switch diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h index da2b9641b877..2d77f97df72d 100644 --- a/include/linux/usb/role.h +++ b/include/linux/usb/role.h @@ -47,6 +47,7 @@ struct usb_role_switch_desc { int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); struct usb_role_switch *usb_role_switch_get(struct device *dev); +struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *node); void usb_role_switch_put(struct usb_role_switch *sw); struct usb_role_switch * @@ -70,6 +71,12 @@ static inline struct usb_role_switch *usb_role_switch_get(struct device *dev) return ERR_PTR(-ENODEV); } +static inline struct usb_role_switch * +fwnode_usb_role_switch_get(struct fwnode_handle *node) +{ + return ERR_PTR(-ENODEV); +} + static inline void usb_role_switch_put(struct usb_role_switch *sw) { } static inline struct usb_role_switch * -- 2.22.0
[PATCH next v9 04/11] dt-bindings: usb: mtu3: add properties about USB Role Switch
Now the USB Role Switch is supported, so add properties about it, and modify some description related. Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring --- v6~v9 no changes v5 changes: 1. modify decription about extcon and vbus-supply properties 2. make this patch depend on [1] [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ v4 no changes v3 no changes v2 changes: 1. fix typo 2. refer new binding about connector property --- .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 ++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt index 3382b5cb471d..3a8300205cdb 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt @@ -28,8 +28,13 @@ Optional properties: parent's address space - extcon : external connector for vbus and idpin changes detection, needed when supports dual-role mode. + it's considered valid for compatibility reasons, not allowed for + new bindings, and use "usb-role-switch" property instead. - vbus-supply : reference to the VBUS regulator, needed when supports dual-role mode. + it's considered valid for compatibility reasons, not allowed for + new bindings, and put into a usb-connector node. + see connector/usb-connector.txt. - pinctrl-names : a pinctrl state named "default" is optional, and need be defined if auto drd switch is enabled, that means the property dr_mode is set as "otg", and meanwhile the property "mediatek,enable-manual-drd" @@ -39,6 +44,8 @@ Optional properties: - maximum-speed : valid arguments are "super-speed", "high-speed" and "full-speed"; refer to usb/generic.txt + - usb-role-switch : use USB Role Switch to support dual-role switch, but + not extcon; see usb/generic.txt. - enable-manual-drd : supports manual dual-role switch via debugfs; usually used when receptacle is TYPE-A and also wants to support dual-role mode. @@ -61,6 +68,9 @@ The xhci should be added as subnode to mtu3 as shown in the following example if host mode is enabled. The DT binding details of xhci can be found in: Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +The port would be added as subnode if use "usb-role-switch" property. + see graph.txt + Example: ssusb: usb@11271000 { compatible = "mediatek,mt8173-mtu3"; -- 2.22.0
[PATCH next v9 02/11] dt-bindings: connector: add optional properties for Type-B
Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for usb-b-connector Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring --- v6~v9 no changes v5 changes: 1. add reviewed by Rob v4 no changes v3 changes: 1. add GPIO direction, and use fixed-regulator for GPIO controlled VBUS regulator suggested by Rob; v2 changes: 1. describe more clear for vbus-gpios and vbus-supply suggested by Hans --- .../bindings/connector/usb-connector.txt | 14 ++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt index cef556d4e5ee..d357987181ee 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.txt +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt @@ -17,6 +17,20 @@ Optional properties: - self-powered: Set this property if the usb device that has its own power source. +Optional properties for usb-b-connector: +- id-gpios: an input gpio for USB ID pin. +- vbus-gpios: an input gpio for USB VBUS pin, used to detect presence of + VBUS 5V. + see gpio/gpio.txt. +- vbus-supply: a phandle to the regulator for USB VBUS if needed when host + mode or dual role mode is supported. + Particularly, if use an output GPIO to control a VBUS regulator, should + model it as a regulator. + see regulator/fixed-regulator.yaml +- pinctrl-names : a pinctrl state named "default" is optional +- pinctrl-0 : pin control group + see pinctrl/pinctrl-bindings.txt + Optional properties for usb-c-connector: - power-role: should be one of "source", "sink" or "dual"(DRP) if typec connector has power support. -- 2.22.0
[PATCH next v9 03/11] dt-bindings: usb: add binding for USB GPIO based connection detection driver
It's used to support dual role switch via GPIO when use Type-B receptacle, typically the USB ID pin is connected to an input GPIO, and also used to enable/disable device when the USB Vbus pin is connected to an input GPIO. Signed-off-by: Chunfeng Yun --- v9 no changes v8 changes: 1. rename the title 2. change the compatible as "linux,usb-conn-gpio" instead of "linux,typeb-conn-gpio" v7 changes: 1. add description for device only mode v6 changes: 1. remove status and port nodes in example 2. make vbus-supply as optional property v5 changes: 1. treat type-B connector as child device of USB controller's, but not as a separate virtual device, suggested by Rob 2. put connector's port node under connector node, suggested by Rob v4 no changes v3 changes: 1. treat type-B connector as a virtual device, but not child device of USB controller's v2 changes: 1. new patch to make binding clear suggested by Hans --- .../devicetree/bindings/usb/usb-conn-gpio.txt | 31 +++ 1 file changed, 31 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/usb-conn-gpio.txt diff --git a/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt b/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt new file mode 100644 index ..d4d107fedc22 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt @@ -0,0 +1,31 @@ +USB GPIO Based Connection Detection + +This is typically used to switch dual role mode from the USB ID pin connected +to an input GPIO, and also used to enable/disable device mode from the USB +Vbus pin connected to an input GPIO. + +Required properties: +- compatible : should include "linux,usb-conn-gpio" and "usb-b-connector". +- id-gpios, vbus-gpios : input gpios, either one of them must be present, + and both can be present as well. + see connector/usb-connector.txt + +Optional properties: +- vbus-supply : can be present if needed when supports dual role mode. + see connector/usb-connector.txt + +- Sub-nodes: + - port : can be present. + see graph.txt + +Example: + +&mtu3 { + connector { + compatible = "linux,usb-conn-gpio", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb_p0_vbus>; + }; +}; -- 2.22.0
[PATCH next v9 11/11] usb: mtu3: register a USB Role Switch for dual role mode
Because extcon is not allowed for new bindings, and the dual role switch is supported by USB Role Switch, especially for Type-C drivers, so register a USB Role Switch to support the new way Signed-off-by: Chunfeng Yun --- v5~v9 no changes v4 changes: 1. assign fwnode member of usb_role_switch struct suggested by Heikki v3 changes: 1. select USB_ROLE_SWITCH in Kconfig suggested by Heikki 2. rename ssusb_mode_manual_switch() to ssusb_mode_switch() v2 no changes --- drivers/usb/mtu3/Kconfig| 1 + drivers/usb/mtu3/mtu3.h | 5 drivers/usb/mtu3/mtu3_debugfs.c | 4 +-- drivers/usb/mtu3/mtu3_dr.c | 48 - drivers/usb/mtu3/mtu3_dr.h | 6 ++--- drivers/usb/mtu3/mtu3_plat.c| 3 ++- 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig index 928c2cd6fc00..bf98fd36341d 100644 --- a/drivers/usb/mtu3/Kconfig +++ b/drivers/usb/mtu3/Kconfig @@ -44,6 +44,7 @@ config USB_MTU3_DUAL_ROLE bool "Dual Role mode" depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3)) depends on (EXTCON=y || EXTCON=USB_MTU3) + select USB_ROLE_SWITCH help This is the default mode of working of MTU3 controller where both host and gadget features are enabled. diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 76ecf12fdf62..6087be236a35 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -199,6 +199,9 @@ struct mtu3_gpd_ring { * @id_nb : notifier for iddig(idpin) detection * @id_work : work of iddig detection notifier * @id_event : event of iddig detecion notifier +* @role_sw : use USB Role Switch to support dual-role switch, can't use +* extcon at the same time, and extcon is deprecated. +* @role_sw_used : true when the USB Role Switch is used. * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not * @manual_drd_enabled: it's true when supports dual-role device by debugfs * to switch host/device modes depending on user input. @@ -212,6 +215,8 @@ struct otg_switch_mtk { struct notifier_block id_nb; struct work_struct id_work; unsigned long id_event; + struct usb_role_switch *role_sw; + bool role_sw_used; bool is_u3_drd; bool manual_drd_enabled; }; diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c index 62c57ddc554e..c96e5dab0a48 100644 --- a/drivers/usb/mtu3/mtu3_debugfs.c +++ b/drivers/usb/mtu3/mtu3_debugfs.c @@ -453,9 +453,9 @@ static ssize_t ssusb_mode_write(struct file *file, const char __user *ubuf, return -EFAULT; if (!strncmp(buf, "host", 4) && !ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 1); + ssusb_mode_switch(ssusb, 1); } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 0); + ssusb_mode_switch(ssusb, 0); } else { dev_err(ssusb->dev, "wrong or duplicated setting\n"); return -EINVAL; diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 5fcb71af875a..08e18448e8b8 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -7,6 +7,8 @@ * Author: Chunfeng Yun */ +#include + #include "mtu3.h" #include "mtu3_dr.h" #include "mtu3_debug.h" @@ -280,7 +282,7 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) * This is useful in special cases, such as uses TYPE-A receptacle but also * wants to support dual-role mode. */ -void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) +void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; @@ -318,6 +320,47 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb, mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value); } +static int ssusb_role_sw_set(struct device *dev, enum usb_role role) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + bool to_host = false; + + if (role == USB_ROLE_HOST) + to_host = true; + + if (to_host ^ ssusb->is_host) + ssusb_mode_switch(ssusb, to_host); + + return 0; +} + +static enum usb_role ssusb_role_sw_get(struct device *dev) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + enum usb_role role; + + role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE; + + return role; +} + +static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx) +{ + struct usb_role_switch_desc role_sx_desc = { 0 }; + struct ssusb_mtk *ssusb = + container_of(otg_sx, struct ssusb_mtk, otg_switch); + + if (!otg_sx->
[PATCH next v9 06/11] device connection: Add fwnode_connection_find_match()
From: Heikki Krogerus The fwnode_connection_find_match() function is exactly the same as device_connection_find_match(), except it takes struct fwnode_handle as parameter instead of struct device. That allows locating device connections before the device entries have been created. Suggested-by: Heikki Krogerus Signed-off-by: Chunfeng Yun --- v9: replace signed-off-by by suggested-by Heikki v8: no changes v7: rebased on Rafael's tree [1] (after rc4), provided by Heikki [1] https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git/log/?h=linux-next v6: new patch --- drivers/base/devcon.c | 43 ++ include/linux/device.h | 10 +++--- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c index 1d488dc5dd0c..14e2178e09f8 100644 --- a/drivers/base/devcon.c +++ b/drivers/base/devcon.c @@ -12,9 +12,6 @@ static DEFINE_MUTEX(devcon_lock); static LIST_HEAD(devcon_list); -typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, - void *data); - static void * fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id, void *data, devcon_match_fn_t match) @@ -60,6 +57,34 @@ fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id, return NULL; } +/** + * fwnode_connection_find_match - Find connection from a device node + * @fwnode: Device node with the connection + * @con_id: Identifier for the connection + * @data: Data for the match function + * @match: Function to check and convert the connection description + * + * Find a connection with unique identifier @con_id between @fwnode and another + * device node. @match will be used to convert the connection description to + * data the caller is expecting to be returned. + */ +void *fwnode_connection_find_match(struct fwnode_handle *fwnode, + const char *con_id, void *data, + devcon_match_fn_t match) +{ + void *ret; + + if (!fwnode || !match) + return NULL; + + ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); + if (ret) + return ret; + + return fwnode_devcon_match(fwnode, con_id, data, match); +} +EXPORT_SYMBOL_GPL(fwnode_connection_find_match); + /** * device_connection_find_match - Find physical connection to a device * @dev: Device with the connection @@ -83,15 +108,9 @@ void *device_connection_find_match(struct device *dev, const char *con_id, if (!match) return NULL; - if (fwnode) { - ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); - if (ret) - return ret; - - ret = fwnode_devcon_match(fwnode, con_id, data, match); - if (ret) - return ret; - } + ret = fwnode_connection_find_match(fwnode, con_id, data, match); + if (ret) + return ret; mutex_lock(&devcon_lock); diff --git a/include/linux/device.h b/include/linux/device.h index 8ae3f4b47293..93626476c9ae 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1009,10 +1009,14 @@ struct device_connection { struct list_headlist; }; +typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, + void *data); + +void *fwnode_connection_find_match(struct fwnode_handle *fwnode, + const char *con_id, void *data, + devcon_match_fn_t match); void *device_connection_find_match(struct device *dev, const char *con_id, - void *data, - void *(*match)(struct device_connection *con, - int ep, void *data)); + void *data, devcon_match_fn_t match); struct device *device_connection_find(struct device *dev, const char *con_id); -- 2.22.0
[PATCH next v9 00/11] add USB GPIO based connection detection driver
Because the USB Connector is introduced and the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated, meanwhile there is no available common driver when use Type-B connector, typically using an input GPIO to detect USB ID pin. This patch series introduce a USB GPIO based connection detection driver and try to replace the function provided by extcon-usb-gpio driver. v9 changes: 1. replace signed-off-by by suggested-by Heikki 2. add reviewed-by Linus 3. use class_find_device_by_fwnode() introduced by series [1] [1]: https://lore.kernel.org/patchwork/patch/1103630/ [v3,1/7] drivers: Introduce device lookup variants by name they are already in: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/log/drivers/base/core.c?h=driver-core-next v8 changes: 1. rename the driver's name suggested by Heikki 2. move the driver from usb/roles/ into usb/common/ suggested by Heikki 3. introduce Kconfig for usb common core to add the new driver 4. modify binding of the driver 5. rename the subject title v7 changes: 1. [5/10]: add signed-off-by Chunfeng 2. [6/10]: add signed-off-by Chunfeng 3. [6/10]: depends on linux-next of Rafael's tree [1] 4. [7/10]: add signed-off-by Chunfeng and tested-by Biju 5. [9/10]: add tested-by Nagarjuna, and remove DEV_PMS_OPS suggested by Andy [1] https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git/log/?h=linux-next v6 changes: 1. merge [1] and [2] into this series 2. don't use graph anymore to find usb-role-switch 3. abandon [3] and introduce three patches (6, 7, 8 in this series) to rebuild APIs getting usb-role-switch [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ [2]: [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ [3]: [PATCH v5 4/6] usb: roles: add API to get usb_role_switch by node v5 changes: 1. remove linux/of.h and put usb_role_switch when error happens, suggested by Biju 2. treat Type-B connector as USB controller's child, but not as a virtual device, suggested by Rob 3. provide and use generic property "usb-role-switch", see [1], suggested by Rob Note: this series still depends on [2] [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ [2]: [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v4 changes: 1. use switch_fwnode_match() to find fwnode suggested by Heikki 2. assign fwnode member of usb_role_switch struct suggested by Heikki 3. make [4/6] depend on [2] 3. remove linux/gpio.h suggested by Linus 4. put node when error happens [4/6] usb: roles: add API to get usb_role_switch by node [2] [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v3 changes: 1. add GPIO direction, and use fixed-regulator for GPIO controlled VBUS regulator suggested by Rob; 2. rebuild fwnode_usb_role_switch_get() suggested by Andy and Heikki 3. treat the type-B connector as a virtual device; 4. change file name of driver again 5. select USB_ROLE_SWITCH in mtu3/Kconfig suggested by Heikki 6. rename ssusb_mode_manual_switch() to ssusb_mode_switch() v2 changes: 1. make binding clear, and add a extra compatible suggested by Hans Chunfeng Yun (8): dt-binding: usb: add usb-role-switch property dt-bindings: connector: add optional properties for Type-B dt-bindings: usb: add binding for USB GPIO based connection detection driver dt-bindings: usb: mtu3: add properties about USB Role Switch usb: roles: get usb-role-switch from parent usb: common: create Kconfig file usb: common: add USB GPIO based connection detection driver usb: mtu3: register a USB Role Switch for dual role mode Heikki Krogerus (2): device connection: Add fwnode_connection_find_match() usb: roles: Add fwnode_usb_role_switch_get() function Yu Chen (1): usb: roles: Introduce stubs for the exiting functions in role.h .../bindings/connector/usb-connector.txt | 14 + .../devicetree/bindings/usb/generic.txt | 4 + .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 + .../devicetree/bindings/usb/usb-conn-gpio.txt | 31 ++ drivers/base/devcon.c | 43 ++- drivers/usb/Kconfig | 35 +-- drivers/usb/common/Kconfig| 51 drivers/usb/common/Makefile | 1 + drivers/usb/common/usb-conn-gpio.c| 284 ++ drivers/usb/mtu3/Kconfig | 1 + drivers/usb/mtu3/mtu3.h | 5 + drivers/usb/mtu3/mtu3_debugfs.c | 4 +- drivers/usb/mtu3/mtu3_dr.c
Re: [PATCH v10 5/6] usb:cdns3 Add Cadence USB3 DRD Driver
On Tue, 2019-08-13 at 10:48 +0300, Roger Quadros wrote: > > On 13/08/2019 10:30, Chunfeng Yun wrote: > > On Mon, 2019-08-12 at 16:04 +0300, Roger Quadros wrote: > >> > >> On 12/08/2019 15:46, Felipe Balbi wrote: > >>> > >>> Hi, > >>> > >>> Roger Quadros writes: > >>>>> The sysfs file we expose from the class for the role switches is > >>>>> primarily meant for supporting proprietary protocols that require us > >>>>> to basically override the connector USB data role. The default role > >>>>> should always be selected in the drivers. > >>>> > >>>> OK. Let's take this example > >>>> - Port is dual-role port micro AB. > >>>> - microAB to type-A adapter is connected which pulls ID low. port > >>>> transitions > >>>> to "host" role by the controller driver. > >>>> - proprietary protocol want to switch role to device role so writes > >>>> "device" to > >>>> mode switch sysfs. port transitions to "device" role. > >>>> > >>>> Now, how does controller driver know to fall back to HW based role > >>>> switching? > >>> > >>> Use a 'disconnect' or 'suspend' event to go reset it? But that should, > >>> probably, be done at kernel space, no? > >>> > >> > >> Yes that could be one option. > >> So after a disconnect, sysfs role should reflect actual hardware role. > >> correct? > > > > Maybe it's difficult to support both HW based role switch and SW based > > role switch by sysfs at the same if the HW's FSM rely on, such as, the > > state of Vbus pin or ID pin. Likes the upper example, when user writes > > "device" to mode switch sysfs, the driver should skip the HW state of ID > > pin, due to it's state is Low, or force it as High. > > > > We do need a clear way of indicating that SW wants to override so HW > state is ignored. > > > Another option way is that introduces a property in DTS to indicate the > > way the driver want to use (HW based or SW based, usb_role_switch > > doesn't provide this information for the controller driver), but is not > > flexible enough. > > That is not good enough for us. We need both HW and SW based role switching. > > Can we introduce a new state (e.g. "auto") in usb_role_switch. This would > explicitly indicate the driver to do HW based switching. But "auto" is not a role? How about introducing a new attribute in usb_role_switch? > > This way we don't need to depend on connect/disconnect events and can > do role switch tests even without cable/device connected. >
Re: [PATCH v10 5/6] usb:cdns3 Add Cadence USB3 DRD Driver
On Mon, 2019-08-12 at 16:04 +0300, Roger Quadros wrote: > > On 12/08/2019 15:46, Felipe Balbi wrote: > > > > Hi, > > > > Roger Quadros writes: > >>> The sysfs file we expose from the class for the role switches is > >>> primarily meant for supporting proprietary protocols that require us > >>> to basically override the connector USB data role. The default role > >>> should always be selected in the drivers. > >> > >> OK. Let's take this example > >> - Port is dual-role port micro AB. > >> - microAB to type-A adapter is connected which pulls ID low. port > >> transitions > >> to "host" role by the controller driver. > >> - proprietary protocol want to switch role to device role so writes > >> "device" to > >> mode switch sysfs. port transitions to "device" role. > >> > >> Now, how does controller driver know to fall back to HW based role > >> switching? > > > > Use a 'disconnect' or 'suspend' event to go reset it? But that should, > > probably, be done at kernel space, no? > > > > Yes that could be one option. > So after a disconnect, sysfs role should reflect actual hardware role. > correct? Maybe it's difficult to support both HW based role switch and SW based role switch by sysfs at the same if the HW's FSM rely on, such as, the state of Vbus pin or ID pin. Likes the upper example, when user writes "device" to mode switch sysfs, the driver should skip the HW state of ID pin, due to it's state is Low, or force it as High. Another option way is that introduces a property in DTS to indicate the way the driver want to use (HW based or SW based, usb_role_switch doesn't provide this information for the controller driver), but is not flexible enough. > > cheers, > -roger
Re: [Patch V6 7/8] usb: gadget: Add UDC driver for tegra XUSB device mode controller
On Mon, 2019-08-12 at 15:49 +0300, Felipe Balbi wrote: > Hi, > > Chunfeng Yun writes: > >> +/* XUSB_DEV registers */ > >> +#define SPARAM 0x000 > >> +#define SPARAM_ERSTMAX_SHIFT 16 > >> +#define SPARAM_ERSTMAX_MASK GENMASK(4, 0) > >> +#define DB 0x004 > >> +#define DB_TARGET_SHIFT 8 > >> +#define DB_TARGET_MASK GENMASK(7, 0) > >> +#define DB_STREAMID_SHIFT 16 > >> +#define DB_STREAMID_MASK GENMASK(15, 0) > > To me, define it as : > > #define DB_STREAMID_MASK GENMASK(31, 16), > > it's more clearer. > > and define another macro > > #define DB_STREAMID(x) (((x) & 0x) << 16) > > perhaps? > > #define DB_STREAMID(x)(((x) << 16) & DB_STREAMID_MASK) It's a better way :) > > Otherwise you end up defining the mask twice. >
Re: [Patch V6 7/8] usb: gadget: Add UDC driver for tegra XUSB device mode controller
On Thu, 2019-08-08 at 15:07 +0530, Nagarjuna Kristam wrote: > This patch adds UDC driver for tegra XUSB 3.0 device mode controller. > XUSB device mode controller supports SS, HS and FS modes > > Based on work by: > Mark Kuo > Hui Fu > Andrew Bresticker > > Signed-off-by: Nagarjuna Kristam > Acked-by: Thierry Reding > --- > drivers/usb/gadget/udc/Kconfig | 11 + > drivers/usb/gadget/udc/Makefile |1 + > drivers/usb/gadget/udc/tegra_xudc.c | 3808 > +++ > 3 files changed, 3820 insertions(+) > create mode 100644 drivers/usb/gadget/udc/tegra_xudc.c > > diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig > index ef0259a..fe6028e 100644 > --- a/drivers/usb/gadget/udc/Kconfig > +++ b/drivers/usb/gadget/udc/Kconfig > @@ -440,6 +440,17 @@ config USB_GADGET_XILINX > dynamically linked module called "udc-xilinx" and force all > gadget drivers to also be dynamically linked. > > +config USB_TEGRA_XUDC > + tristate "NVIDIA Tegra Superspeed USB 3.0 Device Controller" > + depends on ARCH_TEGRA > + select USB_ROLE_SWITCH > + help > + Enables NVIDIA Tegra USB 3.0 device mode controller driver. > + > + Say "y" to link the driver statically, or "m" to build a > + dynamically linked module called "tegra_xudc" and force all > + gadget drivers to also be dynamically linked. > + > source "drivers/usb/gadget/udc/aspeed-vhub/Kconfig" > > # > diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile > index 897f648..1c55c96 100644 > --- a/drivers/usb/gadget/udc/Makefile > +++ b/drivers/usb/gadget/udc/Makefile > @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_BCM63XX_UDC) += bcm63xx_udc.o > obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o > fsl_usb2_udc-y := fsl_udc_core.o > fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o > +obj-$(CONFIG_USB_TEGRA_XUDC) += tegra_xudc.o > obj-$(CONFIG_USB_M66592) += m66592-udc.o > obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o > obj-$(CONFIG_USB_RENESAS_USB3) += renesas_usb3.o > diff --git a/drivers/usb/gadget/udc/tegra_xudc.c > b/drivers/usb/gadget/udc/tegra_xudc.c > new file mode 100644 > index 000..26a889b > --- /dev/null > +++ b/drivers/usb/gadget/udc/tegra_xudc.c > @@ -0,0 +1,3808 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * NVIDIA Tegra XUSB device mode controller > + * > + * Copyright (c) 2013-2019, NVIDIA CORPORATION. All rights reserved. > + * Copyright (c) 2015, Google Inc. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* XUSB_DEV registers */ > +#define SPARAM 0x000 > +#define SPARAM_ERSTMAX_SHIFT 16 > +#define SPARAM_ERSTMAX_MASK GENMASK(4, 0) > +#define DB 0x004 > +#define DB_TARGET_SHIFT 8 > +#define DB_TARGET_MASK GENMASK(7, 0) > +#define DB_STREAMID_SHIFT 16 > +#define DB_STREAMID_MASK GENMASK(15, 0) To me, define it as : #define DB_STREAMID_MASK GENMASK(31, 16), it's more clearer. and define another macro #define DB_STREAMID(x) (((x) & 0x) << 16) this can avoid over flow sometimes, of cause it'll not happen for DB_STREAM, but may happen for BD_TARGET when use the way you write > +#define ERSTSZ 0x008 > +#define ERSTSZ_ERSTXSZ_SHIFT(x) ((x) * 16) > +#define ERSTSZ_ERSTXSZ_MASK GENMASK(15, 0) > +#define ERSTXBALO(x) (0x010 + 8 * (x)) > +#define ERSTXBAHI(x) (0x014 + 8 * (x)) > +#define ERDPLO 0x020 > +#define ERDPLO_EHB BIT(3) > +#define ERDPHI 0x024 > +#define EREPLO 0x028 > +#define EREPLO_ECS BIT(0) > +#define EREPLO_SEGI BIT(1) > +#define EREPHI 0x02c > +#define CTRL 0x030 > +#define CTRL_RUN BIT(0) > +#define CTRL_LSE BIT(1) > +#define CTRL_IE BIT(4) > +#define CTRL_SMI_EVT BIT(5) > +#define CTRL_SMI_DSE BIT(6) > +#define CTRL_EWE BIT(7) > +#define CTRL_DEVADDR_SHIFT 24 > +#define CTRL_DEVADDR_MASK GENMASK(6, 0) > +#define CTRL_ENABLE BIT(31) > +#define ST 0x034 > +#define ST_RC BIT(0) > +#define ST_IP BIT(4) > +#define RT_IMOD 0x038 > +#define RT_IMOD_IMODI_SHIFT 0 > +#define RT_IMOD_IMODI_MASK GENMASK(15, 0) > +#define RT_IMOD_IMODC_SHIFT 16 > +#define RT_IMOD_IMODC_MASK GENMASK(15, 0) > +#define PORTSC 0x03c > +#define PORTSC_CCS BIT(0) > +#define PORTSC_PED BIT(1) > +#define PORTSC_PR BIT(4) > +#define PORTSC_PLS_SHIFT 5 > +#define PORTSC_PLS_MASK GENMASK(3, 0) > +#define PORTSC_PLS_U0 0x0 > +#define PORTSC_PLS_U2 0x2 > +#define PORTSC_PLS_U3 0x3 > +#define PORTSC_PLS_DISABLED 0x4 > +#define PORTSC_PLS_RXDETECT 0x5 > +#define PORTSC_PLS_INACTIVE 0x6 > +#define PORTSC_PLS_RESUME 0xf > +#define PORTSC_PS_SHIFT 10 > +#define PORTSC_PS_MASK GENMASK(3, 0) > +#define PORTSC_PS_UNDEFINED 0x0 > +#define PORTSC_PS_FS 0x1 > +#define PORTSC_PS_LS 0x2 > +#define PORT
Re: [PATCH v8 00/11] add USB GPIO based connection detection driver
On Mon, 2019-08-05 at 12:06 +0200, Linus Walleij wrote: > On Wed, Jul 24, 2019 at 10:51 AM Chunfeng Yun > wrote: > > > Because the USB Connector is introduced and the requirement of > > usb-connector.txt binding, the old way using extcon to support > > USB Dual-Role switch is now deprecated, meanwhile there is no > > available common driver when use Type-B connector, typically > > using an input GPIO to detect USB ID pin. > > However while this was going on, > drivers/extcon/extcon-fsa9480.c was merged and that detects > not only GPIO on the USB port but multiplexed usecases such > as UART over the USB micro PHY (and no that UART is not > a USB UART, but an actual RX/TX over D-/D+). > > That driver also measure a whole slew of funny resistance > values on the ID pin, that is how it does its job. I look into the spec of fsa9480, it indeed detect many USB accessories. But this driver is used for simplest cases that only uses micro receptacle with id-pin/vbus-pin > > But for just "hey I'm plugged in" we can surely keep this > ID on GPIO detection in the USB subsystem. Sorry, you mean provide a common API? could you please describe more clearer about your suggestion? Introducing a single driver using usb_role_switch will help to keep transparent for USB controller driver, no matter it uses type-c or micro Thanks a lot > > I just get a bit insecure about how we should ideally > handle these "funny-PHY's". > > Yours, > Linus Walleij
Re: [PATCH v8 08/11] usb: roles: get usb-role-switch from parent
Hi Heikki, On Mon, 2019-07-29 at 17:25 +0300, Heikki Krogerus wrote: > On Wed, Jul 24, 2019 at 04:50:42PM +0800, Chunfeng Yun wrote: > > when the USB host controller is the parent of the connector, > > usually type-B, sometimes don't need the graph, so we should > > check whether it's parent registers usb-role-switch or not > > firstly, and get it if exists. > > > > Signed-off-by: Heikki Krogerus > > I don't think I actually wrote the patch. I may have proposed the code > for you, but I never prepared a patch out out that. Please drop the > above Signed-off-by line if that is the case. I case I really did > write the patch, then you are missing the "From: Heikki..." first > line, but I really don't remember preparing the patch. > > If the idea came from me, you can use for example the suggested-by > tag: "Suggested-by: Heikki Krogerus > > Signed-off-by: Chunfeng Yun > > --- > > v8: no changes > > v7: > > add signed-off-by Chunfeng > > > > v6: > > new patch > > --- > > drivers/usb/roles/class.c | 25 + > > 1 file changed, 21 insertions(+), 4 deletions(-) > > > > diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c > > index 5b637aaf311f..87439a84c983 100644 > > --- a/drivers/usb/roles/class.c > > +++ b/drivers/usb/roles/class.c > > @@ -114,6 +114,19 @@ static void *usb_role_switch_match(struct > > device_connection *con, int ep, > > return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); > > } > > > > +static struct usb_role_switch * > > +usb_role_switch_is_parent(struct fwnode_handle *fwnode) > > +{ > > + struct fwnode_handle *parent = fwnode_get_parent(fwnode); > > + struct device *dev; > > + > > + if (!parent || !fwnode_property_present(parent, "usb-role-switch")) > > + return NULL; > > + > > + dev = class_find_device(role_class, NULL, parent, switch_fwnode_match); > > + return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); > > +} > > + > > /** > > * usb_role_switch_get - Find USB role switch linked with the caller > > * @dev: The caller device > > @@ -125,8 +138,10 @@ struct usb_role_switch *usb_role_switch_get(struct > > device *dev) > > { > > struct usb_role_switch *sw; > > > > - sw = device_connection_find_match(dev, "usb-role-switch", NULL, > > - usb_role_switch_match); > > + sw = usb_role_switch_is_parent(dev_fwnode(dev)); > > + if (!sw) > > + sw = device_connection_find_match(dev, "usb-role-switch", NULL, > > + usb_role_switch_match); > > > > if (!IS_ERR_OR_NULL(sw)) > > WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); > > @@ -146,8 +161,10 @@ struct usb_role_switch > > *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) > > { > > struct usb_role_switch *sw; > > > > - sw = fwnode_connection_find_match(fwnode, "usb-role-switch", NULL, > > - usb_role_switch_match); > > + sw = usb_role_switch_is_parent(fwnode); > > + if (!sw) > > + sw = fwnode_connection_find_match(fwnode, "usb-role-switch", > > + NULL, usb_role_switch_match); > > if (!IS_ERR_OR_NULL(sw)) > > WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); > > > > -- > > 2.21.0 > > thanks, >
[PATCH v2 2/2] usb: xhci-mtk: add an optional xhci_ck clock
Some SoCs may have an optional clock xhci_ck (125M or 200M), it usually uses the same PLL as sys_ck, so support it. Signed-off-by: Chunfeng Yun --- v2 no changes --- drivers/usb/host/xhci-mtk.c | 13 + drivers/usb/host/xhci-mtk.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 026fe18972d3..b18a6baef204 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -216,6 +216,10 @@ static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk) return PTR_ERR(mtk->sys_clk); } + mtk->xhci_clk = devm_clk_get_optional(dev, "xhci_ck"); + if (IS_ERR(mtk->xhci_clk)) + return PTR_ERR(mtk->xhci_clk); + mtk->ref_clk = devm_clk_get_optional(dev, "ref_ck"); if (IS_ERR(mtk->ref_clk)) return PTR_ERR(mtk->ref_clk); @@ -244,6 +248,12 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) goto sys_clk_err; } + ret = clk_prepare_enable(mtk->xhci_clk); + if (ret) { + dev_err(mtk->dev, "failed to enable xhci_clk\n"); + goto xhci_clk_err; + } + ret = clk_prepare_enable(mtk->mcu_clk); if (ret) { dev_err(mtk->dev, "failed to enable mcu_clk\n"); @@ -261,6 +271,8 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) dma_clk_err: clk_disable_unprepare(mtk->mcu_clk); mcu_clk_err: + clk_disable_unprepare(mtk->xhci_clk); +xhci_clk_err: clk_disable_unprepare(mtk->sys_clk); sys_clk_err: clk_disable_unprepare(mtk->ref_clk); @@ -272,6 +284,7 @@ static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk) { clk_disable_unprepare(mtk->dma_clk); clk_disable_unprepare(mtk->mcu_clk); + clk_disable_unprepare(mtk->xhci_clk); clk_disable_unprepare(mtk->sys_clk); clk_disable_unprepare(mtk->ref_clk); } diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h index 8be8c5f7ff62..5ac458b7d2e0 100644 --- a/drivers/usb/host/xhci-mtk.h +++ b/drivers/usb/host/xhci-mtk.h @@ -139,6 +139,7 @@ struct xhci_hcd_mtk { struct regulator *vusb33; struct regulator *vbus; struct clk *sys_clk;/* sys and mac clock */ + struct clk *xhci_clk; struct clk *ref_clk; struct clk *mcu_clk; struct clk *dma_clk; -- 2.21.0
[PATCH v2 1/2] dt-bindings: usb: mtk-xhci: add an optional xhci_ck clock
Add a new optional clock xhci_ck Signed-off-by: Chunfeng Yun --- v2 changes: 1. add the new clock at the end, suggested by Rob --- Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt index 266c2d917a28..f3e4acecabe8 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt @@ -30,7 +30,8 @@ Required properties: the following ones are optional: "ref_ck": reference clock used by low power mode etc, "mcu_ck": mcu_bus clock for register access, - "dma_ck": dma_bus clock for data transfer by DMA + "dma_ck": dma_bus clock for data transfer by DMA, + "xhci_ck": controller clock - phys : see usb-hcd.txt in the current directory @@ -100,7 +101,7 @@ Required properties: - clocks : a list of phandle + clock-specifier pairs, one for each entry in clock-names - clock-names : must contain "sys_ck", and the following ones are optional: - "ref_ck", "mcu_ck" and "dma_ck" + "ref_ck", "mcu_ck" and "dma_ck", "xhci_ck" Optional properties: - vbus-supply : reference to the VBUS regulator; -- 2.21.0
[PATCH v8 09/11] usb: common: create Kconfig file
Create Kconfig file for USB common core, and move USB_LED_TRIG and USB_ULPI_BUS configs into the new file from the parent Kconfig, it will help to add new configs later. Signed-off-by: Chunfeng Yun --- v8: new patch --- drivers/usb/Kconfig| 35 +-- drivers/usb/common/Kconfig | 38 ++ 2 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 drivers/usb/common/Kconfig diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 6e59d370ef81..7bf94e65ed2f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -36,8 +36,7 @@ menuconfig USB_SUPPORT if USB_SUPPORT -config USB_COMMON - tristate +source "drivers/usb/common/Kconfig" config USB_ARCH_HAS_HCD def_bool y @@ -175,36 +174,4 @@ source "drivers/usb/typec/Kconfig" source "drivers/usb/roles/Kconfig" -config USB_LED_TRIG - bool "USB LED Triggers" - depends on LEDS_CLASS && LEDS_TRIGGERS - select USB_COMMON - help - This option adds LED triggers for USB host and/or gadget activity. - - Say Y here if you are working on a system with led-class supported - LEDs and you want to use them as activity indicators for USB host or - gadget. - -config USB_ULPI_BUS - tristate "USB ULPI PHY interface support" - select USB_COMMON - help - UTMI+ Low Pin Interface (ULPI) is specification for a commonly used - USB 2.0 PHY interface. The ULPI specification defines a standard set - of registers that can be used to detect the vendor and product which - allows ULPI to be handled as a bus. This module is the driver for that - bus. - - The ULPI interfaces (the buses) are registered by the drivers for USB - controllers which support ULPI register access and have ULPI PHY - attached to them. The ULPI PHY drivers themselves are normal PHY - drivers. - - ULPI PHYs provide often functions such as ADP sensing/probing (OTG - protocol) and USB charger detection. - - To compile this driver as a module, choose M here: the module will - be called ulpi. - endif # USB_SUPPORT diff --git a/drivers/usb/common/Kconfig b/drivers/usb/common/Kconfig new file mode 100644 index ..848545b099cf --- /dev/null +++ b/drivers/usb/common/Kconfig @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: GPL-2.0 + +config USB_COMMON + tristate + + +config USB_LED_TRIG + bool "USB LED Triggers" + depends on LEDS_CLASS && LEDS_TRIGGERS + select USB_COMMON + help + This option adds LED triggers for USB host and/or gadget activity. + + Say Y here if you are working on a system with led-class supported + LEDs and you want to use them as activity indicators for USB host or + gadget. + +config USB_ULPI_BUS + tristate "USB ULPI PHY interface support" + select USB_COMMON + help + UTMI+ Low Pin Interface (ULPI) is specification for a commonly used + USB 2.0 PHY interface. The ULPI specification defines a standard set + of registers that can be used to detect the vendor and product which + allows ULPI to be handled as a bus. This module is the driver for that + bus. + + The ULPI interfaces (the buses) are registered by the drivers for USB + controllers which support ULPI register access and have ULPI PHY + attached to them. The ULPI PHY drivers themselves are normal PHY + drivers. + + ULPI PHYs provide often functions such as ADP sensing/probing (OTG + protocol) and USB charger detection. + + To compile this driver as a module, choose M here: the module will + be called ulpi. + -- 2.21.0
[PATCH v8 06/11] device connection: Add fwnode_connection_find_match()
From: Heikki Krogerus The fwnode_connection_find_match() function is exactly the same as device_connection_find_match(), except it takes struct fwnode_handle as parameter instead of struct device. That allows locating device connections before the device entries have been created. Signed-off-by: Heikki Krogerus Signed-off-by: Chunfeng Yun --- v8: no changes v7: rebased on Rafael's tree [1] (after rc4), provided by Heikki [1] https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git/log/?h=linux-next v6: new patch --- drivers/base/devcon.c | 43 ++ include/linux/device.h | 10 +++--- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c index 09f28479b243..986ad89de2f9 100644 --- a/drivers/base/devcon.c +++ b/drivers/base/devcon.c @@ -12,9 +12,6 @@ static DEFINE_MUTEX(devcon_lock); static LIST_HEAD(devcon_list); -typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, - void *data); - static void * fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id, void *data, devcon_match_fn_t match) @@ -60,6 +57,34 @@ fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id, return NULL; } +/** + * fwnode_connection_find_match - Find connection from a device node + * @fwnode: Device node with the connection + * @con_id: Identifier for the connection + * @data: Data for the match function + * @match: Function to check and convert the connection description + * + * Find a connection with unique identifier @con_id between @fwnode and another + * device node. @match will be used to convert the connection description to + * data the caller is expecting to be returned. + */ +void *fwnode_connection_find_match(struct fwnode_handle *fwnode, + const char *con_id, void *data, + devcon_match_fn_t match) +{ + void *ret; + + if (!fwnode || !match) + return NULL; + + ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); + if (ret) + return ret; + + return fwnode_devcon_match(fwnode, con_id, data, match); +} +EXPORT_SYMBOL_GPL(fwnode_connection_find_match); + /** * device_connection_find_match - Find physical connection to a device * @dev: Device with the connection @@ -83,15 +108,9 @@ void *device_connection_find_match(struct device *dev, const char *con_id, if (!match) return NULL; - if (fwnode) { - ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); - if (ret) - return ret; - - ret = fwnode_devcon_match(fwnode, con_id, data, match); - if (ret) - return ret; - } + ret = fwnode_connection_find_match(fwnode, con_id, data, match); + if (ret) + return ret; mutex_lock(&devcon_lock); diff --git a/include/linux/device.h b/include/linux/device.h index c330b75c6c57..ba73878f8e93 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -778,10 +778,14 @@ struct device_connection { struct list_headlist; }; +typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, + void *data); + +void *fwnode_connection_find_match(struct fwnode_handle *fwnode, + const char *con_id, void *data, + devcon_match_fn_t match); void *device_connection_find_match(struct device *dev, const char *con_id, - void *data, - void *(*match)(struct device_connection *con, - int ep, void *data)); + void *data, devcon_match_fn_t match); struct device *device_connection_find(struct device *dev, const char *con_id); -- 2.21.0
[PATCH v8 02/11] dt-bindings: connector: add optional properties for Type-B
Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for usb-b-connector Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring --- v8 no changes v7 no changes v6 no changes v5 changes: 1. add reviewed by Rob v4 no changes v3 changes: 1. add GPIO direction, and use fixed-regulator for GPIO controlled VBUS regulator suggested by Rob; v2 changes: 1. describe more clear for vbus-gpios and vbus-supply suggested by Hans --- .../bindings/connector/usb-connector.txt | 14 ++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt index cef556d4e5ee..d357987181ee 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.txt +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt @@ -17,6 +17,20 @@ Optional properties: - self-powered: Set this property if the usb device that has its own power source. +Optional properties for usb-b-connector: +- id-gpios: an input gpio for USB ID pin. +- vbus-gpios: an input gpio for USB VBUS pin, used to detect presence of + VBUS 5V. + see gpio/gpio.txt. +- vbus-supply: a phandle to the regulator for USB VBUS if needed when host + mode or dual role mode is supported. + Particularly, if use an output GPIO to control a VBUS regulator, should + model it as a regulator. + see regulator/fixed-regulator.yaml +- pinctrl-names : a pinctrl state named "default" is optional +- pinctrl-0 : pin control group + see pinctrl/pinctrl-bindings.txt + Optional properties for usb-c-connector: - power-role: should be one of "source", "sink" or "dual"(DRP) if typec connector has power support. -- 2.21.0
[PATCH v8 01/11] dt-binding: usb: add usb-role-switch property
Add a property usb-role-switch to tell the driver that use USB Role Switch framework to handle the role switch, it's useful when the driver has already supported other ways, such as extcon framework etc. Cc: Biju Das Cc: Yu Chen Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring Reviewed-by: Heikki Krogerus --- v8: no changes v7: no changes v6: 1. merge into this series patch 2. add Reviewed-by (no v4, v5) v3: add property type, modify description suggested by Heikki v2: describe it in terms of h/w functionality suggested by Rob v1: the property is discussed in: [v2,2/7] dt-bindings: usb: renesas_usb3: add usb-role-switch property https://patchwork.kernel.org/patch/10852497/ Mediatek and Hisilicon also try to use it: [v4,3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch https://patchwork.kernel.org/patch/10918385/ [v4,6/6] usb: mtu3: register a USB Role Switch for dual role mode https://patchwork.kernel.org/patch/10918367/ [v6,10/13] usb: dwc3: Registering a role switch in the DRD code https://patchwork.kernel.org/patch/10909981/ --- Documentation/devicetree/bindings/usb/generic.txt | 4 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt index 0a74ab8dfdc2..cf5a1ad456e6 100644 --- a/Documentation/devicetree/bindings/usb/generic.txt +++ b/Documentation/devicetree/bindings/usb/generic.txt @@ -30,6 +30,10 @@ Optional properties: optional for OTG device. - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is optional for OTG device. + - usb-role-switch: boolean, 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.txt. This is an attribute to a USB controller such as: -- 2.21.0
[PATCH v8 05/11] usb: roles: Introduce stubs for the exiting functions in role.h.
From: Yu Chen This patch adds stubs for the exiting functions while CONFIG_USB_ROLE_SWITCH does not enabled. Cc: Greg Kroah-Hartman Cc: Heikki Krogerus Cc: Hans de Goede Cc: Andy Shevchenko Cc: John Stultz Reviewed-by: Heikki Krogerus Signed-off-by: Yu Chen Signed-off-by: Chunfeng Yun --- v8: no changes v7: add Signed-off-by Chunfeng v6: merge this patch [1] into this series to add new API [1] https://patchwork.kernel.org/patch/10909971/ --- include/linux/usb/role.h | 30 ++ 1 file changed, 30 insertions(+) diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h index c05ffa6abda9..da2b9641b877 100644 --- a/include/linux/usb/role.h +++ b/include/linux/usb/role.h @@ -42,6 +42,8 @@ struct usb_role_switch_desc { bool allow_userspace_control; }; + +#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); struct usb_role_switch *usb_role_switch_get(struct device *dev); @@ -51,5 +53,33 @@ struct usb_role_switch * usb_role_switch_register(struct device *parent, const struct usb_role_switch_desc *desc); void usb_role_switch_unregister(struct usb_role_switch *sw); +#else +static inline int usb_role_switch_set_role(struct usb_role_switch *sw, + enum usb_role role) +{ + return 0; +} + +static inline enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) +{ + return USB_ROLE_NONE; +} + +static inline struct usb_role_switch *usb_role_switch_get(struct device *dev) +{ + return ERR_PTR(-ENODEV); +} + +static inline void usb_role_switch_put(struct usb_role_switch *sw) { } + +static inline struct usb_role_switch * +usb_role_switch_register(struct device *parent, +const struct usb_role_switch_desc *desc) +{ + return ERR_PTR(-ENODEV); +} + +static inline void usb_role_switch_unregister(struct usb_role_switch *sw) { } +#endif #endif /* __LINUX_USB_ROLE_H */ -- 2.21.0
[PATCH v8 07/11] usb: roles: Add fwnode_usb_role_switch_get() function
From: Heikki Krogerus The fwnode_usb_role_switch_get() function is exactly the same as usb_role_switch_get(), except that it takes struct fwnode_handle as parameter instead of struct device. Signed-off-by: Heikki Krogerus Signed-off-by: Chunfeng Yun Tested-by: Biju Das --- v8: no changes v7: add signed-off-by Chunfeng and tested-by Biju v6: new patch --- drivers/usb/roles/class.c | 20 include/linux/usb/role.h | 7 +++ 2 files changed, 27 insertions(+) diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 86defca6623e..5b637aaf311f 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -135,6 +135,26 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) } EXPORT_SYMBOL_GPL(usb_role_switch_get); +/** + * fwnode_usb_role_switch_get - Find USB role switch linked with the caller + * @fwnode: The caller device node + * + * This is similar to the usb_role_switch_get() function above, but it searches + * the switch using fwnode instead of device entry. + */ +struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) +{ + struct usb_role_switch *sw; + + sw = fwnode_connection_find_match(fwnode, "usb-role-switch", NULL, + usb_role_switch_match); + if (!IS_ERR_OR_NULL(sw)) + WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); + + return sw; +} +EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get); + /** * usb_role_switch_put - Release handle to a switch * @sw: USB Role Switch diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h index da2b9641b877..2d77f97df72d 100644 --- a/include/linux/usb/role.h +++ b/include/linux/usb/role.h @@ -47,6 +47,7 @@ struct usb_role_switch_desc { int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); struct usb_role_switch *usb_role_switch_get(struct device *dev); +struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *node); void usb_role_switch_put(struct usb_role_switch *sw); struct usb_role_switch * @@ -70,6 +71,12 @@ static inline struct usb_role_switch *usb_role_switch_get(struct device *dev) return ERR_PTR(-ENODEV); } +static inline struct usb_role_switch * +fwnode_usb_role_switch_get(struct fwnode_handle *node) +{ + return ERR_PTR(-ENODEV); +} + static inline void usb_role_switch_put(struct usb_role_switch *sw) { } static inline struct usb_role_switch * -- 2.21.0
[PATCH v8 08/11] usb: roles: get usb-role-switch from parent
when the USB host controller is the parent of the connector, usually type-B, sometimes don't need the graph, so we should check whether it's parent registers usb-role-switch or not firstly, and get it if exists. Signed-off-by: Heikki Krogerus Signed-off-by: Chunfeng Yun --- v8: no changes v7: add signed-off-by Chunfeng v6: new patch --- drivers/usb/roles/class.c | 25 + 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 5b637aaf311f..87439a84c983 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -114,6 +114,19 @@ static void *usb_role_switch_match(struct device_connection *con, int ep, return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); } +static struct usb_role_switch * +usb_role_switch_is_parent(struct fwnode_handle *fwnode) +{ + struct fwnode_handle *parent = fwnode_get_parent(fwnode); + struct device *dev; + + if (!parent || !fwnode_property_present(parent, "usb-role-switch")) + return NULL; + + dev = class_find_device(role_class, NULL, parent, switch_fwnode_match); + return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); +} + /** * usb_role_switch_get - Find USB role switch linked with the caller * @dev: The caller device @@ -125,8 +138,10 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) { struct usb_role_switch *sw; - sw = device_connection_find_match(dev, "usb-role-switch", NULL, - usb_role_switch_match); + sw = usb_role_switch_is_parent(dev_fwnode(dev)); + if (!sw) + sw = device_connection_find_match(dev, "usb-role-switch", NULL, + usb_role_switch_match); if (!IS_ERR_OR_NULL(sw)) WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); @@ -146,8 +161,10 @@ struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) { struct usb_role_switch *sw; - sw = fwnode_connection_find_match(fwnode, "usb-role-switch", NULL, - usb_role_switch_match); + sw = usb_role_switch_is_parent(fwnode); + if (!sw) + sw = fwnode_connection_find_match(fwnode, "usb-role-switch", + NULL, usb_role_switch_match); if (!IS_ERR_OR_NULL(sw)) WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); -- 2.21.0
[PATCH v8 10/11] usb: common: add USB GPIO based connection detection driver
Due to the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated when use Type-B connector. This patch introduces a driver of Type-B connector which typically uses an input GPIO to detect USB ID pin, and try to replace the function provided by extcon-usb-gpio driver Signed-off-by: Chunfeng Yun Tested-by: Nagarjuna Kristam --- v8 changes: 1. rename the driver name and usb new compatible suggested by Heikki 2. move the driver into usb/common from usb/roles suggested by Heikki v7 changes: 1. remove macro DEV_PMS_OPS suggested by Andy 2. add tested-by Nagarjuna v6 changes: 1. get usb-role-swtich by usb_role_switch_get() v5 changes: 1. put usb_role_switch when error happens suggested by Biju 2. don't treat bype-B connector as a virtual device suggested by Rob v4 changes: 1. remove linux/gpio.h suggested by Linus 2. put node when error happens v3 changes: 1. treat bype-B connector as a virtual device; 2. change file name again v2 changes: 1. file name is changed 2. use new compatible --- drivers/usb/common/Kconfig | 13 ++ drivers/usb/common/Makefile| 1 + drivers/usb/common/usb-conn-gpio.c | 284 + 3 files changed, 298 insertions(+) create mode 100644 drivers/usb/common/usb-conn-gpio.c diff --git a/drivers/usb/common/Kconfig b/drivers/usb/common/Kconfig index 848545b099cf..d611477aae41 100644 --- a/drivers/usb/common/Kconfig +++ b/drivers/usb/common/Kconfig @@ -36,3 +36,16 @@ config USB_ULPI_BUS To compile this driver as a module, choose M here: the module will be called ulpi. +config USB_CONN_GPIO + tristate "USB GPIO Based Connection Detection Driver" + depends on GPIOLIB + select USB_ROLE_SWITCH + help + The driver supports USB role switch between host and device via GPIO + based USB cable detection, used typically if an input GPIO is used + to detect USB ID pin, and another input GPIO may be also used to detect + Vbus pin at the same time, it also can be used to enable/disable + device if an input GPIO is only used to detect Vbus pin. + + To compile the driver as a module, choose M here: the module will + be called usb-conn-gpio.ko diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile index 0a7c45e85481..8227ffc2cf0b 100644 --- a/drivers/usb/common/Makefile +++ b/drivers/usb/common/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_USB_COMMON) += usb-common.o usb-common-y += common.o usb-common-$(CONFIG_USB_LED_TRIG) += led.o +obj-$(CONFIG_USB_CONN_GPIO)+= usb-conn-gpio.o obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o obj-$(CONFIG_USB_ULPI_BUS) += ulpi.o diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c new file mode 100644 index ..e4935e99f295 --- /dev/null +++ b/drivers/usb/common/usb-conn-gpio.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * USB GPIO Based Connection Detection Driver + * + * Copyright (C) 2019 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USB_GPIO_DEB_MS20 /* ms */ +#define USB_GPIO_DEB_US((USB_GPIO_DEB_MS) * 1000) /* us */ + +#define USB_CONN_IRQF \ + (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT) + +struct usb_conn_info { + struct device *dev; + struct usb_role_switch *role_sw; + enum usb_role last_role; + struct regulator *vbus; + struct delayed_work dw_det; + unsigned long debounce_jiffies; + + struct gpio_desc *id_gpiod; + struct gpio_desc *vbus_gpiod; + int id_irq; + int vbus_irq; +}; + +/** + * "DEVICE" = VBUS and "HOST" = !ID, so we have: + * Both "DEVICE" and "HOST" can't be set as active at the same time + * so if "HOST" is active (i.e. ID is 0) we keep "DEVICE" inactive + * even if VBUS is on. + * + * Role | ID | VBUS + * + * [1] DEVICE| H | H + * [2] NONE | H | L + * [3] HOST | L | H + * [4] HOST | L | L + * + * In case we have only one of these signals: + * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1 + * - ID only - we want to distinguish between [1] and [4], so VBUS = ID + */ +static void usb_conn_detect_cable(struct work_struct *work) +{ + struct usb_conn_info *info; + enum usb_role role; + int id, vbus, ret; + + info = container_of(to_delayed_work(work), + struct usb_conn_info, dw_det); + + /* check ID and VBUS */ + id = info->id_gpiod
[PATCH v8 11/11] usb: mtu3: register a USB Role Switch for dual role mode
Because extcon is not allowed for new bindings, and the dual role switch is supported by USB Role Switch, especially for Type-C drivers, so register a USB Role Switch to support the new way Signed-off-by: Chunfeng Yun --- v8 no changes v7 no changes v6 no changes v5 no changes v4 changes: 1. assign fwnode member of usb_role_switch struct suggested by Heikki v3 changes: 1. select USB_ROLE_SWITCH in Kconfig suggested by Heikki 2. rename ssusb_mode_manual_switch() to ssusb_mode_switch() v2 no changes --- drivers/usb/mtu3/Kconfig| 1 + drivers/usb/mtu3/mtu3.h | 5 drivers/usb/mtu3/mtu3_debugfs.c | 4 +-- drivers/usb/mtu3/mtu3_dr.c | 48 - drivers/usb/mtu3/mtu3_dr.h | 6 ++--- drivers/usb/mtu3/mtu3_plat.c| 3 ++- 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig index 928c2cd6fc00..bf98fd36341d 100644 --- a/drivers/usb/mtu3/Kconfig +++ b/drivers/usb/mtu3/Kconfig @@ -44,6 +44,7 @@ config USB_MTU3_DUAL_ROLE bool "Dual Role mode" depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3)) depends on (EXTCON=y || EXTCON=USB_MTU3) + select USB_ROLE_SWITCH help This is the default mode of working of MTU3 controller where both host and gadget features are enabled. diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 76ecf12fdf62..6087be236a35 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -199,6 +199,9 @@ struct mtu3_gpd_ring { * @id_nb : notifier for iddig(idpin) detection * @id_work : work of iddig detection notifier * @id_event : event of iddig detecion notifier +* @role_sw : use USB Role Switch to support dual-role switch, can't use +* extcon at the same time, and extcon is deprecated. +* @role_sw_used : true when the USB Role Switch is used. * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not * @manual_drd_enabled: it's true when supports dual-role device by debugfs * to switch host/device modes depending on user input. @@ -212,6 +215,8 @@ struct otg_switch_mtk { struct notifier_block id_nb; struct work_struct id_work; unsigned long id_event; + struct usb_role_switch *role_sw; + bool role_sw_used; bool is_u3_drd; bool manual_drd_enabled; }; diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c index 62c57ddc554e..c96e5dab0a48 100644 --- a/drivers/usb/mtu3/mtu3_debugfs.c +++ b/drivers/usb/mtu3/mtu3_debugfs.c @@ -453,9 +453,9 @@ static ssize_t ssusb_mode_write(struct file *file, const char __user *ubuf, return -EFAULT; if (!strncmp(buf, "host", 4) && !ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 1); + ssusb_mode_switch(ssusb, 1); } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 0); + ssusb_mode_switch(ssusb, 0); } else { dev_err(ssusb->dev, "wrong or duplicated setting\n"); return -EINVAL; diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 5fcb71af875a..08e18448e8b8 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -7,6 +7,8 @@ * Author: Chunfeng Yun */ +#include + #include "mtu3.h" #include "mtu3_dr.h" #include "mtu3_debug.h" @@ -280,7 +282,7 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) * This is useful in special cases, such as uses TYPE-A receptacle but also * wants to support dual-role mode. */ -void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) +void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; @@ -318,6 +320,47 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb, mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value); } +static int ssusb_role_sw_set(struct device *dev, enum usb_role role) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + bool to_host = false; + + if (role == USB_ROLE_HOST) + to_host = true; + + if (to_host ^ ssusb->is_host) + ssusb_mode_switch(ssusb, to_host); + + return 0; +} + +static enum usb_role ssusb_role_sw_get(struct device *dev) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + enum usb_role role; + + role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE; + + return role; +} + +static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx) +{ + struct usb_role_switch_desc role_sx_desc = { 0 }; + struct ssusb_mtk *ssusb = + container_of(otg_sx, struct ssusb_mtk, otg_switch); + +
[PATCH v8 03/11] dt-bindings: usb: add binding for USB GPIO based connection detection driver
It's used to support dual role switch via GPIO when use Type-B receptacle, typically the USB ID pin is connected to an input GPIO, and also used to enable/disable device when the USB Vbus pin is connected to an input GPIO. Signed-off-by: Chunfeng Yun --- v8 changes: 1. rename the title 2. change the compatible as "linux,usb-conn-gpio" instead of "linux,typeb-conn-gpio" v7 changes: 1. add description for device only mode v6 changes: 1. remove status and port nodes in example 2. make vbus-supply as optional property v5 changes: 1. treat type-B connector as child device of USB controller's, but not as a separate virtual device, suggested by Rob 2. put connector's port node under connector node, suggested by Rob v4 no changes v3 changes: 1. treat type-B connector as a virtual device, but not child device of USB controller's v2 changes: 1. new patch to make binding clear suggested by Hans --- .../devicetree/bindings/usb/usb-conn-gpio.txt | 31 +++ 1 file changed, 31 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/usb-conn-gpio.txt diff --git a/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt b/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt new file mode 100644 index ..d4d107fedc22 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/usb-conn-gpio.txt @@ -0,0 +1,31 @@ +USB GPIO Based Connection Detection + +This is typically used to switch dual role mode from the USB ID pin connected +to an input GPIO, and also used to enable/disable device mode from the USB +Vbus pin connected to an input GPIO. + +Required properties: +- compatible : should include "linux,usb-conn-gpio" and "usb-b-connector". +- id-gpios, vbus-gpios : input gpios, either one of them must be present, + and both can be present as well. + see connector/usb-connector.txt + +Optional properties: +- vbus-supply : can be present if needed when supports dual role mode. + see connector/usb-connector.txt + +- Sub-nodes: + - port : can be present. + see graph.txt + +Example: + +&mtu3 { + connector { + compatible = "linux,usb-conn-gpio", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb_p0_vbus>; + }; +}; -- 2.21.0
[PATCH v8 00/11] add USB GPIO based connection detection driver
Because the USB Connector is introduced and the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated, meanwhile there is no available common driver when use Type-B connector, typically using an input GPIO to detect USB ID pin. This patch series introduce a USB GPIO based connection detecton driver and try to replace the function provided by extcon-usb-gpio driver. v8 changes: 1. rename the driver's name suggested by Heikki 2. move the driver from usb/roles/ into usb/common/ suggested by Heikki 3. introduce Kconfig for usb common core to add the new driver 4. modify binding of the driver 5. rename the subject title v7 changes: 1. [5/10]: add signed-off-by Chunfeng 2. [6/10]: add signed-off-by Chunfeng 3. [6/10]: depends on linux-next of Rafael's tree [1] 4. [7/10]: add signed-off-by Chunfeng and tested-by Biju 5. [9/10]: add tested-by Nagarjuna, and remove DEV_PMS_OPS suggested by Andy [1] https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git/log/?h=linux-next v6 changes: 1. merge [1] and [2] into this series 2. don't use graph anymore to find usb-role-switch 3. abandon [3] and introduce three patches (6, 7, 8 in this series) to rebuild APIs getting usb-role-switch [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ [2]: [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ [3]: [PATCH v5 4/6] usb: roles: add API to get usb_role_switch by node v5 changes: 1. remove linux/of.h and put usb_role_switch when error happens, suggested by Biju 2. treat Type-B connector as USB controller's child, but not as a virtual device, suggested by Rob 3. provide and use generic property "usb-role-switch", see [1], suggested by Rob Note: this series still depends on [2] [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ [2]: [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v4 changes: 1. use switch_fwnode_match() to find fwnode suggested by Heikki 2. assign fwnode member of usb_role_switch struct suggested by Heikki 3. make [4/6] depend on [2] 3. remove linux/gpio.h suggested by Linus 4. put node when error happens [4/6] usb: roles: add API to get usb_role_switch by node [2] [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v3 changes: 1. add GPIO direction, and use fixed-regulator for GPIO controlled VBUS regulator suggested by Rob; 2. rebuild fwnode_usb_role_switch_get() suggested by Andy and Heikki 3. treat the type-B connector as a virtual device; 4. change file name of driver again 5. select USB_ROLE_SWITCH in mtu3/Kconfig suggested by Heikki 6. rename ssusb_mode_manual_switch() to ssusb_mode_switch() v2 changes: 1. make binding clear, and add a extra compatible suggested by Hans Chunfeng Yun (8): dt-binding: usb: add usb-role-switch property dt-bindings: connector: add optional properties for Type-B dt-bindings: usb: add binding for USB GPIO based connection detection driver dt-bindings: usb: mtu3: add properties about USB Role Switch usb: roles: get usb-role-switch from parent usb: common: create Kconfig file usb: common: add USB GPIO based connection detection driver usb: mtu3: register a USB Role Switch for dual role mode Heikki Krogerus (2): device connection: Add fwnode_connection_find_match() usb: roles: Add fwnode_usb_role_switch_get() function Yu Chen (1): usb: roles: Introduce stubs for the exiting functions in role.h. .../bindings/connector/usb-connector.txt | 14 + .../devicetree/bindings/usb/generic.txt | 4 + .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 + .../devicetree/bindings/usb/usb-conn-gpio.txt | 31 ++ drivers/base/devcon.c | 43 ++- drivers/usb/Kconfig | 35 +-- drivers/usb/common/Kconfig| 51 drivers/usb/common/Makefile | 1 + drivers/usb/common/usb-conn-gpio.c| 284 ++ drivers/usb/mtu3/Kconfig | 1 + drivers/usb/mtu3/mtu3.h | 5 + drivers/usb/mtu3/mtu3_debugfs.c | 4 +- drivers/usb/mtu3/mtu3_dr.c| 48 ++- drivers/usb/mtu3/mtu3_dr.h| 6 +- drivers/usb/mtu3/mtu3_plat.c | 3 +- drivers/usb/roles/class.c | 41 ++- include/linux/device.h| 10 +- include/linux/usb/role.h | 37 +++ 18 files changed, 570 insertions(+), 58 deletions(-) create mode 100644 Documentation/devicetree/bindings
[PATCH v8 04/11] dt-bindings: usb: mtu3: add properties about USB Role Switch
Now the USB Role Switch is supported, so add properties about it, and modify some description related. Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring --- v8 no changes v7 no changes v6 no changes v5 changes: 1. modify decription about extcon and vbus-supply properties 2. make this patch depend on [1] [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ v4 no changes v3 no changes v2 changes: 1. fix typo 2. refer new binding about connector property --- .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 ++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt index 3382b5cb471d..3a8300205cdb 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt @@ -28,8 +28,13 @@ Optional properties: parent's address space - extcon : external connector for vbus and idpin changes detection, needed when supports dual-role mode. + it's considered valid for compatibility reasons, not allowed for + new bindings, and use "usb-role-switch" property instead. - vbus-supply : reference to the VBUS regulator, needed when supports dual-role mode. + it's considered valid for compatibility reasons, not allowed for + new bindings, and put into a usb-connector node. + see connector/usb-connector.txt. - pinctrl-names : a pinctrl state named "default" is optional, and need be defined if auto drd switch is enabled, that means the property dr_mode is set as "otg", and meanwhile the property "mediatek,enable-manual-drd" @@ -39,6 +44,8 @@ Optional properties: - maximum-speed : valid arguments are "super-speed", "high-speed" and "full-speed"; refer to usb/generic.txt + - usb-role-switch : use USB Role Switch to support dual-role switch, but + not extcon; see usb/generic.txt. - enable-manual-drd : supports manual dual-role switch via debugfs; usually used when receptacle is TYPE-A and also wants to support dual-role mode. @@ -61,6 +68,9 @@ The xhci should be added as subnode to mtu3 as shown in the following example if host mode is enabled. The DT binding details of xhci can be found in: Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +The port would be added as subnode if use "usb-role-switch" property. + see graph.txt + Example: ssusb: usb@11271000 { compatible = "mediatek,mt8173-mtu3"; -- 2.21.0
Re: [PATCH 3/5] dt-bindings: usb: mtk-xhci: add an optional xhci_ck clock
On Tue, 2019-07-09 at 08:22 -0600, Rob Herring wrote: > On Wed, Jun 12, 2019 at 01:55:19PM +0800, Chunfeng Yun wrote: > > Add a new optional clock xhci_ck > > > > Signed-off-by: Chunfeng Yun > > --- > > Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 3 ++- > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt > > b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt > > index 266c2d917a28..91c0704b586b 100644 > > --- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt > > +++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt > > @@ -29,6 +29,7 @@ Required properties: > > "sys_ck": controller clock used by normal mode, > > the following ones are optional: > > "ref_ck": reference clock used by low power mode etc, > > + "xhci_ck": controller clock, > > "mcu_ck": mcu_bus clock for register access, > > "dma_ck": dma_bus clock for data transfer by DMA > > A new clock should go at the end to stay backwards compatible. Ok, will fix it, thanks > > > > > @@ -100,7 +101,7 @@ Required properties: > > - clocks : a list of phandle + clock-specifier pairs, one for each > > entry in clock-names > > - clock-names : must contain "sys_ck", and the following ones are > > optional: > > - "ref_ck", "mcu_ck" and "dma_ck" > > + "ref_ck", "xhci_ck", "mcu_ck" and "dma_ck" > > > > Optional properties: > > - vbus-supply : reference to the VBUS regulator; > > -- > > 2.21.0 > >
Re: [Patch V4 4/8] dt-bindings: usb: Add NVIDIA Tegra XUSB device mode controller binding
On Mon, 2019-06-10 at 15:49 +0530, Nagarjuna Kristam wrote: > Add device-tree binding documentation for the XUSB device mode controller > present on Tegra210 SoC. This controller supports the USB 3.0 > specification. > > Signed-off-by: Nagarjuna Kristam > Reviewed-by: JC Kuo > --- > .../devicetree/bindings/usb/nvidia,tegra-xudc.txt | 108 > + > 1 file changed, 108 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.txt > > diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.txt > b/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.txt > new file mode 100644 > index 000..cde4e11 > --- /dev/null > +++ b/Documentation/devicetree/bindings/usb/nvidia,tegra-xudc.txt > @@ -0,0 +1,108 @@ > +Device tree binding for NVIDIA Tegra XUSB device mode controller (XUDC) > +=== > + > +The Tegra XUDC controller supports both USB 2.0 HighSpeed/FullSpeed and > +USB 3.0 SuperSpeed protocols. > + > +Required properties: > + > +- compatible: For Tegra210, must contain "nvidia,tegra210-xudc". > +- reg: Must contain the base and length of the XUSB device registers, XUSB > device > + PCI Config registers and XUSB device controller registers. > +- reg-names: Must include all the register names needed for the driver add names list? > +- interrupts: Must contain the XUSB device interrupt. > +- clocks: Must contain an entry for all clocks used. > + See ../clock/clock-bindings.txt for details. > +- clock-names: Must include the following entries: > + - dev: Clock to enable core XUSB dev clock. > + - ss: Clock to enable XUSB super speed clock. > + - ss_src: Clock to enable XUSB super speed dev clock. > + - hs_src: Clock to enable XUSB high speed dev clock. > + - fs_src: Clock to enable XUSB full speed dev clock. > +- nvidia,xusb-padctl: phandle to the XUSB pad controller that is used to > + configure the USB pads used by the XUDC controller. > +- power-domains: A list of PM domain specifiers that reference each > power-domain > + used by the XUSB device mode controller. This list must comprise of a > specifier > + for the XUSBA and XUSBB power-domains. See ../power/power_domain.txt and > + ../arm/tegra/nvidia,tegra20-pmc.txt for details. > +- power-domain-names: A list of names that represent each of the specifiers > in > + the 'power-domains' property. Must include 'ss' and 'dev'. > +- phys: Must contain an entry for each entry in phy-names. > + See ../phy/phy-bindings.txt for details. > +- phy-names: Should include an entry for each PHY used by the controller. > + Names must be "usb2", and "usb3" if support SuperSpeed device mode. > + - "usb3" phy, SuperSpeed (SSTX+/SSTX-/SSRX+/SSRX-) data lines. > + - "usb2" phy, USB 2.0 (D+/D-) data lines. > + > +For Tegra210: > +- avddio-usb-supply: PCIe/USB3 analog logic power supply. Must supply 1.05 V. > +- hvdd-usb-supply: USB controller power supply. Must supply 3.3 V. > + > + > +Optional properties: > + > +- usb-role-switch: boolean property to indicate use of USB Role Switch > driver. > + > +Sub-nodes: > +-- > +- The port would be added as subnode if use "usb-role-switch" property. > + see graph.txt. > + > +Example: > + > + pmc: pmc@7000e400 { > + compatible = "nvidia,tegra210-pmc"; > + reg = <0x0 0x7000e400 0x0 0x400>; > + clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>; > + clock-names = "pclk", "clk32k_in"; > + > + powergates { > + pd_xusbss: xusba { > + clocks = <&tegra_car TEGRA210_CLK_XUSB_SS>; > + resets = <&tegra_car 156>; > + #power-domain-cells = <0>; > + }; > + > + pd_xusbdev: xusbb { > + clocks = <&tegra_car TEGRA210_CLK_XUSB_DEV>; > + resets = <&tegra_car 95>; > + #power-domain-cells = <0>; > + }; > + }; > + }; > + > + xudc@700d { > + compatible = "nvidia,tegra210-xudc"; > + reg = <0x0 0x700d 0x0 0x8000>, > + <0x0 0x700d8000 0x0 0x1000>, > + <0x0 0x700d9000 0x0 0x1000>; > + reg-names = "base", "fpci", "ipfs"; > + > + interrupts = ; > + > + clocks = <&tegra_car TEGRA210_CLK_XUSB_DEV>, > + <&tegra_car TEGRA210_CLK_XUSB_SS>, > + <&tegra_car TEGRA210_CLK_XUSB_SSP_SRC>, > + <&tegra_car TEGRA210_CLK_XUSB_HS_SRC>, > + <&tegra_car TEGRA210_CLK_XUSB_FS_SRC>; > + clock-names = "dev", "ss", "ss_src", "hs_src", "fs_src"; > + > + power-domains = <&pd_xusbdev>, <&pd_xusbss>; > + power-domain-names
Re: [Patch V3 7/8] usb: gadget: Add UDC driver for tegra XUSB device mode controller
Hi, Nagarjuna, On Fri, 2019-05-24 at 12:20 +0530, Nagarjuna Kristam wrote: > > On 16-05-2019 14:38, Chunfeng Yun wrote: > > On Thu, 2019-05-16 at 12:09 +0530, Nagarjuna Kristam wrote: > >> This patch adds UDC driver for tegra XUSB 3.0 device mode controller. > >> XUSB device mode controller supports SS, HS and FS modes > >> > >> Based on work by: > >> Mark Kuo > >> Andrew Bresticker > >> > >> Signed-off-by: Nagarjuna Kristam > >> --- > >> drivers/usb/gadget/udc/Kconfig | 10 + > >> drivers/usb/gadget/udc/Makefile |1 + > >> drivers/usb/gadget/udc/tegra_xudc.c | 3807 > >> +++ > >> 3 files changed, 3818 insertions(+) > >> create mode 100644 drivers/usb/gadget/udc/tegra_xudc.c > >> > >> diff --git a/drivers/usb/gadget/udc/Kconfig > >> b/drivers/usb/gadget/udc/Kconfig > >> index ef0259a..b35856c 100644 > >> --- a/drivers/usb/gadget/udc/Kconfig > >> +++ b/drivers/usb/gadget/udc/Kconfig > >> @@ -440,6 +440,16 @@ config USB_GADGET_XILINX > >> dynamically linked module called "udc-xilinx" and force all > >> gadget drivers to also be dynamically linked. > >> > >> +config USB_TEGRA_XUDC > >> + tristate "NVIDIA Tegra Superspeed USB 3.0 Device Controller" > >> + depends on ARCH_TEGRA > >> + help > >> + Enables NVIDIA Tegra USB 3.0 device mode controller driver. > >> + > >> + Say "y" to link the driver statically, or "m" to build a > >> + dynamically linked module called "tegra_xudc" and force all > >> + gadget drivers to also be dynamically linked. > >> + > >> source "drivers/usb/gadget/udc/aspeed-vhub/Kconfig" > >> [...] > >> +static int tegra_xudc_probe(struct platform_device *pdev) > >> +{ > >> + struct tegra_xudc *xudc; > >> + struct resource *res; > >> + unsigned int i; > >> + int err; > >> + > >> + xudc = devm_kzalloc(&pdev->dev, sizeof(*xudc), GFP_ATOMIC); > >> + if (!xudc) > >> + return -ENOMEM; > >> + > >> + xudc->dev = &pdev->dev; > >> + platform_set_drvdata(pdev, xudc); > >> + > >> + xudc->soc = of_device_get_match_data(&pdev->dev); > >> + if (!xudc->soc) > >> + return -ENODEV; > >> + > >> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > >> + xudc->base = devm_ioremap_resource(&pdev->dev, res); > >> + if (IS_ERR(xudc->base)) > >> + return PTR_ERR(xudc->base); > >> + xudc->phys_base = res->start; > >> + > >> + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > >> + xudc->fpci = devm_ioremap_resource(&pdev->dev, res); > >> + if (IS_ERR(xudc->fpci)) > >> + return PTR_ERR(xudc->fpci); > >> + > >> + if (xudc->soc->has_ipfs) { > >> + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); > >> + xudc->ipfs = devm_ioremap_resource(&pdev->dev, res); > >> + if (IS_ERR(xudc->ipfs)) > >> + return PTR_ERR(xudc->ipfs); > >> + } > > providing register names will make more clear > > will migrate to platform_get_resource_by_name > > >> + > >> + xudc->irq = platform_get_irq(pdev, 0); > >> + if (xudc->irq < 0) { > >> + dev_err(xudc->dev, "failed to get IRQ: %d\n", > >> + xudc->irq); > >> + return xudc->irq; > >> + } > >> + > >> + err = devm_request_irq(&pdev->dev, xudc->irq, tegra_xudc_irq, 0, > >> + dev_name(&pdev->dev), xudc); > >> + if (err < 0) { > >> + dev_err(xudc->dev, "failed to claim IRQ#%u: %d\n", xudc->irq, > >> + err); > >> + return err; > >> + } > >> + > >> + xudc->clks = devm_kcalloc(&pdev->dev, xudc->soc->num_clks, > >> +sizeof(*xudc->clks), GFP_KERNEL); > >> + if (!xudc->clks) > >> + return -ENOMEM; > >> + > >> + for (i = 0; i < xudc->soc->num_clks; i++) > >> + xudc->clks[i].id = xudc->soc->clock_names[i]; > >> + > >> +
Re: [Patch V3 7/8] usb: gadget: Add UDC driver for tegra XUSB device mode controller
On Thu, 2019-05-16 at 12:09 +0530, Nagarjuna Kristam wrote: > This patch adds UDC driver for tegra XUSB 3.0 device mode controller. > XUSB device mode controller supports SS, HS and FS modes > > Based on work by: > Mark Kuo > Andrew Bresticker > > Signed-off-by: Nagarjuna Kristam > --- > drivers/usb/gadget/udc/Kconfig | 10 + > drivers/usb/gadget/udc/Makefile |1 + > drivers/usb/gadget/udc/tegra_xudc.c | 3807 > +++ > 3 files changed, 3818 insertions(+) > create mode 100644 drivers/usb/gadget/udc/tegra_xudc.c > > diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig > index ef0259a..b35856c 100644 > --- a/drivers/usb/gadget/udc/Kconfig > +++ b/drivers/usb/gadget/udc/Kconfig > @@ -440,6 +440,16 @@ config USB_GADGET_XILINX > dynamically linked module called "udc-xilinx" and force all > gadget drivers to also be dynamically linked. > > +config USB_TEGRA_XUDC > + tristate "NVIDIA Tegra Superspeed USB 3.0 Device Controller" > + depends on ARCH_TEGRA > + help > + Enables NVIDIA Tegra USB 3.0 device mode controller driver. > + > + Say "y" to link the driver statically, or "m" to build a > + dynamically linked module called "tegra_xudc" and force all > + gadget drivers to also be dynamically linked. > + > source "drivers/usb/gadget/udc/aspeed-vhub/Kconfig" > > # > diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile > index 897f648..1c55c96 100644 > --- a/drivers/usb/gadget/udc/Makefile > +++ b/drivers/usb/gadget/udc/Makefile > @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_BCM63XX_UDC) += bcm63xx_udc.o > obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o > fsl_usb2_udc-y := fsl_udc_core.o > fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o > +obj-$(CONFIG_USB_TEGRA_XUDC) += tegra_xudc.o > obj-$(CONFIG_USB_M66592) += m66592-udc.o > obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o > obj-$(CONFIG_USB_RENESAS_USB3) += renesas_usb3.o > diff --git a/drivers/usb/gadget/udc/tegra_xudc.c > b/drivers/usb/gadget/udc/tegra_xudc.c > new file mode 100644 > index 000..6cd4675 > --- /dev/null > +++ b/drivers/usb/gadget/udc/tegra_xudc.c > @@ -0,0 +1,3807 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * NVIDIA Tegra XUSB device mode controller > + * > + * Copyright (c) 2013-2019, NVIDIA CORPORATION. All rights reserved. > + * Copyright (c) 2015, Google Inc. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* XUSB_DEV registers */ > +#define SPARAM 0x000 > +#define SPARAM_ERSTMAX_SHIFT 16 > +#define SPARAM_ERSTMAX_MASK 0x1f use GENMASK() to generate mask? > +#define DB 0x004 > +#define DB_TARGET_SHIFT 8 > +#define DB_TARGET_MASK 0xff > +#define DB_STREAMID_SHIFT 16 > +#define DB_STREAMID_MASK 0x > +#define ERSTSZ 0x008 > +#define ERSTSZ_ERSTXSZ_SHIFT(x) ((x) * 16) > +#define ERSTSZ_ERSTXSZ_MASK 0x > +#define ERSTXBALO(x) (0x010 + 8 * (x)) > +#define ERSTXBAHI(x) (0x014 + 8 * (x)) > +#define ERDPLO 0x020 > +#define ERDPLO_EHB BIT(3) > +#define ERDPHI 0x024 > +#define EREPLO 0x028 > +#define EREPLO_ECS BIT(0) > +#define EREPLO_SEGI BIT(1) > +#define EREPHI 0x02c > +#define CTRL 0x030 > +#define CTRL_RUN BIT(0) > +#define CTRL_LSE BIT(1) > +#define CTRL_IE BIT(4) > +#define CTRL_SMI_EVT BIT(5) > +#define CTRL_SMI_DSE BIT(6) > +#define CTRL_EWE BIT(7) > +#define CTRL_DEVADDR_SHIFT 24 > +#define CTRL_DEVADDR_MASK 0x7f > +#define CTRL_ENABLE BIT(31) > +#define ST 0x034 > +#define ST_RC BIT(0) > +#define ST_IP BIT(4) > +#define RT_IMOD 0x038 > +#define RT_IMOD_IMODI_SHIFT 0 > +#define RT_IMOD_IMODI_MASK 0x > +#define RT_IMOD_IMODC_SHIFT 16 > +#define RT_IMOD_IMODC_MASK 0x > +#define PORTSC 0x03c > +#define PORTSC_CCS BIT(0) > +#define PORTSC_PED BIT(1) > +#define PORTSC_PR BIT(4) > +#define PORTSC_PLS_SHIFT 5 > +#define PORTSC_PLS_MASK 0xf > +#define PORTSC_PLS_U0 0x0 > +#define PORTSC_PLS_U2 0x2 > +#define PORTSC_PLS_U3 0x3 > +#define PORTSC_PLS_DISABLED 0x4 > +#define PORTSC_PLS_RXDETECT 0x5 > +#define PORTSC_PLS_INACTIVE 0x6 > +#define PORTSC_PLS_RESUME 0xf > +#define PORTSC_PS_SHIFT 10 > +#define PORTSC_PS_MASK 0xf > +#define PORTSC_PS_UNDEFINED 0x0 > +#define PORTSC_PS_FS 0x1 > +#define PORTSC_PS_LS 0x2 > +#define PORTSC_PS_HS 0x3 > +#define PORTSC_PS_SS 0x4 > +#define PORTSC_LWS BIT(16) > +#define PORTSC_CSC BIT(17) > +#define PORTSC_WRC BIT(19) > +#define PORTSC_PRC BIT(21) > +#define PORTSC_PLC BIT(22) > +#define PORTSC_CEC BIT(23) > +#define PORTSC_WPR BIT(30) > +#define PORTSC_CHANGE_MASK (PORTSC_CSC | PORTSC_WRC | PORTSC_PRC | \ > + PORTSC_PLC | PORTSC_CEC) > +#defi
Re: [PATCH v6 4/7] usb: gadget: udc: renesas_usb3: Add dual role switch support
On Wed, 2019-05-15 at 13:09 +0100, Biju Das wrote: > The RZ/G2E cat874 board has a type-c connector connected to hd3ss3220 usb > type-c drp port controller. This patch adds dual role switch support for > the type-c connector using the usb role switch class framework. > > Signed-off-by: Biju Das > --- > V5-->V6 >* Added graph api's to find the role supported by the connector. > V4-->V5 >* Incorporated Shimoda-san's review comment > (https://patchwork.kernel.org/patch/10902537/) > V3-->V4 >* No Change > V2-->V3 >* Incorporated Shimoda-san's review comment > (https://patchwork.kernel.org/patch/10852507/) >* Used renesas,usb-role-switch property for differentiating USB > role switch associated with Type-C port controller driver. > V1-->V2 >* Driver uses usb role clas for handling dual role switch and handling > connect/disconnect events instead of extcon. > --- > drivers/usb/gadget/udc/renesas_usb3.c | 121 > -- > 1 file changed, 114 insertions(+), 7 deletions(-) > > diff --git a/drivers/usb/gadget/udc/renesas_usb3.c > b/drivers/usb/gadget/udc/renesas_usb3.c > index 7dc2485..1d41998 100644 > --- a/drivers/usb/gadget/udc/renesas_usb3.c > +++ b/drivers/usb/gadget/udc/renesas_usb3.c > @@ -24,6 +24,7 @@ > #include > #include > #include > +#include > #include > > /* register definitions */ > @@ -351,6 +352,8 @@ struct renesas_usb3 { > int disabled_count; > > struct usb_request *ep0_req; > + > + enum usb_role connection_state; > u16 test_mode; > u8 ep0_buf[USB3_EP0_BUF_SIZE]; > bool softconnect; > @@ -359,6 +362,7 @@ struct renesas_usb3 { > bool extcon_usb;/* check vbus and set EXTCON_USB */ > bool forced_b_device; > bool start_to_connect; > + bool dual_role_sw; > }; > > #define gadget_to_renesas_usb3(_gadget) \ > @@ -699,8 +703,10 @@ static void usb3_mode_config(struct renesas_usb3 *usb3, > bool host, bool a_dev) > unsigned long flags; > > spin_lock_irqsave(&usb3->lock, flags); > - usb3_set_mode_by_role_sw(usb3, host); > - usb3_vbus_out(usb3, a_dev); > + if (!usb3->dual_role_sw || usb3->connection_state != USB_ROLE_NONE) { > + usb3_set_mode_by_role_sw(usb3, host); > + usb3_vbus_out(usb3, a_dev); > + } > /* for A-Peripheral or forced B-device mode */ > if ((!host && a_dev) || usb3->start_to_connect) > usb3_connect(usb3); > @@ -716,7 +722,8 @@ static void usb3_check_id(struct renesas_usb3 *usb3) > { > usb3->extcon_host = usb3_is_a_device(usb3); > > - if (usb3->extcon_host && !usb3->forced_b_device) > + if ((!usb3->dual_role_sw && usb3->extcon_host && !usb3->forced_b_device) > + || usb3->connection_state == USB_ROLE_HOST) > usb3_mode_config(usb3, true, true); > else > usb3_mode_config(usb3, false, false); > @@ -2343,14 +2350,65 @@ static enum usb_role > renesas_usb3_role_switch_get(struct device *dev) > return cur_role; > } > > -static int renesas_usb3_role_switch_set(struct device *dev, > - enum usb_role role) > +static void handle_ext_role_switch_states(struct device *dev, > + enum usb_role role) > +{ > + struct renesas_usb3 *usb3 = dev_get_drvdata(dev); > + struct device *host = usb3->host_dev; > + enum usb_role cur_role = renesas_usb3_role_switch_get(dev); > + > + switch (role) { > + case USB_ROLE_NONE: > + usb3->connection_state = USB_ROLE_NONE; > + if (usb3->driver) > + usb3_disconnect(usb3); > + usb3_vbus_out(usb3, false); > + break; > + case USB_ROLE_DEVICE: > + if (usb3->connection_state == USB_ROLE_NONE) { > + usb3->connection_state = USB_ROLE_DEVICE; > + usb3_set_mode(usb3, false); > + if (usb3->driver) > + usb3_connect(usb3); > + } else if (cur_role == USB_ROLE_HOST) { > + device_release_driver(host); > + usb3_set_mode(usb3, false); > + if (usb3->driver) > + usb3_connect(usb3); > + } > + usb3_vbus_out(usb3, false); > + break; > + case USB_ROLE_HOST: > + if (usb3->connection_state == USB_ROLE_NONE) { > + if (usb3->driver) > + usb3_disconnect(usb3); > + > + usb3->connection_state = USB_ROLE_HOST; > + usb3_set_mode(usb3, true); > + usb3_vbus_out(usb3, true); > + if (device_attach(host) < 0) > + dev_err(dev, "device_attach(host) failed\n"); > + } else if (cur_role == USB_ROLE_DEVICE) { > +
Re: [PATCH v5 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
On Tue, 2019-05-14 at 13:12 -0500, Rob Herring wrote: > On Tue, May 14, 2019 at 04:47:19PM +0800, Chunfeng Yun wrote: > > It's used to support dual role switch via GPIO when use Type-B > > receptacle, typically the USB ID pin is connected to an input > > GPIO pin > > > > Signed-off-by: Chunfeng Yun > > --- > > v5 changes: > > 1. treat type-B connector as child device of USB controller's, but not > > as a separate virtual device, suggested by Rob > > 2. put connector's port node under connector node, suggested by Rob > > > > v4 no changes > > > > v3 changes: > > 1. treat type-B connector as a virtual device, but not child device of > > USB controller's > > > > v2 changes: > > 1. new patch to make binding clear suggested by Hans > > --- > > .../bindings/usb/typeb-conn-gpio.txt | 42 +++ > > 1 file changed, 42 insertions(+) > > create mode 100644 > > Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt > > > > diff --git a/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt > > b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt > > new file mode 100644 > > index ..20dd3499a348 > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt > > @@ -0,0 +1,42 @@ > > +USB Type-B GPIO Connector > > + > > +This is used to switch dual role mode from the USB ID pin connected to > > +an input GPIO pin. > > + > > +Required properties: > > +- compatible : should include "linux,typeb-conn-gpio" and > > "usb-b-connector". > > I don't think we need "linux,typeb-conn-gpio". Not all usb-b-connector child node need bind this driver, by adding the new compatible can avoid unnecessary binding. > A driver can decide to > handle GPIO lines if they present Yes, the driver, e.g. USB controller driver can do it, but here I want to provide a common driver to handle this special case, like extcon-usb-gpio driver does, and try to keep transparency from USB controller driver. > or we assume the parent device handles > ID and/or Vbus if they are not present. Yes, it will > > > +- id-gpios, vbus-gpios : either one of them must be present, and both > > + can be present as well. > > Please clarify that vbus-gpios is an input to sense Vbus presence as an > output it should be modelled as a regulator only. Ok, will add more description. > > These should be added to usb-connector.txt. Already add them in [1/6]. > > The result of all this is you don't need this file. Just additions to > usb-connector.txt. Here add more constrains for id-gpios and vbus-gpios, at least one should be present, although they are both optional, this is not true for some cases, so not suitable to add into usb-connector.txt. > > > +- vbus-supply : can be present if needed when supports dual role mode or > > + host mode. > > + see connector/usb-connector.txt > > + > > +Sub-nodes: > > +- port : should be present. > > + see graph.txt > > + > > +Example: > > + > > +&mtu3 { > > + status = "okay"; > > Don't show status in examples. Ok, will drop it. > > > + > > + connector { > > + compatible = "linux,typeb-conn-gpio", "usb-b-connector"; > > + label = "micro-USB"; > > + type = "micro"; > > + id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>; > > + vbus-supply = <&usb_p0_vbus>; > > + > > + port { > > + bconn_ep: endpoint@0 { > > + remote-endpoint = <&usb_role_sw>; > > + }; > > + }; > > + }; > > + > > + port { > > + usb_role_sw: endpoint@0 { > > + remote-endpoint = <&bconn_ep>; > > + }; > > + }; > > When the host controller is the parent of the connector, you don't need > the graph unless you're describing the alternate modes in Type-C. Ok, got it. Thanks a lot. > > > +}; > > -- > > 2.21.0 > >
[PATCH v5 4/6] usb: roles: add API to get usb_role_switch by node
Add fwnode_usb_role_switch_get() to make easier to get usb_role_switch by fwnode which register it. It's useful when there is not device_connection registered between two drivers and only knows the fwnode which register usb_role_switch. Signed-off-by: Chunfeng Yun Tested-by: Biju Das --- v5 changes: 1. remove linux/of.h suggested by Biju 2. add tested by Biju Note: still depends on [1] [1]: [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v4 changes: 1. use switch_fwnode_match() to find fwnode suggested by Heikki 2. this patch now depends on [1] [1] [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v3 changes: 1. use fwnodes instead of node suggested by Andy 2. rebuild the API suggested by Heikki v2 no changes --- drivers/usb/roles/class.c | 24 include/linux/usb/role.h | 8 2 files changed, 32 insertions(+) diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index f45d8df5cfb8..4a1f09a41ec0 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -135,6 +135,30 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) } EXPORT_SYMBOL_GPL(usb_role_switch_get); +/** + * fwnode_usb_role_switch_get - Find USB role switch by it's parent fwnode + * @fwnode: The fwnode that register USB role switch + * + * Finds and returns role switch registered by @fwnode. The reference count + * for the found switch is incremented. + */ +struct usb_role_switch * +fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) +{ + struct usb_role_switch *sw; + struct device *dev; + + dev = class_find_device(role_class, NULL, fwnode, switch_fwnode_match); + if (!dev) + return ERR_PTR(-EPROBE_DEFER); + + sw = to_role_switch(dev); + WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); + + return sw; +} +EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get); + /** * usb_role_switch_put - Release handle to a switch * @sw: USB Role Switch diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h index da2b9641b877..35d460f9ec40 100644 --- a/include/linux/usb/role.h +++ b/include/linux/usb/role.h @@ -48,6 +48,8 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); struct usb_role_switch *usb_role_switch_get(struct device *dev); void usb_role_switch_put(struct usb_role_switch *sw); +struct usb_role_switch * +fwnode_usb_role_switch_get(struct fwnode_handle *fwnode); struct usb_role_switch * usb_role_switch_register(struct device *parent, @@ -72,6 +74,12 @@ static inline struct usb_role_switch *usb_role_switch_get(struct device *dev) static inline void usb_role_switch_put(struct usb_role_switch *sw) { } +static inline struct usb_role_switch * +fwnode_usb_role_switch_get(struct fwnode_handle *fwnode) +{ + return ERR_PTR(-ENODEV); +} + static inline struct usb_role_switch * usb_role_switch_register(struct device *parent, const struct usb_role_switch_desc *desc) -- 2.21.0
[PATCH v5 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
It's used to support dual role switch via GPIO when use Type-B receptacle, typically the USB ID pin is connected to an input GPIO pin Signed-off-by: Chunfeng Yun --- v5 changes: 1. treat type-B connector as child device of USB controller's, but not as a separate virtual device, suggested by Rob 2. put connector's port node under connector node, suggested by Rob v4 no changes v3 changes: 1. treat type-B connector as a virtual device, but not child device of USB controller's v2 changes: 1. new patch to make binding clear suggested by Hans --- .../bindings/usb/typeb-conn-gpio.txt | 42 +++ 1 file changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt diff --git a/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt new file mode 100644 index ..20dd3499a348 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt @@ -0,0 +1,42 @@ +USB Type-B GPIO Connector + +This is used to switch dual role mode from the USB ID pin connected to +an input GPIO pin. + +Required properties: +- compatible : should include "linux,typeb-conn-gpio" and "usb-b-connector". +- id-gpios, vbus-gpios : either one of them must be present, and both + can be present as well. +- vbus-supply : can be present if needed when supports dual role mode or + host mode. + see connector/usb-connector.txt + +Sub-nodes: +- port : should be present. + see graph.txt + +Example: + +&mtu3 { + status = "okay"; + + connector { + compatible = "linux,typeb-conn-gpio", "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>; + vbus-supply = <&usb_p0_vbus>; + + port { + bconn_ep: endpoint@0 { + remote-endpoint = <&usb_role_sw>; + }; + }; + }; + + port { + usb_role_sw: endpoint@0 { + remote-endpoint = <&bconn_ep>; + }; + }; +}; -- 2.21.0
[PATCH v5 6/6] usb: mtu3: register a USB Role Switch for dual role mode
Because extcon is not allowed for new bindings, and the dual role switch is supported by USB Role Switch, especially for Type-C drivers, so register a USB Role Switch to support the new way Signed-off-by: Chunfeng Yun --- v5 no change v4 changes: 1. assign fwnode member of usb_role_switch struct suggested by Heikki v3 changes: 1. select USB_ROLE_SWITCH in Kconfig suggested by Heikki 2. rename ssusb_mode_manual_switch() to ssusb_mode_switch() v2 no change --- drivers/usb/mtu3/Kconfig| 1 + drivers/usb/mtu3/mtu3.h | 5 drivers/usb/mtu3/mtu3_debugfs.c | 4 +-- drivers/usb/mtu3/mtu3_dr.c | 48 - drivers/usb/mtu3/mtu3_dr.h | 6 ++--- drivers/usb/mtu3/mtu3_plat.c| 3 ++- 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig index bcc23486c4ed..88e3db7b3016 100644 --- a/drivers/usb/mtu3/Kconfig +++ b/drivers/usb/mtu3/Kconfig @@ -43,6 +43,7 @@ config USB_MTU3_DUAL_ROLE bool "Dual Role mode" depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3)) depends on (EXTCON=y || EXTCON=USB_MTU3) + select USB_ROLE_SWITCH help This is the default mode of working of MTU3 controller where both host and gadget features are enabled. diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 76ecf12fdf62..6087be236a35 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -199,6 +199,9 @@ struct mtu3_gpd_ring { * @id_nb : notifier for iddig(idpin) detection * @id_work : work of iddig detection notifier * @id_event : event of iddig detecion notifier +* @role_sw : use USB Role Switch to support dual-role switch, can't use +* extcon at the same time, and extcon is deprecated. +* @role_sw_used : true when the USB Role Switch is used. * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not * @manual_drd_enabled: it's true when supports dual-role device by debugfs * to switch host/device modes depending on user input. @@ -212,6 +215,8 @@ struct otg_switch_mtk { struct notifier_block id_nb; struct work_struct id_work; unsigned long id_event; + struct usb_role_switch *role_sw; + bool role_sw_used; bool is_u3_drd; bool manual_drd_enabled; }; diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c index b7c86ccd50b4..3ed666f94dd9 100644 --- a/drivers/usb/mtu3/mtu3_debugfs.c +++ b/drivers/usb/mtu3/mtu3_debugfs.c @@ -453,9 +453,9 @@ static ssize_t ssusb_mode_write(struct file *file, const char __user *ubuf, return -EFAULT; if (!strncmp(buf, "host", 4) && !ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 1); + ssusb_mode_switch(ssusb, 1); } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 0); + ssusb_mode_switch(ssusb, 0); } else { dev_err(ssusb->dev, "wrong or duplicated setting\n"); return -EINVAL; diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 5fcb71af875a..08e18448e8b8 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -7,6 +7,8 @@ * Author: Chunfeng Yun */ +#include + #include "mtu3.h" #include "mtu3_dr.h" #include "mtu3_debug.h" @@ -280,7 +282,7 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) * This is useful in special cases, such as uses TYPE-A receptacle but also * wants to support dual-role mode. */ -void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) +void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; @@ -318,6 +320,47 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb, mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value); } +static int ssusb_role_sw_set(struct device *dev, enum usb_role role) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + bool to_host = false; + + if (role == USB_ROLE_HOST) + to_host = true; + + if (to_host ^ ssusb->is_host) + ssusb_mode_switch(ssusb, to_host); + + return 0; +} + +static enum usb_role ssusb_role_sw_get(struct device *dev) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + enum usb_role role; + + role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE; + + return role; +} + +static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx) +{ + struct usb_role_switch_desc role_sx_desc = { 0 }; + struct ssusb_mtk *ssusb = + container_of(otg_sx, struct ssusb_mtk, otg_switch); + + if (!otg_sx->
[PATCH v5 5/6] usb: roles: add USB Type-B GPIO connector driver
Due to the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated when use Type-B connector. This patch introduces a driver of Type-B connector which typically uses an input GPIO to detect USB ID pin, and try to replace the function provided by extcon-usb-gpio driver Signed-off-by: Chunfeng Yun --- v5 changes: 1. put usb_role_switch when error happens suggested by Biju 2. don't treat bype-B connector as a virtual device suggested by Rob v4 changes: 1. remove linux/gpio.h suggested by Linus 2. put node when error happens v3 changes: 1. treat bype-B connector as a virtual device; 2. change file name again v2 changes: 1. file name is changed 2. use new compatible --- drivers/usb/roles/Kconfig | 11 ++ drivers/usb/roles/Makefile | 1 + drivers/usb/roles/typeb-conn-gpio.c | 295 3 files changed, 307 insertions(+) create mode 100644 drivers/usb/roles/typeb-conn-gpio.c diff --git a/drivers/usb/roles/Kconfig b/drivers/usb/roles/Kconfig index f8b31aa67526..d1156e18a81a 100644 --- a/drivers/usb/roles/Kconfig +++ b/drivers/usb/roles/Kconfig @@ -26,4 +26,15 @@ config USB_ROLES_INTEL_XHCI To compile the driver as a module, choose M here: the module will be called intel-xhci-usb-role-switch. +config TYPEB_CONN_GPIO + tristate "USB Type-B GPIO Connector" + depends on GPIOLIB + help + The driver supports USB role switch between host and device via GPIO + based USB cable detection, used typically if an input GPIO is used + to detect USB ID pin. + + To compile the driver as a module, choose M here: the module will + be called typeb-conn-gpio.ko + endif # USB_ROLE_SWITCH diff --git a/drivers/usb/roles/Makefile b/drivers/usb/roles/Makefile index 757a7d2797eb..5d5620d9d113 100644 --- a/drivers/usb/roles/Makefile +++ b/drivers/usb/roles/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_USB_ROLE_SWITCH) += roles.o roles-y:= class.o obj-$(CONFIG_USB_ROLES_INTEL_XHCI) += intel-xhci-usb-role-switch.o +obj-$(CONFIG_TYPEB_CONN_GPIO) += typeb-conn-gpio.o diff --git a/drivers/usb/roles/typeb-conn-gpio.c b/drivers/usb/roles/typeb-conn-gpio.c new file mode 100644 index ..988ecf565f33 --- /dev/null +++ b/drivers/usb/roles/typeb-conn-gpio.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * USB Type-B GPIO Connector Driver + * + * Copyright (C) 2019 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USB_GPIO_DEB_MS20 /* ms */ +#define USB_GPIO_DEB_US((USB_GPIO_DEB_MS) * 1000) /* us */ + +#define USB_CONN_IRQF \ + (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT) + +struct usb_conn_info { + struct device *dev; + struct usb_role_switch *role_sw; + enum usb_role last_role; + struct regulator *vbus; + struct delayed_work dw_det; + unsigned long debounce_jiffies; + + struct gpio_desc *id_gpiod; + struct gpio_desc *vbus_gpiod; + int id_irq; + int vbus_irq; +}; + +/** + * "DEVICE" = VBUS and "HOST" = !ID, so we have: + * Both "DEVICE" and "HOST" can't be set as active at the same time + * so if "HOST" is active (i.e. ID is 0) we keep "DEVICE" inactive + * even if VBUS is on. + * + * Role | ID | VBUS + * + * [1] DEVICE| H | H + * [2] NONE | H | L + * [3] HOST | L | H + * [4] HOST | L | L + * + * In case we have only one of these signals: + * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1 + * - ID only - we want to distinguish between [1] and [4], so VBUS = ID + */ +static void usb_conn_detect_cable(struct work_struct *work) +{ + struct usb_conn_info *info; + enum usb_role role; + int id, vbus, ret; + + info = container_of(to_delayed_work(work), + struct usb_conn_info, dw_det); + + /* check ID and VBUS */ + id = info->id_gpiod ? + gpiod_get_value_cansleep(info->id_gpiod) : 1; + vbus = info->vbus_gpiod ? + gpiod_get_value_cansleep(info->vbus_gpiod) : id; + + if (!id) + role = USB_ROLE_HOST; + else if (vbus) + role = USB_ROLE_DEVICE; + else + role = USB_ROLE_NONE; + + dev_dbg(info->dev, "role %d/%d, gpios: id %d, vbus %d\n", + info->last_role, role, id, vbus); + + if (info->last_role == role) { + dev_warn(info->d
[PATCH v5 1/6] dt-bindings: connector: add optional properties for Type-B
Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for usb-b-connector Signed-off-by: Chunfeng Yun Reviewed-by: Rob Herring --- v5 no changes v4 no changes v3 changes: 1. add GPIO direction, and use fixed-regulator for GPIO controlled VBUS regulator suggested by Rob; v2 changes: 1. describe more clear for vbus-gpios and vbus-supply suggested by Hans --- .../bindings/connector/usb-connector.txt | 14 ++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt index a9a2f2fc44f2..e8f9e854fd11 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.txt +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt @@ -17,6 +17,20 @@ Optional properties: - self-powered: Set this property if the usb device that has its own power source. +Optional properties for usb-b-connector: +- id-gpios: an input gpio for USB ID pin. +- vbus-gpios: an input gpio for USB VBUS pin, used to detect presence of + VBUS 5V. + see gpio/gpio.txt. +- vbus-supply: a phandle to the regulator for USB VBUS if needed when host + mode or dual role mode is supported. + Particularly, if use an output GPIO to control a VBUS regulator, should + model it as a regulator. + see regulator/fixed-regulator.yaml +- pinctrl-names : a pinctrl state named "default" is optional +- pinctrl-0 : pin control group + see pinctrl/pinctrl-bindings.txt + Optional properties for usb-c-connector: - power-role: should be one of "source", "sink" or "dual"(DRP) if typec connector has power support. -- 2.21.0
[v5 PATCH 0/6] add USB Type-B GPIO connector driver
Because the USB Connector is introduced and the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated, meanwhile there is no available common driver when use Type-B connector, typically using an input GPIO to detect USB ID pin. This patch series introduce a Type-B GPIO connector driver and try to replace the function provided by extcon-usb-gpio driver. v5 changes: 1. remove linux/of.h and put usb_role_switch when error happens, suggested by Biju 2. treat Type-B connector as USB controller's child, but not as a virtual device, suggested by Rob 3. provide and use generic property "usb-role-switch", see [1], suggested by Rob Note: this series still depends on [2] [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ [2]: [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v4 changes: 1. use switch_fwnode_match() to find fwnode suggested by Heikki 2. assign fwnode member of usb_role_switch struct suggested by Heikki 3. make [4/6] depend on [2] 3. remove linux/gpio.h suggested by Linus 4. put node when error happens [4/6] usb: roles: add API to get usb_role_switch by node [2] [v6,08/13] usb: roles: Introduce stubs for the exiting functions in role.h https://patchwork.kernel.org/patch/10909971/ v3 changes: 1. add GPIO direction, and use fixed-regulator for GPIO controlled VBUS regulator suggested by Rob; 2. rebuild fwnode_usb_role_switch_get() suggested by Andy and Heikki 3. treat the type-B connector as a virtual device; 4. change file name of driver again 5. select USB_ROLE_SWITCH in mtu3/Kconfig suggested by Heikki 6. rename ssusb_mode_manual_switch() to ssusb_mode_switch() v2 changes: 1. make binding clear, and add a extra compatible suggested by Hans Chunfeng Yun (6): dt-bindings: connector: add optional properties for Type-B dt-bindings: usb: add binding for Type-B GPIO connector driver dt-bindings: usb: mtu3: add properties about USB Role Switch usb: roles: add API to get usb_role_switch by node usb: roles: add USB Type-B GPIO connector driver usb: mtu3: register a USB Role Switch for dual role mode .../bindings/connector/usb-connector.txt | 14 + .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 + .../bindings/usb/typeb-conn-gpio.txt | 42 +++ drivers/usb/mtu3/Kconfig | 1 + drivers/usb/mtu3/mtu3.h | 5 + drivers/usb/mtu3/mtu3_debugfs.c | 4 +- drivers/usb/mtu3/mtu3_dr.c| 48 ++- drivers/usb/mtu3/mtu3_dr.h| 6 +- drivers/usb/mtu3/mtu3_plat.c | 3 +- drivers/usb/roles/Kconfig | 11 + drivers/usb/roles/Makefile| 1 + drivers/usb/roles/class.c | 24 ++ drivers/usb/roles/typeb-conn-gpio.c | 295 ++ include/linux/usb/role.h | 8 + 14 files changed, 465 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt create mode 100644 drivers/usb/roles/typeb-conn-gpio.c -- 2.21.0
[PATCH v5 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
Now the USB Role Switch is supported, so add properties about it, and modify some description related. Signed-off-by: Chunfeng Yun --- v5 changes 1. modify decription about extcon and vbus-supply properties 2. make this patch depend on [1] [1]: [v3] dt-binding: usb: add usb-role-switch property https://patchwork.kernel.org/patch/10934835/ v4: no changes v3: no changes v2 changes: 1. fix typo 2. refer new binding about connector property --- .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 ++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt index 3382b5cb471d..3a8300205cdb 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt @@ -28,8 +28,13 @@ Optional properties: parent's address space - extcon : external connector for vbus and idpin changes detection, needed when supports dual-role mode. + it's considered valid for compatibility reasons, not allowed for + new bindings, and use "usb-role-switch" property instead. - vbus-supply : reference to the VBUS regulator, needed when supports dual-role mode. + it's considered valid for compatibility reasons, not allowed for + new bindings, and put into a usb-connector node. + see connector/usb-connector.txt. - pinctrl-names : a pinctrl state named "default" is optional, and need be defined if auto drd switch is enabled, that means the property dr_mode is set as "otg", and meanwhile the property "mediatek,enable-manual-drd" @@ -39,6 +44,8 @@ Optional properties: - maximum-speed : valid arguments are "super-speed", "high-speed" and "full-speed"; refer to usb/generic.txt + - usb-role-switch : use USB Role Switch to support dual-role switch, but + not extcon; see usb/generic.txt. - enable-manual-drd : supports manual dual-role switch via debugfs; usually used when receptacle is TYPE-A and also wants to support dual-role mode. @@ -61,6 +68,9 @@ The xhci should be added as subnode to mtu3 as shown in the following example if host mode is enabled. The DT binding details of xhci can be found in: Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +The port would be added as subnode if use "usb-role-switch" property. + see graph.txt + Example: ssusb: usb@11271000 { compatible = "mediatek,mt8173-mtu3"; -- 2.21.0
Re: [PATCH v2 2/8] usb: phy: phy-mxs-usb: add imx7ulp support
On Tue, 2019-05-14 at 07:38 +, Peter Chen wrote: > At imx7ulp, the USB related analog register is located in PHY register > region too, so we need to control PLL at PHY driver directly. > > Signed-off-by: Peter Chen > --- > drivers/usb/phy/phy-mxs-usb.c | 76 > ++- > 1 file changed, 75 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c > index 1b1bb0ad40c3..90c96a8e9342 100644 > --- a/drivers/usb/phy/phy-mxs-usb.c > +++ b/drivers/usb/phy/phy-mxs-usb.c > @@ -20,6 +20,7 @@ > > #define DRIVER_NAME "mxs_phy" > > +/* Register Macro */ > #define HW_USBPHY_PWD0x00 > #define HW_USBPHY_TX 0x10 > #define HW_USBPHY_CTRL 0x30 > @@ -37,6 +38,11 @@ > #define GM_USBPHY_TX_TXCAL45DN(x)(((x) & 0xf) << 8) > #define GM_USBPHY_TX_D_CAL(x)(((x) & 0xf) << 0) > > +/* imx7ulp */ > +#define HW_USBPHY_PLL_SIC0xa0 > +#define HW_USBPHY_PLL_SIC_SET0xa4 > +#define HW_USBPHY_PLL_SIC_CLR0xa8 > + > #define BM_USBPHY_CTRL_SFTRSTBIT(31) > #define BM_USBPHY_CTRL_CLKGATE BIT(30) > #define BM_USBPHY_CTRL_OTG_ID_VALUE BIT(27) > @@ -55,6 +61,12 @@ > #define BM_USBPHY_IP_FIX (BIT(17) | BIT(18)) > > #define BM_USBPHY_DEBUG_CLKGATE BIT(30) > +/* imx7ulp */ > +#define BM_USBPHY_PLL_LOCK BIT(31) > +#define BM_USBPHY_PLL_REG_ENABLE BIT(21) > +#define BM_USBPHY_PLL_BYPASS BIT(16) > +#define BM_USBPHY_PLL_POWER BIT(12) > +#define BM_USBPHY_PLL_EN_USB_CLKSBIT(6) > > /* Anatop Registers */ > #define ANADIG_ANA_MISC0 0x150 > @@ -167,6 +179,9 @@ static const struct mxs_phy_data imx6ul_phy_data = { > .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS, > }; > > +static const struct mxs_phy_data imx7ulp_phy_data = { > +}; > + > static const struct of_device_id mxs_phy_dt_ids[] = { > { .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, }, > { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, }, > @@ -174,6 +189,7 @@ static const struct of_device_id mxs_phy_dt_ids[] = { > { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, }, > { .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, }, > { .compatible = "fsl,imx6ul-usbphy", .data = &imx6ul_phy_data, }, > + { .compatible = "fsl,imx7ulp-usbphy", .data = &imx7ulp_phy_data, }, > { /* sentinel */ } > }; > MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids); > @@ -198,6 +214,11 @@ static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy) > return mxs_phy->data == &imx6sl_phy_data; > } > > +static inline bool is_imx7ulp_phy(struct mxs_phy *mxs_phy) > +{ > + return mxs_phy->data == &imx7ulp_phy_data; > +} > + > /* > * PHY needs some 32K cycles to switch from 32K clock to > * bus (such as AHB/AXI, etc) clock. > @@ -221,14 +242,59 @@ static void mxs_phy_tx_init(struct mxs_phy *mxs_phy) > } > } > > +static int wait_for_pll_lock(const void __iomem *base) > +{ > + int loop_count = 100; > + > + /* Wait for PLL to lock */ > + do { > + if (readl(base + HW_USBPHY_PLL_SIC) & BM_USBPHY_PLL_LOCK) > + break; > + usleep_range(100, 150); > + } while (loop_count-- > 0); > + there is a common API readl_poll_timeout(), maybe you can try it. > + return readl(base + HW_USBPHY_PLL_SIC) & BM_USBPHY_PLL_LOCK > + ? 0 : -ETIMEDOUT; > +} > + > +static int mxs_phy_pll_enable(void __iomem *base, bool enable) > +{ > + int ret = 0; > + > + if (enable) { > + writel(BM_USBPHY_PLL_REG_ENABLE, base + HW_USBPHY_PLL_SIC_SET); > + writel(BM_USBPHY_PLL_BYPASS, base + HW_USBPHY_PLL_SIC_CLR); > + writel(BM_USBPHY_PLL_POWER, base + HW_USBPHY_PLL_SIC_SET); > + ret = wait_for_pll_lock(base); > + if (ret) > + return ret; > + writel(BM_USBPHY_PLL_EN_USB_CLKS, base + > + HW_USBPHY_PLL_SIC_SET); > + } else { > + writel(BM_USBPHY_PLL_EN_USB_CLKS, base + > + HW_USBPHY_PLL_SIC_CLR); > + writel(BM_USBPHY_PLL_POWER, base + HW_USBPHY_PLL_SIC_CLR); > + writel(BM_USBPHY_PLL_BYPASS, base + HW_USBPHY_PLL_SIC_SET); > + writel(BM_USBPHY_PLL_REG_ENABLE, base + HW_USBPHY_PLL_SIC_CLR); > + } > + > + return ret; > +} > + > static int mxs_phy_hw_init(struct mxs_phy *mxs_phy) > { > int ret; > void __iomem *base = mxs_phy->phy.io_priv; > > + if (is_imx7ulp_phy(mxs_phy)) { > + ret = mxs_phy_pll_enable(base, true); > + if (ret) > + return
Re: [PATCH 2/2] usb: xhci-mtk: Do not create shared_hcd if no USB 3.0 port available
Hi Nicolas, On Thu, 2019-05-02 at 12:56 +0800, Nicolas Boichat wrote: > When the controller only supports USB 2.0, do not even create the > USB 3.0 hcd/root hub. > > Signed-off-by: Nicolas Boichat > --- > drivers/usb/host/xhci-mtk.c | 44 +++-- > 1 file changed, 28 insertions(+), 16 deletions(-) > > diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c > index 026fe18972d3e5b..189f5dc614e6e05 100644 > --- a/drivers/usb/host/xhci-mtk.c > +++ b/drivers/usb/host/xhci-mtk.c > @@ -527,23 +527,28 @@ static int xhci_mtk_probe(struct platform_device *pdev) > xhci->imod_interval = 5000; > device_property_read_u32(dev, "imod-interval-ns", &xhci->imod_interval); > > - xhci->shared_hcd = usb_create_shared_hcd(driver, dev, > + /* Only create shared_hcd when USB3.0 port is available. */ > + if (xhci->usb3_rhub.num_ports > 0) { xhci->usb3_rhub.num_ports is not set until usb_add_hcd() is called. > + xhci->shared_hcd = usb_create_shared_hcd(driver, dev, > dev_name(dev), hcd); > - if (!xhci->shared_hcd) { > - ret = -ENOMEM; > - goto disable_device_wakeup; > + if (!xhci->shared_hcd) { > + ret = -ENOMEM; > + goto disable_device_wakeup; > + } > } > > ret = usb_add_hcd(hcd, irq, IRQF_SHARED); > if (ret) > goto put_usb3_hcd; > > - if (HCC_MAX_PSA(xhci->hcc_params) >= 4) > - xhci->shared_hcd->can_do_streams = 1; > + if (xhci->usb3_rhub.num_ports > 0) { > + if (HCC_MAX_PSA(xhci->hcc_params) >= 4) > + xhci->shared_hcd->can_do_streams = 1; > > - ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); > - if (ret) > - goto dealloc_usb2_hcd; > + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); > + if (ret) > + goto dealloc_usb2_hcd; > + } > > return 0; > > @@ -552,7 +557,8 @@ static int xhci_mtk_probe(struct platform_device *pdev) > > put_usb3_hcd: > xhci_mtk_sch_exit(mtk); > - usb_put_hcd(xhci->shared_hcd); > + if (xhci->shared_hcd) > + usb_put_hcd(xhci->shared_hcd); > > disable_device_wakeup: > device_init_wakeup(dev, false); > @@ -579,12 +585,14 @@ static int xhci_mtk_remove(struct platform_device *dev) > struct xhci_hcd *xhci = hcd_to_xhci(hcd); > struct usb_hcd *shared_hcd = xhci->shared_hcd; > > - usb_remove_hcd(shared_hcd); > + if (shared_hcd) > + usb_remove_hcd(shared_hcd); > xhci->shared_hcd = NULL; > device_init_wakeup(&dev->dev, false); > > usb_remove_hcd(hcd); > - usb_put_hcd(shared_hcd); > + if (shared_hcd) > + usb_put_hcd(shared_hcd); > usb_put_hcd(hcd); > xhci_mtk_sch_exit(mtk); > xhci_mtk_clks_disable(mtk); > @@ -611,8 +619,10 @@ static int __maybe_unused xhci_mtk_suspend(struct device > *dev) > xhci_dbg(xhci, "%s: stop port polling\n", __func__); > clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); > del_timer_sync(&hcd->rh_timer); > - clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); > - del_timer_sync(&xhci->shared_hcd->rh_timer); > + if (xhci->shared_hcd) { > + clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); > + del_timer_sync(&xhci->shared_hcd->rh_timer); > + } > > xhci_mtk_host_disable(mtk); > xhci_mtk_clks_disable(mtk); > @@ -631,8 +641,10 @@ static int __maybe_unused xhci_mtk_resume(struct device > *dev) > xhci_mtk_host_enable(mtk); > > xhci_dbg(xhci, "%s: restart port polling\n", __func__); > - set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); > - usb_hcd_poll_rh_status(xhci->shared_hcd); > + if (xhci->shared_hcd) { > + set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); > + usb_hcd_poll_rh_status(xhci->shared_hcd); > + } > set_bit(HCD_FLAG_POLL_RH, &hcd->flags); > usb_hcd_poll_rh_status(hcd); > return 0;
[PATCH 5/5] usb: mtu3: register a USB Role Switch for Dual-Role mode
Due to extcon is not allowed for new bindings, and the Dual-Role switch is supported by USB Role Switch, especially for Type-C drivers, so register a USB Role Switch to support the new way Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h | 5 drivers/usb/mtu3/mtu3_dr.c | 50 +--- drivers/usb/mtu3/mtu3_plat.c | 3 ++- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 87823ac0d120..8f9da03255b6 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -202,6 +202,9 @@ struct mtu3_gpd_ring { * @id_nb : notifier for iddig(idpin) detection * @id_work : work of iddig detection notifier * @id_event : event of iddig detecion notifier +* @role_sw : use USB Role Switch to support dual-role switch, can't use +* extcon at the same time, and extcon is deprecated. +* @role_sw_used : true when the USB Role Switch is used. * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not * @manual_drd_enabled: it's true when supports dual-role device by debugfs * to switch host/device modes depending on user input. @@ -215,6 +218,8 @@ struct otg_switch_mtk { struct notifier_block id_nb; struct work_struct id_work; unsigned long id_event; + struct usb_role_switch *role_sw; + bool role_sw_used; bool is_u3_drd; bool manual_drd_enabled; }; diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index ac60e9c8564e..b9272295fe2b 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "mtu3.h" #include "mtu3_dr.h" @@ -266,7 +267,7 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) * This is useful in special cases, such as uses TYPE-A receptacle but also * wants to support dual-role mode. */ -static void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) +static void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; @@ -308,9 +309,9 @@ static ssize_t ssusb_mode_write(struct file *file, return -EFAULT; if (!strncmp(buf, "host", 4) && !ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 1); + ssusb_mode_switch(ssusb, 1); } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { - ssusb_mode_manual_switch(ssusb, 0); + ssusb_mode_switch(ssusb, 0); } else { dev_err(ssusb->dev, "wrong or duplicated setting\n"); return -EINVAL; @@ -412,6 +413,46 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb, mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value); } +static int ssusb_role_sw_set(struct device *dev, enum usb_role role) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + bool to_host = false; + + if (role == USB_ROLE_HOST) + to_host = true; + + if (to_host ^ ssusb->is_host) + ssusb_mode_switch(ssusb, to_host); + + return 0; +} + +static enum usb_role ssusb_role_sw_get(struct device *dev) +{ + struct ssusb_mtk *ssusb = dev_get_drvdata(dev); + enum usb_role role; + + role = ssusb->is_host ? USB_ROLE_HOST : USB_ROLE_DEVICE; + + return role; +} + +static int ssusb_role_sw_register(struct otg_switch_mtk *otg_sx) +{ + struct usb_role_switch_desc role_sx_desc = { 0 }; + struct ssusb_mtk *ssusb = + container_of(otg_sx, struct ssusb_mtk, otg_switch); + + if (!otg_sx->role_sw_used) + return 0; + + role_sx_desc.set = ssusb_role_sw_set; + role_sx_desc.get = ssusb_role_sw_get; + otg_sx->role_sw = usb_role_switch_register(ssusb->dev, &role_sx_desc); + + return PTR_ERR_OR_ZERO(otg_sx->role_sw); +} + int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; @@ -421,6 +462,8 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) if (otg_sx->manual_drd_enabled) ssusb_debugfs_init(ssusb); + else if (otg_sx->role_sw_used) + ssusb_role_sw_register(otg_sx); else ssusb_extcon_register(otg_sx); @@ -436,4 +479,5 @@ void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) cancel_work_sync(&otg_sx->id_work); cancel_work_sync(&otg_sx->vbus_work); + usb_role_switch_unregister(otg_sx->role_sw); } diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index e086630e41a9..02c288a85989 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -313,8 +313,9 @@ static int get_ssusb_rscs(struct platform_devic
[PATCH 4/5] usb: roles: add USB Type-B connector driver
Due to the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated when use Type-B connector. This patch introduce a Type-B connector driver and try to replace the function provided by extcon-usb-gpio driver Signed-off-by: Chunfeng Yun --- drivers/usb/roles/Kconfig | 14 ++ drivers/usb/roles/Makefile | 1 + drivers/usb/roles/usb-b-connector.c | 285 3 files changed, 300 insertions(+) create mode 100644 drivers/usb/roles/usb-b-connector.c diff --git a/drivers/usb/roles/Kconfig b/drivers/usb/roles/Kconfig index e4194ac94510..e267132917c2 100644 --- a/drivers/usb/roles/Kconfig +++ b/drivers/usb/roles/Kconfig @@ -24,4 +24,18 @@ config USB_ROLES_INTEL_XHCI To compile the driver as a module, choose M here: the module will be called intel-xhci-usb-role-switch. +config USB_B_CONNECTOR + tristate "USB Type-B Connector" + depends on GPIOLIB + help + The driver supports USB role switch between host and device by GPIO + based USB cable detection, used typically if GPIO is used for USB ID + pin detection. And it's used to replace the function provided by + drivers/extcon/extcon-usb-gpio.c driver due to the requirement by + connector/usb-connector.txt + + Say Y here if your USB Type-B Connector supports Dual-Role mode. + To compile the driver as a module, choose M here: the module will + be called usb-b-connector.ko + endif # USB_ROLE_SWITCH diff --git a/drivers/usb/roles/Makefile b/drivers/usb/roles/Makefile index c02873206fc1..ff8be33253a4 100644 --- a/drivers/usb/roles/Makefile +++ b/drivers/usb/roles/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_USB_ROLE_SWITCH) += roles.o roles-y:= class.o +obj-$(CONFIG_USB_B_CONNECTOR) += usb-b-connector.o obj-$(CONFIG_USB_ROLES_INTEL_XHCI) += intel-xhci-usb-role-switch.o diff --git a/drivers/usb/roles/usb-b-connector.c b/drivers/usb/roles/usb-b-connector.c new file mode 100644 index ..debd0c6500cf --- /dev/null +++ b/drivers/usb/roles/usb-b-connector.c @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * USB Type-B Connector Driver + * + * Copyright (C) 2019 MediaTek Inc. + * + * Author: Chunfeng Yun + * + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USB_GPIO_DEB_MS20 /* ms */ +#define USB_GPIO_DEB_US((USB_GPIO_DEB_MS) * 1000) /* us */ + +#define USB_CONN_IRQF \ + (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT) + +struct usb_conn_info { + struct device *dev; + struct usb_role_switch *role_sw; + enum usb_role last_role; + struct regulator *vbus; + struct delayed_work dw_det; + unsigned long debounce_jiffies; + + struct gpio_desc *id_gpiod; + struct gpio_desc *vbus_gpiod; + int id_irq; + int vbus_irq; +}; + +/** + * "DEVICE" = VBUS and "HOST" = !ID, so we have: + * Both "DEVICE" and "HOST" can't be set as active at the same time + * so if "HOST" is active (i.e. ID is 0) we keep "DEVICE" inactive + * even if VBUS is on. + * + * Role | ID | VBUS + * + * [1] DEVICE| H | H + * [2] NONE | H | L + * [3] HOST | L | H + * [4] HOST | L | L + * + * In case we have only one of these signals: + * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1 + * - ID only - we want to distinguish between [1] and [4], so VBUS = ID + */ +static void usb_conn_detect_cable(struct work_struct *work) +{ + struct usb_conn_info *info; + enum usb_role role; + int id, vbus, ret; + + info = container_of(to_delayed_work(work), + struct usb_conn_info, dw_det); + + /* check ID and VBUS */ + id = info->id_gpiod ? + gpiod_get_value_cansleep(info->id_gpiod) : 1; + vbus = info->vbus_gpiod ? + gpiod_get_value_cansleep(info->vbus_gpiod) : id; + + if (!id) + role = USB_ROLE_HOST; + else if (vbus) + role = USB_ROLE_DEVICE; + else + role = USB_ROLE_NONE; + + dev_dbg(info->dev, "role %d/%d, gpios: id %d, vbus %d\n", + info->last_role, role, id, vbus); + + if (info->last_role == role) { + dev_warn(info->dev, "repeated role: %d\n", role); + return; + } + + if (info->last_role == USB_ROLE_HOST) + regulator_disable(info->vbus); + + ret = usb_role_switch_set_role(info->role_sw, role); + if
[PATCH 3/5] usb: roles: add API to get usb_role_switch by node
Add usb_role_switch_get_by_node() to make easier to get usb_role_switch by node which register it. It's useful when there is not device_connection registered between two drivers and only knows the node which register usb_role_switch. Signed-off-by: Chunfeng Yun --- drivers/usb/roles/class.c | 30 ++ include/linux/usb/role.h | 1 + 2 files changed, 31 insertions(+) diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 99116af07f1d..284b19856dc4 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -11,6 +11,7 @@ #include #include #include +#include #include static struct class *role_class; @@ -121,6 +122,35 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev) } EXPORT_SYMBOL_GPL(usb_role_switch_get); +static int __switch_match_node(struct device *dev, const void *node) +{ + return dev->parent->of_node == (const struct device_node *)node; +} + +/** + * usb_role_switch_get_by_node - Find USB role switch by it's parent node + * @node: The node that register USB role switch + * + * Finds and returns role switch registered by @node. The reference count + * for the found switch is incremented. + */ +struct usb_role_switch *usb_role_switch_get_by_node(struct device_node *node) +{ + struct usb_role_switch *sw; + struct device *dev; + + dev = class_find_device(role_class, NULL, node, + __switch_match_node); + if (!dev) + return ERR_PTR(-EPROBE_DEFER); + + sw = to_role_switch(dev); + WARN_ON(!try_module_get(sw->dev.parent->driver->owner)); + + return sw; +} +EXPORT_SYMBOL_GPL(usb_role_switch_get_by_node); + /** * usb_role_switch_put - Release handle to a switch * @sw: USB Role Switch diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h index edc51be4a77c..056498b83dee 100644 --- a/include/linux/usb/role.h +++ b/include/linux/usb/role.h @@ -42,6 +42,7 @@ struct usb_role_switch_desc { int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); +struct usb_role_switch *usb_role_switch_get_by_node(struct device_node *node); struct usb_role_switch *usb_role_switch_get(struct device *dev); void usb_role_switch_put(struct usb_role_switch *sw); -- 2.20.1
[PATCH 2/5] dt-bindings: usb: mtu3: add properties about USB Role Switch
Now the USB Role Switch is supported, so add properties about it Signed-off-by: Chunfeng Yun --- .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt index 3382b5cb471d..97239913a7bd 100644 --- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt @@ -27,7 +27,9 @@ Optional properties: - ranges : allows valid 1:1 translation between child's address space and parent's address space - extcon : external connector for vbus and idpin changes detection, needed - when supports dual-role mode. + when supports dual-role mode; it's consiedered valid for compatibility + reasons, and not allowed for new bindings, use the property + usb-role-switch instead. - vbus-supply : reference to the VBUS regulator, needed when supports dual-role mode. - pinctrl-names : a pinctrl state named "default" is optional, and need be @@ -36,7 +38,8 @@ Optional properties: is not set. - pinctrl-0 : pin control group See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt - + - usb-role-switch : use USB Role Switch to support dual-role siwtch, but + not extcon - maximum-speed : valid arguments are "super-speed", "high-speed" and "full-speed"; refer to usb/generic.txt - enable-manual-drd : supports manual dual-role switch via debugfs; usually @@ -61,6 +64,9 @@ The xhci should be added as subnode to mtu3 as shown in the following example if host mode is enabled. The DT binding details of xhci can be found in: Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +The connector would be added as subnode if receptacle is Micro, see +connector/usb-connector.txt + Example: ssusb: usb@11271000 { compatible = "mediatek,mt8173-mtu3"; -- 2.20.1
[PATCH 0/5] add USB Type-B connector driver
Because the USB Connector is introduced and the requirement of usb-connector.txt binding, the old way using extcon to support USB Dual-Role switch is now deprecated, meanwhile there is no available common driver when use Type-B connector. This patch series introduce a Type-B connector driver and try to replace the function provided by extcon-usb-gpio driver. The main purpose of the patches is also to solve the Type-B connector problem encountered in [1]. [1]: https://patchwork.kernel.org/patch/10819377/ Chunfeng Yun (5): dt-bindings: connector: add optional properties for Type-B dt-bindings: usb: mtu3: add properties about USB Role Switch usb: roles: add API to get usb_role_switch by node usb: roles: add USB Type-B connector driver usb: mtu3: register a USB Role Switch for Dual-Role mode .../bindings/connector/usb-connector.txt | 10 + .../devicetree/bindings/usb/mediatek,mtu3.txt | 10 +- drivers/usb/mtu3/mtu3.h | 5 + drivers/usb/mtu3/mtu3_dr.c| 50 ++- drivers/usb/mtu3/mtu3_plat.c | 3 +- drivers/usb/roles/Kconfig | 14 + drivers/usb/roles/Makefile| 1 + drivers/usb/roles/class.c | 30 ++ drivers/usb/roles/usb-b-connector.c | 285 ++ include/linux/usb/role.h | 1 + 10 files changed, 403 insertions(+), 6 deletions(-) create mode 100644 drivers/usb/roles/usb-b-connector.c -- 2.20.1
[PATCH 1/5] dt-bindings: connector: add optional properties for Type-B
Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for usb-b-connector Signed-off-by: Chunfeng Yun --- .../devicetree/bindings/connector/usb-connector.txt| 10 ++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt index a9a2f2fc44f2..7a07b0f4f973 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.txt +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt @@ -17,6 +17,16 @@ Optional properties: - self-powered: Set this property if the usb device that has its own power source. +Optional properties for usb-b-connector: +- id-gpios: gpio for USB ID pin. +- vbus-gpios: gpio for USB VBUS pin. + see gpio/gpio.txt. +- vbus-supply: reference to the VBUS regulator, needed when supports + dual-role mode. +- pinctrl-names : a pinctrl state named "default" is optional +- pinctrl-0 : pin control group + see pinctrl/pinctrl-bindings.txt + Optional properties for usb-c-connector: - power-role: should be one of "source", "sink" or "dual"(DRP) if typec connector has power support. -- 2.20.1
Re: [PATCH v2 8/8] usb: dwc3: Add Amlogic G12A DWC3 glue
On Thu, 2019-03-07 at 10:45 +0100, Neil Armstrong wrote: > On 07/03/2019 03:02, Chunfeng Yun wrote: > > Hi, > > On Mon, 2019-03-04 at 11:38 +0100, Neil Armstrong wrote: > >> Adds support for Amlogic G12A USB Control Glue HW. > >> > >> The Amlogic G12A SoC Family embeds 2 USB Controllers : > >> - a DWC3 IP configured as Host for USB2 and USB3 > >> - a DWC2 IP configured as Peripheral USB2 Only > >> > >> A glue connects these both controllers to 2 USB2 PHYs, and optionnally > >> to an USB3+PCIE Combo PHY shared with the PCIE controller. > >> > >> The Glue configures the UTMI 8bit interfaces for the USB2 PHYs, including > >> routing of the OTG PHY between the DWC3 and DWC2 controllers, and > >> setups the on-chip OTG mode selection for this PHY. > >> > >> This drivers supports the on-probe setup of the OTG mode, and manually > >> via a debugfs interface. The IRQ mode change detect is yet to be added > >> in a future patchset, mainly due to lack of hardware to validate on. > >> > >> Signed-off-by: Neil Armstrong > >> --- > >> drivers/usb/dwc3/Kconfig | 10 + > >> drivers/usb/dwc3/Makefile | 1 + > >> drivers/usb/dwc3/dwc3-meson-g12a.c | 601 + > >> 3 files changed, 612 insertions(+) > >> create mode 100644 drivers/usb/dwc3/dwc3-meson-g12a.c > >> > >> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig > >> index 1a0404fda596..21ce7368d325 100644 > >> --- a/drivers/usb/dwc3/Kconfig > >> +++ b/drivers/usb/dwc3/Kconfig > >> @@ -93,6 +93,16 @@ config USB_DWC3_KEYSTONE > >> Support of USB2/3 functionality in TI Keystone2 platforms. > >> Say 'Y' or 'M' here if you have one such device > >> > >> +config USB_DWC3_MESON_G12A > >> + tristate "Amlogic Meson G12A Platforms" > >> + depends on OF && COMMON_CLK > >> + depends on ARCH_MESON || COMPILE_TEST > >> + default USB_DWC3 > >> + select USB_ROLE_SWITCH > >> + help > >> + Support USB2/3 functionality in Amlogic G12A platforms. > >> + Say 'Y' or 'M' if you have one such device. > >> + > >> config USB_DWC3_OF_SIMPLE > >> tristate "Generic OF Simple Glue Layer" > >> depends on OF && COMMON_CLK > >> diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile > >> index 6e3ef6144e5d..ae86da0dc5bd 100644 > >> --- a/drivers/usb/dwc3/Makefile > >> +++ b/drivers/usb/dwc3/Makefile > >> @@ -47,6 +47,7 @@ obj-$(CONFIG_USB_DWC3_EXYNOS)+= dwc3-exynos.o > >> obj-$(CONFIG_USB_DWC3_PCI)+= dwc3-pci.o > >> obj-$(CONFIG_USB_DWC3_HAPS) += dwc3-haps.o > >> obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o > >> +obj-$(CONFIG_USB_DWC3_MESON_G12A) += dwc3-meson-g12a.o > >> obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o > >> obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o > >> obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o > >> diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c > >> b/drivers/usb/dwc3/dwc3-meson-g12a.c > >> new file mode 100644 > >> index ..75942614a034 > >> --- /dev/null > >> +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c > >> @@ -0,0 +1,601 @@ > >> +// SPDX-License-Identifier: GPL-2.0 > >> +/* > >> + * USB Glue for Amlogic G12A SoCs > >> + * > >> + * Copyright (c) 2019 BayLibre, SAS > >> + * Author: Neil Armstrong > >> + */ > >> + > >> +/* > >> + * The USB is organized with a glue around the DWC3 Controller IP as : > >> + * - Control registers for each USB2 Ports > >> + * - Control registers for the USB PHY layer > >> + * - SuperSpeed PHY can be enabled only if port is used > >> + * > >> + * TOFIX: > >> + * - Add dynamic OTG switching with ID change interrupt > >> + */ > >> + > > [...] > >> + > >> +static int dwc3_meson_g12a_probe(struct platform_device *pdev) > >> +{ > >> + struct dwc3_meson_g12a *priv; > >> + struct device *dev = &pdev->dev; > >> + struct device_node *np = dev->of_node; > >> + void __iomem *base; > >> + struct resource *res; > >> + enum phy_mode otg_id; > >> + int ret, i; > >>
Re: [PATCH v2 8/8] usb: dwc3: Add Amlogic G12A DWC3 glue
Hi, On Mon, 2019-03-04 at 11:38 +0100, Neil Armstrong wrote: > Adds support for Amlogic G12A USB Control Glue HW. > > The Amlogic G12A SoC Family embeds 2 USB Controllers : > - a DWC3 IP configured as Host for USB2 and USB3 > - a DWC2 IP configured as Peripheral USB2 Only > > A glue connects these both controllers to 2 USB2 PHYs, and optionnally > to an USB3+PCIE Combo PHY shared with the PCIE controller. > > The Glue configures the UTMI 8bit interfaces for the USB2 PHYs, including > routing of the OTG PHY between the DWC3 and DWC2 controllers, and > setups the on-chip OTG mode selection for this PHY. > > This drivers supports the on-probe setup of the OTG mode, and manually > via a debugfs interface. The IRQ mode change detect is yet to be added > in a future patchset, mainly due to lack of hardware to validate on. > > Signed-off-by: Neil Armstrong > --- > drivers/usb/dwc3/Kconfig | 10 + > drivers/usb/dwc3/Makefile | 1 + > drivers/usb/dwc3/dwc3-meson-g12a.c | 601 + > 3 files changed, 612 insertions(+) > create mode 100644 drivers/usb/dwc3/dwc3-meson-g12a.c > > diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig > index 1a0404fda596..21ce7368d325 100644 > --- a/drivers/usb/dwc3/Kconfig > +++ b/drivers/usb/dwc3/Kconfig > @@ -93,6 +93,16 @@ config USB_DWC3_KEYSTONE > Support of USB2/3 functionality in TI Keystone2 platforms. > Say 'Y' or 'M' here if you have one such device > > +config USB_DWC3_MESON_G12A > + tristate "Amlogic Meson G12A Platforms" > + depends on OF && COMMON_CLK > + depends on ARCH_MESON || COMPILE_TEST > + default USB_DWC3 > + select USB_ROLE_SWITCH > + help > + Support USB2/3 functionality in Amlogic G12A platforms. > + Say 'Y' or 'M' if you have one such device. > + > config USB_DWC3_OF_SIMPLE > tristate "Generic OF Simple Glue Layer" > depends on OF && COMMON_CLK > diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile > index 6e3ef6144e5d..ae86da0dc5bd 100644 > --- a/drivers/usb/dwc3/Makefile > +++ b/drivers/usb/dwc3/Makefile > @@ -47,6 +47,7 @@ obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o > obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o > obj-$(CONFIG_USB_DWC3_HAPS) += dwc3-haps.o > obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o > +obj-$(CONFIG_USB_DWC3_MESON_G12A)+= dwc3-meson-g12a.o > obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o > obj-$(CONFIG_USB_DWC3_ST)+= dwc3-st.o > obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o > diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c > b/drivers/usb/dwc3/dwc3-meson-g12a.c > new file mode 100644 > index ..75942614a034 > --- /dev/null > +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c > @@ -0,0 +1,601 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * USB Glue for Amlogic G12A SoCs > + * > + * Copyright (c) 2019 BayLibre, SAS > + * Author: Neil Armstrong > + */ > + > +/* > + * The USB is organized with a glue around the DWC3 Controller IP as : > + * - Control registers for each USB2 Ports > + * - Control registers for the USB PHY layer > + * - SuperSpeed PHY can be enabled only if port is used > + * > + * TOFIX: > + * - Add dynamic OTG switching with ID change interrupt > + */ > + [...] > + > +static int dwc3_meson_g12a_probe(struct platform_device *pdev) > +{ > + struct dwc3_meson_g12a *priv; > + struct device *dev = &pdev->dev; > + struct device_node *np = dev->of_node; > + void __iomem *base; > + struct resource *res; > + enum phy_mode otg_id; > + int ret, i; > + > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + base = devm_ioremap_resource(dev, res); > + if (IS_ERR(base)) > + return PTR_ERR(base); > + > + priv->regmap = devm_regmap_init_mmio(dev, base, > + &phy_meson_g12a_usb3_regmap_conf); > + if (IS_ERR(priv->regmap)) > + return PTR_ERR(priv->regmap); > + > + priv->vbus = devm_regulator_get_optional(dev, "vbus"); > + if (IS_ERR(priv->vbus)) { > + if (PTR_ERR(priv->vbus) == -EPROBE_DEFER) > + return PTR_ERR(priv->vbus); > + priv->vbus = NULL; > + } > + > + priv->clk = devm_clk_get(dev, NULL); > + if (IS_ERR(priv->clk)) > + return PTR_ERR(priv->clk); > + > + ret = clk_prepare_enable(priv->clk); > + if (ret) > + return ret; > + > + platform_set_drvdata(pdev, priv); > + priv->dev = dev; > + > + priv->reset = devm_reset_control_get(dev, NULL); > + if (IS_ERR(priv->reset)) { > + ret = PTR_ERR(priv->reset); > + dev_err(dev, "failed to get device reset, err=%d\n", ret); > + return ret; > + } >
[PATCH 01/11] usb: mtu3: check return value of devm_extcon_register_notifier()
Check the return value of devm_extcon_register_notifier() and add error handling. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3_dr.c | 13 + drivers/usb/mtu3/mtu3_plat.c | 8 +++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index ac60e9c8564e..61694c40e101 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -238,14 +238,18 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) otg_sx->vbus_nb.notifier_call = ssusb_vbus_notifier; ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB, &otg_sx->vbus_nb); - if (ret < 0) + if (ret < 0) { dev_err(ssusb->dev, "failed to register notifier for USB\n"); + return ret; + } otg_sx->id_nb.notifier_call = ssusb_id_notifier; ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB_HOST, &otg_sx->id_nb); - if (ret < 0) + if (ret < 0) { dev_err(ssusb->dev, "failed to register notifier for USB-HOST\n"); + return ret; + } dev_dbg(ssusb->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n", extcon_get_state(edev, EXTCON_USB), @@ -415,6 +419,7 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb, int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) { struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + int ret = 0; INIT_WORK(&otg_sx->id_work, ssusb_id_work); INIT_WORK(&otg_sx->vbus_work, ssusb_vbus_work); @@ -422,9 +427,9 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) if (otg_sx->manual_drd_enabled) ssusb_debugfs_init(ssusb); else - ssusb_extcon_register(otg_sx); + ret = ssusb_extcon_register(otg_sx); - return 0; + return ret; } void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index e086630e41a9..dee31d5eefe1 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -401,7 +401,11 @@ static int mtu3_probe(struct platform_device *pdev) goto gadget_exit; } - ssusb_otg_switch_init(ssusb); + ret = ssusb_otg_switch_init(ssusb); + if (ret) { + dev_err(dev, "failed to initialize switch\n"); + goto host_exit; + } break; default: dev_err(dev, "unsupported mode: %d\n", ssusb->dr_mode); @@ -411,6 +415,8 @@ static int mtu3_probe(struct platform_device *pdev) return 0; +host_exit: + ssusb_host_exit(ssusb); gadget_exit: ssusb_gadget_exit(ssusb); comm_exit: -- 2.20.1
[PATCH 04/11] usb: mtu3: rebuild the code of getting vbus regulator
Remove local variable @vbus and use @dev instead of @pdev->dev Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3_plat.c | 8 +++- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 3a4a80f15957..a326b1d6006a 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -228,7 +228,6 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) struct device_node *node = pdev->dev.of_node; struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; struct device *dev = &pdev->dev; - struct regulator *vbus; struct resource *res; int i; int ret; @@ -299,12 +298,11 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) of_property_read_u32(node, "mediatek,u3p-dis-msk", &ssusb->u3p_dis_msk); - vbus = devm_regulator_get(&pdev->dev, "vbus"); - if (IS_ERR(vbus)) { + otg_sx->vbus = devm_regulator_get(dev, "vbus"); + if (IS_ERR(otg_sx->vbus)) { dev_err(dev, "failed to get vbus\n"); - return PTR_ERR(vbus); + return PTR_ERR(otg_sx->vbus); } - otg_sx->vbus = vbus; if (ssusb->dr_mode == USB_DR_MODE_HOST) goto out; -- 2.20.1
[PATCH 00/11] add debugfs consumers, tracepoints and rebuild QMU
In order to help debug, this series add more debugfs consumers, introduce a few initial tracepoints; And support new features introduced by USB3 Gen2 ISOC: 1. TXCSR/RXCSR registers are adjusted to support greater MULT and MAX_PKT 2. QMU format is also improved last, some small problems are fixed. Chunfeng Yun (11): usb: mtu3: check return value of devm_extcon_register_notifier() usb: mtu3: print useful information also for device and host modes usb: mtu3: remove unnecessary local variable @req usb: mtu3: rebuild the code of getting vbus regulator usb: mtu3: fix transfer error of USB3 Gen2 isoc usb: mtu3: rebuild qmu_gpd struct to prepare to support new QMU format usb: mtu3: supports new QMU format usb: mtu3: add debugfs interface files usb: mtu3: move vbus and mode debugfs interfaces into mtu3_debugfs.c usb: mtu3: add tracepoints to help debug usb: mtu3: add a function to switch mailbox state to string drivers/usb/mtu3/Makefile | 11 + drivers/usb/mtu3/mtu3.h| 57 ++- drivers/usb/mtu3/mtu3_core.c | 27 +- drivers/usb/mtu3/mtu3_debug.h | 50 +++ drivers/usb/mtu3/mtu3_debugfs.c| 539 + drivers/usb/mtu3/mtu3_dr.c | 156 ++--- drivers/usb/mtu3/mtu3_dr.h | 4 + drivers/usb/mtu3/mtu3_gadget.c | 20 +- drivers/usb/mtu3/mtu3_gadget_ep0.c | 4 + drivers/usb/mtu3/mtu3_hw_regs.h| 48 ++- drivers/usb/mtu3/mtu3_plat.c | 28 +- drivers/usb/mtu3/mtu3_qmu.c| 118 --- drivers/usb/mtu3/mtu3_qmu.h| 1 + drivers/usb/mtu3/mtu3_trace.c | 23 ++ drivers/usb/mtu3/mtu3_trace.h | 279 +++ 15 files changed, 1146 insertions(+), 219 deletions(-) create mode 100644 drivers/usb/mtu3/mtu3_debug.h create mode 100644 drivers/usb/mtu3/mtu3_debugfs.c create mode 100644 drivers/usb/mtu3/mtu3_trace.c create mode 100644 drivers/usb/mtu3/mtu3_trace.h -- 2.20.1
[PATCH 03/11] usb: mtu3: remove unnecessary local variable @req
The local variable @req is unnecessary in qmu_tx_zlp_error_handler, so remove it. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3_qmu.c | 7 ++- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c index 09f19f70fe8f..f4b5431264c1 100644 --- a/drivers/usb/mtu3/mtu3_qmu.c +++ b/drivers/usb/mtu3/mtu3_qmu.c @@ -382,16 +382,13 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) struct mtu3_gpd_ring *ring = &mep->gpd_ring; void __iomem *mbase = mtu->mac_base; struct qmu_gpd *gpd_current = NULL; - struct usb_request *req = NULL; struct mtu3_request *mreq; dma_addr_t cur_gpd_dma; u32 txcsr = 0; int ret; mreq = next_request(mep); - if (mreq && mreq->request.length == 0) - req = &mreq->request; - else + if (mreq && mreq->request.length != 0) return; cur_gpd_dma = read_txq_cur_addr(mbase, epnum); @@ -402,7 +399,7 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) return; } - dev_dbg(mtu->dev, "%s send ZLP for req=%p\n", __func__, req); + dev_dbg(mtu->dev, "%s send ZLP for req=%p\n", __func__, mreq); mtu3_clrbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_DMAREQEN); -- 2.20.1
[PATCH 05/11] usb: mtu3: fix transfer error of USB3 Gen2 isoc
To support USB3 Gen2 ISOC, the registers of TXCSR1 and RXCSR1 are adjusted to support greater maxpkt and mult value, this patch fix this issue Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h | 11 ++ drivers/usb/mtu3/mtu3_core.c| 14 +++-- drivers/usb/mtu3/mtu3_hw_regs.h | 36 + 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 87823ac0d120..e3143f81b6a0 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -62,6 +62,15 @@ struct mtu3_request; #define MTU3_U3_IP_SLOT_DEFAULT 2 #define MTU3_U2_IP_SLOT_DEFAULT 1 +/** + * IP TRUNK version + * from 0x1003 version, USB3 Gen2 is supported, two changes affect driver: + * 1. MAXPKT and MULTI bits layout of TXCSR1 and RXCSR1 are adjusted, + *but not backward compatible + * 2. QMU extend buffer length supported + */ +#define MTU3_TRUNK_VERS_1003 0x1003 + /** * Normally the device works on HS or SS, to simplify fifo management, * devide fifo into some 512B parts, use bitmap to manage it; And @@ -316,6 +325,7 @@ static inline struct ssusb_mtk *dev_to_ssusb(struct device *dev) * @may_wakeup: means device's remote wakeup is enabled * @is_self_powered: is reported in device status and the config descriptor * @delayed_status: true when function drivers ask for delayed status + * @gen2cp: compatible with USB3 Gen2 IP * @ep0_req: dummy request used while handling standard USB requests * for GET_STATUS and SET_SEL * @setup_buf: ep0 response buffer for GET_STATUS and SET_SEL requests @@ -356,6 +366,7 @@ struct mtu3 { unsigned u2_enable:1; unsigned is_u3_ip:1; unsigned delayed_status:1; + unsigned gen2cp:1; u8 address; u8 test_mode_nr; diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index 4fee200795a5..ef27c2052ad6 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -299,6 +299,7 @@ int mtu3_config_ep(struct mtu3 *mtu, struct mtu3_ep *mep, int interval, int burst, int mult) { void __iomem *mbase = mtu->mac_base; + bool gen2cp = mtu->gen2cp; int epnum = mep->epnum; u32 csr0, csr1, csr2; int fifo_sgsz, fifo_addr; @@ -319,7 +320,7 @@ int mtu3_config_ep(struct mtu3 *mtu, struct mtu3_ep *mep, num_pkts = (burst + 1) * (mult + 1) - 1; csr1 = TX_SS_BURST(burst) | TX_SLOT(mep->slot); - csr1 |= TX_MAX_PKT(num_pkts) | TX_MULT(mult); + csr1 |= TX_MAX_PKT(gen2cp, num_pkts) | TX_MULT(gen2cp, mult); csr2 = TX_FIFOADDR(fifo_addr >> 4); csr2 |= TX_FIFOSEGSIZE(fifo_sgsz); @@ -355,7 +356,7 @@ int mtu3_config_ep(struct mtu3 *mtu, struct mtu3_ep *mep, num_pkts = (burst + 1) * (mult + 1) - 1; csr1 = RX_SS_BURST(burst) | RX_SLOT(mep->slot); - csr1 |= RX_MAX_PKT(num_pkts) | RX_MULT(mult); + csr1 |= RX_MAX_PKT(gen2cp, num_pkts) | RX_MULT(gen2cp, mult); csr2 = RX_FIFOADDR(fifo_addr >> 4); csr2 |= RX_FIFOSEGSIZE(fifo_sgsz); @@ -749,13 +750,14 @@ static irqreturn_t mtu3_irq(int irq, void *data) static int mtu3_hw_init(struct mtu3 *mtu) { - u32 cap_dev; + u32 value; int ret; - mtu->hw_version = mtu3_readl(mtu->ippc_base, U3D_SSUSB_HW_ID); + value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_TRUNK_VERS); + mtu->hw_version = IP_TRUNK_VERS(value); - cap_dev = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_DEV_CAP); - mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(cap_dev); + value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_DEV_CAP); + mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(value); dev_info(mtu->dev, "IP version 0x%x(%s IP)\n", mtu->hw_version, mtu->is_u3_ip ? "U3" : "U2"); diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h index 1d65b7476f23..fae3b8de1092 100644 --- a/drivers/usb/mtu3/mtu3_hw_regs.h +++ b/drivers/usb/mtu3/mtu3_hw_regs.h @@ -133,11 +133,23 @@ #define TX_W1C_BITS(~(TX_SENTSTALL)) /* U3D_TX1CSR1 */ -#define TX_MULT(x) (((x) & 0x3) << 22) -#define TX_MAX_PKT(x) (((x) & 0x3f) << 16) +#define TX_MAX_PKT_G2(x) (((x) & 0x7f) << 24) +#define TX_MULT_G2(x) (((x) & 0x7) << 21) +#define TX_MULT_OG(x) (((x) & 0x3) << 22) +#define TX_MAX_PKT_OG(x) (((x) & 0x3f) << 16) #define TX_SLOT(x) (((x) & 0x3f) << 8) #define TX_TYPE(x) (((x) & 0x3) << 4) #define TX_SS_BURST(x) (((x) & 0xf) << 0) +#define TX_MULT(g2c, x)\ +({ \ +
[PATCH 11/11] usb: mtu3: add a function to switch mailbox state to string
By introducing mailbox_state_string(), allow to make debug log more readable Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3_dr.c | 20 ++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 82913120622b..5fcb71af875a 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -21,6 +21,22 @@ enum mtu3_vbus_id_state { MTU3_VBUS_VALID, }; +static char *mailbox_state_string(enum mtu3_vbus_id_state state) +{ + switch (state) { + case MTU3_ID_FLOAT: + return "ID_FLOAT"; + case MTU3_ID_GROUND: + return "ID_GROUND"; + case MTU3_VBUS_OFF: + return "VBUS_OFF"; + case MTU3_VBUS_VALID: + return "VBUS_VALID"; + default: + return "UNKNOWN"; + } +} + static void toggle_opstate(struct ssusb_mtk *ssusb) { if (!ssusb->otg_switch.is_u3_drd) { @@ -140,8 +156,8 @@ static void ssusb_set_mailbox(struct otg_switch_mtk *otg_sx, container_of(otg_sx, struct ssusb_mtk, otg_switch); struct mtu3 *mtu = ssusb->u3d; - dev_dbg(ssusb->dev, "mailbox state(%d)\n", status); - mtu3_dbg_trace(ssusb->dev, "mailbox %d", status); + dev_dbg(ssusb->dev, "mailbox %s\n", mailbox_state_string(status)); + mtu3_dbg_trace(ssusb->dev, "mailbox %s", mailbox_state_string(status)); switch (status) { case MTU3_ID_GROUND: -- 2.20.1
[PATCH 06/11] usb: mtu3: rebuild qmu_gpd struct to prepare to support new QMU format
To support USB3 Gen2 ISOC, the data buffer length need be extended, it's hard to make the current qmu_gpd struct compatible, so here rebuild qmu_gpd struct and make easy to support new QMU format Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h | 45 +++-- drivers/usb/mtu3/mtu3_qmu.c | 56 + 2 files changed, 42 insertions(+), 59 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index e3143f81b6a0..4dda7ed6e24e 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -144,45 +144,32 @@ struct mtu3_fifo_info { * The format of TX GPD is a little different from RX one. * And the size of GPD is 16 bytes. * - * @flag: + * @dw0_info: * bit0: Hardware Own (HWO) * bit1: Buffer Descriptor Present (BDP), always 0, BD is not supported * bit2: Bypass (BPS), 1: HW skips this GPD if HWO = 1 * bit7: Interrupt On Completion (IOC) - * @chksum: This is used to validate the contents of this GPD; - * If TXQ_CS_EN / RXQ_CS_EN bit is set, an interrupt is issued - * when checksum validation fails; - * Checksum value is calculated over the 16 bytes of the GPD by default; - * @data_buf_len (RX ONLY): This value indicates the length of - * the assigned data buffer - * @tx_ext_addr (TX ONLY): [3:0] are 4 extension bits of @buffer, - * [7:4] are 4 extension bits of @next_gpd + * bit[31:16]: allow data buffer length (RX ONLY), + * the buffer length of the data to receive + * bit[23:16]: extension address (TX ONLY), + * lower 4 bits are extension bits of @buffer, + * upper 4 bits are extension bits of @next_gpd * @next_gpd: Physical address of the next GPD * @buffer: Physical address of the data buffer - * @buf_len: - * (TX): This value indicates the length of the assigned data buffer - * (RX): The total length of data received - * @ext_len: reserved - * @rx_ext_addr(RX ONLY): [3:0] are 4 extension bits of @buffer, - * [7:4] are 4 extension bits of @next_gpd - * @ext_flag: - * bit5 (TX ONLY): Zero Length Packet (ZLP), + * @dw3_info: + * bit[15:0]: data buffer length, + * (TX): the buffer length of the data to transmit + * (RX): The total length of data received + * bit[23:16]: extension address (RX ONLY), + * lower 4 bits are extension bits of @buffer, + * upper 4 bits are extension bits of @next_gpd + * bit29: Zero Length Packet (ZLP) (TX ONLY) */ struct qmu_gpd { - __u8 flag; - __u8 chksum; - union { - __le16 data_buf_len; - __le16 tx_ext_addr; - }; + __le32 dw0_info; __le32 next_gpd; __le32 buffer; - __le16 buf_len; - union { - __u8 ext_len; - __u8 rx_ext_addr; - }; - __u8 ext_flag; + __le32 dw3_info; } __packed; /** diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c index f4b5431264c1..7a1919fc9f9e 100644 --- a/drivers/usb/mtu3/mtu3_qmu.c +++ b/drivers/usb/mtu3/mtu3_qmu.c @@ -29,10 +29,13 @@ #define GPD_FLAGS_BDP BIT(1) #define GPD_FLAGS_BPS BIT(2) #define GPD_FLAGS_IOC BIT(7) +#define GET_GPD_HWO(gpd) (le32_to_cpu((gpd)->dw0_info) & GPD_FLAGS_HWO) -#define GPD_EXT_FLAG_ZLP BIT(5) -#define GPD_EXT_NGP(x) (((x) & 0xf) << 4) -#define GPD_EXT_BUF(x) (((x) & 0xf) << 0) +#define GPD_RX_BUF_LEN(x) (((x) & 0x) << 16) +#define GPD_DATA_LEN(x)((x) & 0x) +#define GPD_EXT_FLAG_ZLP BIT(29) +#define GPD_EXT_NGP(x) (((x) & 0xf) << 20) +#define GPD_EXT_BUF(x) (((x) & 0xf) << 16) #define HILO_GEN64(hi, lo) (((u64)(hi) << 32) + (lo)) #define HILO_DMA(hi, lo) \ @@ -125,7 +128,7 @@ static void reset_gpd_list(struct mtu3_ep *mep) struct qmu_gpd *gpd = ring->start; if (gpd) { - gpd->flag &= ~GPD_FLAGS_HWO; + gpd->dw0_info &= cpu_to_le32(~GPD_FLAGS_HWO); gpd_ring_init(ring, gpd); } } @@ -215,15 +218,12 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) struct qmu_gpd *gpd = ring->enqueue; struct usb_request *req = &mreq->request; dma_addr_t enq_dma; - u16 ext_addr; - - /* set all fields to zero as default value */ - memset(gpd, 0, sizeof(*gpd)); + u32 ext_addr; + gpd->dw0_info = 0; /* SW own it */ gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma)); - gpd->buf_len = cpu_to_le16(req->length); - gpd->flag |= GPD_FLAGS_IOC; + gpd->dw3_info = cpu_to_le32(GPD_DATA_LEN(req->length)); /* get the next GPD */ enq = advance_enq_gpd(ring);
[PATCH 10/11] usb: mtu3: add tracepoints to help debug
This patch implements a few initial tracepoints for the mtu3 driver. More traces can be added as necessary in order to ease the task of debugging. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/Makefile | 7 + drivers/usb/mtu3/mtu3_core.c | 5 + drivers/usb/mtu3/mtu3_debug.h | 8 + drivers/usb/mtu3/mtu3_dr.c | 1 + drivers/usb/mtu3/mtu3_gadget.c | 14 +- drivers/usb/mtu3/mtu3_gadget_ep0.c | 4 + drivers/usb/mtu3/mtu3_qmu.c| 7 + drivers/usb/mtu3/mtu3_trace.c | 23 +++ drivers/usb/mtu3/mtu3_trace.h | 279 + 9 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/mtu3/mtu3_trace.c create mode 100644 drivers/usb/mtu3/mtu3_trace.h diff --git a/drivers/usb/mtu3/Makefile b/drivers/usb/mtu3/Makefile index 7c1826bbcebb..3bf8cbcc1add 100644 --- a/drivers/usb/mtu3/Makefile +++ b/drivers/usb/mtu3/Makefile @@ -2,10 +2,17 @@ ccflags-$(CONFIG_USB_MTU3_DEBUG) += -DDEBUG +# define_trace.h needs to know how to find our header +CFLAGS_mtu3_trace.o:= -I$(src) + obj-$(CONFIG_USB_MTU3) += mtu3.o mtu3-y := mtu3_plat.o +ifneq ($(CONFIG_TRACING),) + mtu3-y += mtu3_trace.o +endif + ifneq ($(filter y,$(CONFIG_USB_MTU3_HOST) $(CONFIG_USB_MTU3_DUAL_ROLE)),) mtu3-y += mtu3_host.o endif diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index f106fe81ae10..f8bd1d57e795 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -17,6 +17,7 @@ #include "mtu3.h" #include "mtu3_debug.h" +#include "mtu3_trace.h" static int ep_fifo_alloc(struct mtu3_ep *mep, u32 seg_size) { @@ -656,6 +657,8 @@ static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) break; } dev_dbg(mtu->dev, "%s: %s\n", __func__, usb_speed_string(udev_speed)); + mtu3_dbg_trace(mtu->dev, "link speed %s", + usb_speed_string(udev_speed)); mtu->g.speed = udev_speed; mtu->g.ep0->maxpacket = maxpkt; @@ -678,6 +681,7 @@ static irqreturn_t mtu3_u3_ltssm_isr(struct mtu3 *mtu) ltssm &= mtu3_readl(mbase, U3D_LTSSM_INTR_ENABLE); mtu3_writel(mbase, U3D_LTSSM_INTR, ltssm); /* W1C */ dev_dbg(mtu->dev, "=== LTSSM[%x] ===\n", ltssm); + trace_mtu3_u3_ltssm_isr(ltssm); if (ltssm & (HOT_RST_INTR | WARM_RST_INTR)) mtu3_gadget_reset(mtu); @@ -708,6 +712,7 @@ static irqreturn_t mtu3_u2_common_isr(struct mtu3 *mtu) u2comm &= mtu3_readl(mbase, U3D_COMMON_USB_INTR_ENABLE); mtu3_writel(mbase, U3D_COMMON_USB_INTR, u2comm); /* W1C */ dev_dbg(mtu->dev, "=== U2COMM[%x] ===\n", u2comm); + trace_mtu3_u2_common_isr(u2comm); if (u2comm & SUSPEND_INTR) mtu3_gadget_suspend(mtu); diff --git a/drivers/usb/mtu3/mtu3_debug.h b/drivers/usb/mtu3/mtu3_debug.h index d97a48c73469..e96a69234d05 100644 --- a/drivers/usb/mtu3/mtu3_debug.h +++ b/drivers/usb/mtu3/mtu3_debug.h @@ -39,4 +39,12 @@ static inline void ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb) {} #endif /* CONFIG_DEBUG_FS */ +#if IS_ENABLED(CONFIG_TRACING) +void mtu3_dbg_trace(struct device *dev, const char *fmt, ...); + +#else +static inline void mtu3_dbg_trace(struct device *dev, const char *fmt, ...) {} + +#endif /* CONFIG_TRACING */ + #endif /* __MTU3_DEBUG_H__ */ diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index ff2956272e15..82913120622b 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -141,6 +141,7 @@ static void ssusb_set_mailbox(struct otg_switch_mtk *otg_sx, struct mtu3 *mtu = ssusb->u3d; dev_dbg(ssusb->dev, "mailbox state(%d)\n", status); + mtu3_dbg_trace(ssusb->dev, "mailbox %d", status); switch (status) { case MTU3_ID_GROUND: diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index fe798b94a357..f93732e53fd8 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c @@ -8,6 +8,7 @@ */ #include "mtu3.h" +#include "mtu3_trace.h" void mtu3_req_complete(struct mtu3_ep *mep, struct usb_request *req, int status) @@ -25,6 +26,8 @@ __acquires(mep->mtu->lock) mtu = mreq->mtu; mep->busy = 1; + + trace_mtu3_req_complete(mreq); spin_unlock(&mtu->lock); /* ep0 makes use of PIO, needn't unmap it */ @@ -201,6 +204,7 @@ static int mtu3_gadget_ep_enable(struct usb_ep *ep, spin_unlock_irqrestore(&mtu->lock, flags); dev_dbg(mtu->dev, "%s active_ep=%d\n", __func__, mtu->active_ep); + trace_mtu3_gadget_ep_enable(mep); return ret; } @@ -212,6 +216,7 @@ static int mtu3_gadget_ep_disable(struct usb_ep *ep) unsigned
[PATCH 02/11] usb: mtu3: print useful information also for device and host modes
Print useful information not only dual-role mode but also device mode and host mode. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3_plat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index dee31d5eefe1..3a4a80f15957 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c @@ -286,7 +286,7 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) ssusb->dr_mode = USB_DR_MODE_OTG; if (ssusb->dr_mode == USB_DR_MODE_PERIPHERAL) - return 0; + goto out; /* if host role is supported */ ret = ssusb_wakeup_of_property_parse(ssusb, node); @@ -307,7 +307,7 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) otg_sx->vbus = vbus; if (ssusb->dr_mode == USB_DR_MODE_HOST) - return 0; + goto out; /* if dual-role mode is supported */ otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd"); @@ -322,6 +322,7 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) } } +out: dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk: %x, drd: %s\n", ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk, otg_sx->manual_drd_enabled ? "manual" : "auto"); -- 2.20.1
[PATCH 08/11] usb: mtu3: add debugfs interface files
This adds more debugfs consumers. The debugfs entries read some important registers, fifo status, QMU ring, endpoint status, and IPPC probe interface to get internal status. With these entries, users can check the registers, endpoint and GPD used during run time. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/Makefile | 4 + drivers/usb/mtu3/mtu3_core.c| 3 + drivers/usb/mtu3/mtu3_debug.h | 40 +++ drivers/usb/mtu3/mtu3_debugfs.c | 438 drivers/usb/mtu3/mtu3_dr.c | 13 +- drivers/usb/mtu3/mtu3_hw_regs.h | 11 + drivers/usb/mtu3/mtu3_plat.c| 7 +- 7 files changed, 503 insertions(+), 13 deletions(-) create mode 100644 drivers/usb/mtu3/mtu3_debug.h create mode 100644 drivers/usb/mtu3/mtu3_debugfs.c diff --git a/drivers/usb/mtu3/Makefile b/drivers/usb/mtu3/Makefile index 4a9715812bf9..7c1826bbcebb 100644 --- a/drivers/usb/mtu3/Makefile +++ b/drivers/usb/mtu3/Makefile @@ -17,3 +17,7 @@ endif ifneq ($(CONFIG_USB_MTU3_DUAL_ROLE),) mtu3-y += mtu3_dr.o endif + +ifneq ($(CONFIG_DEBUG_FS),) + mtu3-y += mtu3_debugfs.o +endif diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index d354f5c3805a..f106fe81ae10 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -16,6 +16,7 @@ #include #include "mtu3.h" +#include "mtu3_debug.h" static int ep_fifo_alloc(struct mtu3_ep *mep, u32 seg_size) { @@ -900,6 +901,8 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG) mtu3_stop(mtu); + ssusb_dev_debugfs_init(ssusb); + dev_dbg(dev, " %s() done...\n", __func__); return 0; diff --git a/drivers/usb/mtu3/mtu3_debug.h b/drivers/usb/mtu3/mtu3_debug.h new file mode 100644 index ..94d39b00403e --- /dev/null +++ b/drivers/usb/mtu3/mtu3_debug.h @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mtu3_debug.h - debug header + * + * Copyright (C) 2019 MediaTek Inc. + * + * Author: Chunfeng Yun + */ + +#ifndef __MTU3_DEBUG_H__ +#define __MTU3_DEBUG_H__ + +#include + +#define MTU3_DEBUGFS_NAME_LEN 32 + +struct mtu3_regset { + char name[MTU3_DEBUGFS_NAME_LEN]; + struct debugfs_regset32 regset; + size_t nregs; +}; + +struct mtu3_file_map { + const char *name; + int (*show)(struct seq_file *s, void *unused); +}; + +#if IS_ENABLED(CONFIG_DEBUG_FS) +void ssusb_dev_debugfs_init(struct ssusb_mtk *ssusb); +void ssusb_debugfs_create_root(struct ssusb_mtk *ssusb); +void ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb); + +#else +static inline void ssusb_dev_debugfs_init(struct ssusb_mtk *ssusb) {} +static inline void ssusb_debugfs_create_root(struct ssusb_mtk *ssusb) {} +static inline void ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb) {} + +#endif /* CONFIG_DEBUG_FS */ + +#endif /* __MTU3_DEBUG_H__ */ diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c new file mode 100644 index ..7cb1cad5a4b3 --- /dev/null +++ b/drivers/usb/mtu3/mtu3_debugfs.c @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mtu3_debugfs.c - debugfs interface + * + * Copyright (C) 2019 MediaTek Inc. + * + * Author: Chunfeng Yun + */ + +#include + +#include "mtu3.h" +#include "mtu3_debug.h" + +#define dump_register(nm) \ +{ \ + .name = __stringify(nm),\ + .offset = U3D_ ##nm,\ +} + +#define dump_prb_reg(nm, os) \ +{ \ + .name = nm, \ + .offset = os, \ +} + +static const struct debugfs_reg32 mtu3_ippc_regs[] = { + dump_register(SSUSB_IP_PW_CTRL0), + dump_register(SSUSB_IP_PW_CTRL1), + dump_register(SSUSB_IP_PW_CTRL2), + dump_register(SSUSB_IP_PW_CTRL3), + dump_register(SSUSB_OTG_STS), + dump_register(SSUSB_IP_XHCI_CAP), + dump_register(SSUSB_IP_DEV_CAP), + dump_register(SSUSB_U3_CTRL_0P), + dump_register(SSUSB_U2_CTRL_0P), + dump_register(SSUSB_HW_ID), + dump_register(SSUSB_HW_SUB_ID), + dump_register(SSUSB_IP_SPARE0), +}; + +static const struct debugfs_reg32 mtu3_dev_regs[] = { + dump_register(LV1ISR), + dump_register(LV1IER), + dump_register(EPISR), + dump_register(EPIER), + dump_register(EP0CSR), + dump_register(RXCOUNT0), + dump_register(QISAR0), + dump_register(QIER0), + dump_register(QISAR1), + dump_register(QIER1), + dump_register(CAP_EPNTXFFSZ), + dump_register(CAP_EPNRXFFSZ), + dump_register(CAP_EPINFO), + dump_register(MISC_CTRL), +}; + +static const struct debugfs_reg32 mtu3_csr_regs[] = { + dump_register(DEVICE_CONF), + dump_register(DEV_LINK_INTR_ENABLE), + dump_register(DEV_LINK_INTR), + dump_register(LTSSM_CTRL), + dump_registe
[PATCH 09/11] usb: mtu3: move vbus and mode debugfs interfaces into mtu3_debugfs.c
Due to the separated debugfs files are added, move vbus and mode debugfs interfaces related with dual-role switch from mtu3_dr.c into mtu3_debugfs.c Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3_debug.h | 2 + drivers/usb/mtu3/mtu3_debugfs.c | 101 drivers/usb/mtu3/mtu3_dr.c | 113 +--- drivers/usb/mtu3/mtu3_dr.h | 4 ++ 4 files changed, 110 insertions(+), 110 deletions(-) diff --git a/drivers/usb/mtu3/mtu3_debug.h b/drivers/usb/mtu3/mtu3_debug.h index 94d39b00403e..d97a48c73469 100644 --- a/drivers/usb/mtu3/mtu3_debug.h +++ b/drivers/usb/mtu3/mtu3_debug.h @@ -27,11 +27,13 @@ struct mtu3_file_map { #if IS_ENABLED(CONFIG_DEBUG_FS) void ssusb_dev_debugfs_init(struct ssusb_mtk *ssusb); +void ssusb_dr_debugfs_init(struct ssusb_mtk *ssusb); void ssusb_debugfs_create_root(struct ssusb_mtk *ssusb); void ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb); #else static inline void ssusb_dev_debugfs_init(struct ssusb_mtk *ssusb) {} +static inline void ssusb_dr_debugfs_init(struct ssusb_mtk *ssusb) {} static inline void ssusb_debugfs_create_root(struct ssusb_mtk *ssusb) {} static inline void ssusb_debugfs_remove_root(struct ssusb_mtk *ssusb) {} diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c index 7cb1cad5a4b3..62c57ddc554e 100644 --- a/drivers/usb/mtu3/mtu3_debugfs.c +++ b/drivers/usb/mtu3/mtu3_debugfs.c @@ -10,6 +10,7 @@ #include #include "mtu3.h" +#include "mtu3_dr.h" #include "mtu3_debug.h" #define dump_register(nm) \ @@ -425,6 +426,106 @@ void ssusb_dev_debugfs_init(struct ssusb_mtk *ssusb) mtu, &mtu3_ep_used_fops); } +static int ssusb_mode_show(struct seq_file *sf, void *unused) +{ + struct ssusb_mtk *ssusb = sf->private; + + seq_printf(sf, "current mode: %s(%s drd)\n(echo device/host)\n", + ssusb->is_host ? "host" : "device", + ssusb->otg_switch.manual_drd_enabled ? "manual" : "auto"); + + return 0; +} + +static int ssusb_mode_open(struct inode *inode, struct file *file) +{ + return single_open(file, ssusb_mode_show, inode->i_private); +} + +static ssize_t ssusb_mode_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *sf = file->private_data; + struct ssusb_mtk *ssusb = sf->private; + char buf[16]; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (!strncmp(buf, "host", 4) && !ssusb->is_host) { + ssusb_mode_manual_switch(ssusb, 1); + } else if (!strncmp(buf, "device", 6) && ssusb->is_host) { + ssusb_mode_manual_switch(ssusb, 0); + } else { + dev_err(ssusb->dev, "wrong or duplicated setting\n"); + return -EINVAL; + } + + return count; +} + +static const struct file_operations ssusb_mode_fops = { + .open = ssusb_mode_open, + .write = ssusb_mode_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int ssusb_vbus_show(struct seq_file *sf, void *unused) +{ + struct ssusb_mtk *ssusb = sf->private; + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + + seq_printf(sf, "vbus state: %s\n(echo on/off)\n", + regulator_is_enabled(otg_sx->vbus) ? "on" : "off"); + + return 0; +} + +static int ssusb_vbus_open(struct inode *inode, struct file *file) +{ + return single_open(file, ssusb_vbus_show, inode->i_private); +} + +static ssize_t ssusb_vbus_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *sf = file->private_data; + struct ssusb_mtk *ssusb = sf->private; + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + char buf[16]; + bool enable; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (kstrtobool(buf, &enable)) { + dev_err(ssusb->dev, "wrong setting\n"); + return -EINVAL; + } + + ssusb_set_vbus(otg_sx, enable); + + return count; +} + +static const struct file_operations ssusb_vbus_fops = { + .open = ssusb_vbus_open, + .write = ssusb_vbus_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void ssusb_dr_debugfs_init(struct ssusb_mtk *ssusb) +{ + struct dentry *root = ssusb->dbgfs_root; + + debugfs_create_file("mode", 0644, root, ssusb, &ssusb_mode_fop
[PATCH 07/11] usb: mtu3: supports new QMU format
In order to support U3gen2 ISOC transfer upto 96DPs, extend the data buffer length. Signed-off-by: Chunfeng Yun --- drivers/usb/mtu3/mtu3.h | 11 +++--- drivers/usb/mtu3/mtu3_core.c| 5 +++ drivers/usb/mtu3/mtu3_gadget.c | 6 ++-- drivers/usb/mtu3/mtu3_hw_regs.h | 1 + drivers/usb/mtu3/mtu3_qmu.c | 64 + drivers/usb/mtu3/mtu3_qmu.h | 1 + 6 files changed, 66 insertions(+), 22 deletions(-) diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 4dda7ed6e24e..76ecf12fdf62 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h @@ -148,22 +148,23 @@ struct mtu3_fifo_info { * bit0: Hardware Own (HWO) * bit1: Buffer Descriptor Present (BDP), always 0, BD is not supported * bit2: Bypass (BPS), 1: HW skips this GPD if HWO = 1 + * bit6: [EL] Zero Length Packet (ZLP), moved from @dw3_info[29] * bit7: Interrupt On Completion (IOC) - * bit[31:16]: allow data buffer length (RX ONLY), + * bit[31:16]: ([EL] bit[31:12]) allow data buffer length (RX ONLY), * the buffer length of the data to receive - * bit[23:16]: extension address (TX ONLY), + * bit[23:16]: ([EL] bit[31:24]) extension address (TX ONLY), * lower 4 bits are extension bits of @buffer, * upper 4 bits are extension bits of @next_gpd * @next_gpd: Physical address of the next GPD * @buffer: Physical address of the data buffer * @dw3_info: - * bit[15:0]: data buffer length, + * bit[15:0]: ([EL] bit[19:0]) data buffer length, * (TX): the buffer length of the data to transmit * (RX): The total length of data received - * bit[23:16]: extension address (RX ONLY), + * bit[23:16]: ([EL] bit[31:24]) extension address (RX ONLY), * lower 4 bits are extension bits of @buffer, * upper 4 bits are extension bits of @next_gpd - * bit29: Zero Length Packet (ZLP) (TX ONLY) + * bit29: ([EL] abandoned) Zero Length Packet (ZLP) (TX ONLY) */ struct qmu_gpd { __le32 dw0_info; diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index ef27c2052ad6..d354f5c3805a 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c @@ -601,6 +601,10 @@ static void mtu3_regs_init(struct mtu3 *mtu) mtu3_clrbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); /* enable automatical HWRW from L1 */ mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, LPM_HRWE); + + /* use new QMU format when HW version >= 0x1003 */ + if (mtu->gen2cp) + mtu3_writel(mbase, U3D_QFCR, ~0x0); } static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) @@ -755,6 +759,7 @@ static int mtu3_hw_init(struct mtu3 *mtu) value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_TRUNK_VERS); mtu->hw_version = IP_TRUNK_VERS(value); + mtu->gen2cp = !!(mtu->hw_version >= MTU3_TRUNK_VERS_1003); value = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_DEV_CAP); mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(value); diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index bbcd3332471d..fe798b94a357 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c @@ -278,10 +278,12 @@ static int mtu3_gadget_queue(struct usb_ep *ep, __func__, mep->is_in ? "TX" : "RX", mreq->epnum, ep->name, mreq, ep->maxpacket, mreq->request.length); - if (req->length > GPD_BUF_SIZE) { + if (req->length > GPD_BUF_SIZE || + (mtu->gen2cp && req->length > GPD_BUF_SIZE_EL)) { dev_warn(mtu->dev, "req length > supported MAX:%d requested:%d\n", - GPD_BUF_SIZE, req->length); + mtu->gen2cp ? GPD_BUF_SIZE_EL : GPD_BUF_SIZE, + req->length); return -EOPNOTSUPP; } diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h index fae3b8de1092..bf70ea2426a9 100644 --- a/drivers/usb/mtu3/mtu3_hw_regs.h +++ b/drivers/usb/mtu3/mtu3_hw_regs.h @@ -49,6 +49,7 @@ #define U3D_QCR1 (SSUSB_DEV_BASE + 0x0404) #define U3D_QCR2 (SSUSB_DEV_BASE + 0x0408) #define U3D_QCR3 (SSUSB_DEV_BASE + 0x040C) +#define U3D_QFCR (SSUSB_DEV_BASE + 0x0428) #define U3D_TXQHIAR1 (SSUSB_DEV_BASE + 0x0484) #define U3D_RXQHIAR1 (SSUSB_DEV_BASE + 0x04C4) diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c index 7a1919fc9f9e..9f017aa8fbeb 100644 --- a/drivers/usb/mtu3/mtu3_qmu.c +++ b/drivers/usb/mtu3/mtu3_qmu.c @@ -28,14 +28,42 @@ #define GPD_FLAGS_HWO BIT(0) #define GPD_FLAGS_BDP BIT(1) #define GPD_FLAGS_BPS BIT(2) +#define GPD_FLAGS_ZLP BIT(6) #define GPD_FLAGS_IOC BIT(7) #define GE
Re: [PATCH] usb: introduce usb_ep_type_string() function
Hi, On Fri, 2019-03-01 at 17:21 +0100, Greg Kroah-Hartman wrote: > On Fri, Mar 01, 2019 at 02:58:23PM +0800, Chunfeng Yun wrote: > > In some places, the code prints a human-readable USB endpoint > > transfer type (e.g. "bulk"). This involves a switch statement > > sometimes wrapped around in ({ ... }) block leading to code > > repetition. > > To make this scenario easier, here introduces usb_ep_type_string() > > function, which returns a human-readable name of provided > > endpoint type. > > It also changes a few places switch was used to use this > > new function. > > > > Signed-off-by: Chunfeng Yun > > --- > > drivers/usb/common/common.c | 16 > > drivers/usb/core/endpoint.c | 18 ++ > > drivers/usb/core/hcd.c | 17 ++--- > > drivers/usb/dwc3/debugfs.c | 23 --- > > drivers/usb/gadget/udc/aspeed-vhub/epn.c | 6 +- > > drivers/usb/gadget/udc/dummy_hcd.c | 16 +--- > > drivers/usb/host/xhci-trace.h| 19 ++- > > include/linux/usb/ch9.h | 8 > > 8 files changed, 36 insertions(+), 87 deletions(-) > > > > diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c > > index 48277bbc15e4..2174dd9ec176 100644 > > --- a/drivers/usb/common/common.c > > +++ b/drivers/usb/common/common.c > > @@ -16,6 +16,22 @@ > > #include > > #include > > > > +static const char *const ep_type_names[] = { > > + [USB_ENDPOINT_XFER_CONTROL] = "ctrl", > > + [USB_ENDPOINT_XFER_ISOC] = "isoc", > > + [USB_ENDPOINT_XFER_BULK] = "bulk", > > + [USB_ENDPOINT_XFER_INT] = "intr", > > +}; > > + > > +const char *usb_ep_type_string(int ep_type) > > +{ > > + if (ep_type < 0 || ep_type >= ARRAY_SIZE(ep_type_names)) > > + return "unknown"; > > + > > + return ep_type_names[ep_type]; > > +} > > +EXPORT_SYMBOL_GPL(usb_ep_type_string); > > + > > const char *usb_otg_state_string(enum usb_otg_state state) > > { > > static const char *const names[] = { > > diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c > > index 1c2c04079676..afa43f9a47b2 100644 > > --- a/drivers/usb/core/endpoint.c > > +++ b/drivers/usb/core/endpoint.c > > @@ -60,23 +60,9 @@ static ssize_t type_show(struct device *dev, struct > > device_attribute *attr, > > char *buf) > > { > > struct ep_device *ep = to_ep_device(dev); > > - char *type = "unknown"; > > + int ep_type = usb_endpoint_type(ep->desc); > > > > - switch (usb_endpoint_type(ep->desc)) { > > - case USB_ENDPOINT_XFER_CONTROL: > > - type = "Control"; > > - break; > > - case USB_ENDPOINT_XFER_ISOC: > > - type = "Isoc"; > > - break; > > - case USB_ENDPOINT_XFER_BULK: > > - type = "Bulk"; > > - break; > > - case USB_ENDPOINT_XFER_INT: > > - type = "Interrupt"; > > - break; > > - } > > - return sprintf(buf, "%s\n", type); > > + return sprintf(buf, "%s\n", usb_ep_type_string(ep_type)); > > You just changed a user/kernel API here, the strings are now different > from what they used to be :( How about using these type string to keep them unchanged? I need help from Felipe and Mathias to check whether the changes in dwc3 and xhci have side effect or not, and waiting for their comments Thanks > > That's not ok, odds are you will break tools if you do this. > > > } > > static DEVICE_ATTR_RO(type); > > > > diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c > > index 015b126ce455..193ee92b2fdb 100644 > > --- a/drivers/usb/core/hcd.c > > +++ b/drivers/usb/core/hcd.c > > @@ -1875,23 +1875,10 @@ void usb_hcd_flush_endpoint(struct usb_device *udev, > > /* kick hcd */ > > unlink1(hcd, urb, -ESHUTDOWN); > > dev_dbg (hcd->self.controller, > > - "shutdown urb %pK ep%d%s%s\n", > > + "shutdown urb %pK ep%d%s-%s\n", > > urb, usb_endpoint_num(&ep->desc), > > is_in ? "in" : "out", > > - ({ char *s; > > - > > -
RE: [PATCH v4 5/6] usb:cdns3 Add Cadence USB3 DRD Driver
Hi, On Mon, 2019-03-04 at 11:01 +, Pawel Laszczak wrote: > Hi, > > > >hi, > >On Thu, 2019-02-14 at 19:45 +, Pawel Laszczak wrote: > >> This patch introduce new Cadence USBSS DRD driver to linux kernel. > >> > >> The Cadence USBSS DRD Driver is a highly configurable IP Core whichi > >> can be instantiated as Dual-Role Device (DRD), Peripheral Only and > >> Host Only (XHCI)configurations. > >> > >> The current driver has been validated with FPGA burned. We have support > >> for PCIe bus, which is used on FPGA prototyping. > >> > >> The host side of USBSS-DRD controller is compliance with XHCI > >> specification, so it works with standard XHCI linux driver. > >> > >> Signed-off-by: Pawel Laszczak > >> --- [...] > >> diff --git a/drivers/usb/cdns3/Kconfig b/drivers/usb/cdns3/Kconfig > >> new file mode 100644 > >> index ..27cb3d8dbe3d > >> --- /dev/null > >> +++ b/drivers/usb/cdns3/Kconfig > >> @@ -0,0 +1,44 @@ > >> +config USB_CDNS3 > >> + tristate "Cadence USB3 Dual-Role Controller" > >> + depends on USB_SUPPORT && (USB || USB_GADGET) && HAS_DMA > >> + help > >> +Say Y here if your system has a cadence USB3 dual-role controller. > >> +It supports: dual-role switch, Host-only, and Peripheral-only. > >> + > >> +If you choose to build this driver is a dynamically linked > >> +as module, the module will be called cdns3.ko. > >> + > >> +if USB_CDNS3 > >> + > >> +config USB_CDNS3_GADGET > >> +bool "Cadence USB3 device controller" > >> +depends on USB_GADGET > >> +help > >> + Say Y here to enable device controller functionality of the > >> + cadence USBSS-DEV driver. > >> + > >> + This controller supports FF, HS and SS mode. It doesn't support > >> + LS and SSP mode. > >> + > >> +config USB_CDNS3_HOST > >> +bool "Cadence USB3 host controller" > >> +depends on USB_XHCI_HCD > >> +help > >> + Say Y here to enable host controller functionality of the > >> + cadence driver. > >> + > >> + Host controller is compliant with XHCI so it will use > >> + standard XHCI driver. > >> + > >> +config USB_CDNS3_PCI_WRAP > >> + tristate "Cadence USB3 support on PCIe-based platforms" > >> + depends on USB_PCI && ACPI > >> + default USB_CDNS3 > >> + help > >> +If you're using the USBSS Core IP with a PCIe, please say > >> +'Y' or 'M' here. > >> + > >> +If you choose to build this driver as module it will > >> +be dynamically linked and module will be called cdns3-pci.ko > >> + > >> +endif > >> diff --git a/drivers/usb/cdns3/Makefile b/drivers/usb/cdns3/Makefile > >> new file mode 100644 > >> index ..8f9438593375 > >> --- /dev/null > >> +++ b/drivers/usb/cdns3/Makefile > >> @@ -0,0 +1,14 @@ > >> +# SPDX-License-Identifier: GPL-2.0 > >> +# define_trace.h needs to know how to find our header > >> +CFLAGS_trace.o:= -I$(src) > >> + > >> +cdns3-y := core.o drd.o trace.o > >> + > >> +obj-$(CONFIG_USB_CDNS3) += cdns3.o > >> +ifneq ($(CONFIG_DEBUG_FS),) > >> + cdns3-y += debugfs.o > >> +endif > >> + > >> +cdns3-$(CONFIG_USB_CDNS3_GADGET) += gadget.o ep0.o > >> +cdns3-$(CONFIG_USB_CDNS3_HOST)+= host.o > >> +obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci-wrap.o > >when build as module: > >CONFIG_USB_CDNS3=m > >CONFIG_USB_CDNS3_GADGET=m > >CONFIG_USB_CDNS3_HOST=m > > How you set such configuration ? From make menuconfig it's impossible. I checked again, I changed it directly for easy test, sorry > > >there is an error: > >ERROR: "cdns3_handshake" [drivers/usb/cdns3/cdns3.ko] undefined! > > > >when only set: > >CONFIG_USB_CDNS3=y > >also encounter errors: > >drivers/usb/cdns3/drd.o: In function `cdns3_drd_switch_gadget': > >/drivers/usb/cdns3/drd.c:173: undefined reference to `cdns3_handshake' > >drivers/usb/cdns3/drd.o: In function `cdns3_drd_switch_host': > >drivers/usb/cdns3/drd.c:139: undefined reference to `cdns3_handshake' > > I will check this. > Thanks. > > > > > > > > >> diff --git a/drivers/usb/cdns3/cdns3-pci-wrap.c > >> b/drivers/usb/cdns3/cdns3-pci-wrap.c > >> new file mode 100644 > >> index ..d0b2d3d9b983 > >> --- /dev/null > >> +++ b/drivers/usb/cdns3/cdns3-pci-wrap.c > >> @@ -0,0 +1,155 @@ > >> +// SPDX-License-Identifier: GPL-2.0 > >> +/* > >> + * Cadence USBSS PCI Glue driver > >> + * > >> + * Copyright (C) 2018 Cadence. > >> + * > >> + * Author: Pawel Laszczak > >> + */ > >> + > >> +#include > >> +#include > >> +#include > >> +#include > >> +#include > >> +#include > >> + > >> +struct cdns3_wrap { > >> + struct platform_device *plat_dev; > >> + struct pci_dev *hg_dev; > >> + struct resource dev_res[4]; > >> +}; > >> + > >> +struct cdns3_wrap wrap; > >not used in fact? > > Yes, I forgot to remove it. > > > >> + > >> +#define RES_IRQ_ID0 > >> +#define RES_HOST_ID 1
Re: [PATCH v3 10/12] hikey960: Support usb functionality of Hikey960
hi, On Mon, 2019-03-04 at 08:50 +0200, Andy Shevchenko wrote: > On Mon, Mar 4, 2019 at 3:47 AM Chunfeng Yun wrote: > > On Sat, 2019-03-02 at 17:05 +0800, Yu Chen wrote: > > > > + hisi_hikey_usb->role_sw = usb_role_switch_get(dev); > > > + if (!hisi_hikey_usb->role_sw) > > > + return -EPROBE_DEFER; > > Here return EPROBE_DEFFER means the related device_connection is > > registered after this probe is called, right? > > if not, use IS_ERR_OR_NULL then return PTR_ERR is enough > > How enough? If return value is NULL it would be transformered to 0, > which is success return code from the ->probe() which means we will > have ->probed() and not functional device. > You are right:) > Am I missing something? >
Re: [PATCH v3 10/12] hikey960: Support usb functionality of Hikey960
hi, On Sat, 2019-03-02 at 17:05 +0800, Yu Chen wrote: > This driver handles usb hub power on and typeC port event of HiKey960 board: > 1)DP&DM switching between usb hub and typeC port base on typeC port > state > 2)Control power of usb hub on Hikey960 > 3)Control vbus of typeC port > > Cc: Chunfeng Yun > Cc: Andy Shevchenko > Cc: Arnd Bergmann > Cc: Greg Kroah-Hartman > Cc: John Stultz > Cc: Binghui Wang > Cc: Heikki Krogerus > Signed-off-by: Yu Chen > --- > v1: > * Using gpiod API with the gpios. > * Removing registering usb role switch. > * Registering usb role switch notifier. > v2: > * Fix license declaration. > * Add configuration of gpio direction. > * Remove some log print. > v3: > * Remove property of "typec_vbus_enable_val". > * Remove gpiod_direction_output and set initial value of gpio by > devm_gpiod_get. > --- > --- > drivers/misc/Kconfig | 6 ++ > drivers/misc/Makefile | 1 + > drivers/misc/hisi_hikey_usb.c | 167 > ++ > 3 files changed, 174 insertions(+) > create mode 100644 drivers/misc/hisi_hikey_usb.c > > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig > index f417b06e11c5..8d8b717759e2 100644 > --- a/drivers/misc/Kconfig > +++ b/drivers/misc/Kconfig > @@ -521,6 +521,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" > diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile > index e39ccbbc1b3a..dc8892b13a1a 100644 > --- a/drivers/misc/Makefile > +++ b/drivers/misc/Makefile > @@ -59,3 +59,4 @@ obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o > obj-$(CONFIG_OCXL) += ocxl/ > obj-y+= cardreader/ > obj-$(CONFIG_PVPANIC)+= pvpanic.o > +obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o > diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c > new file mode 100644 > index ..85d6fee468c0 > --- /dev/null > +++ b/drivers/misc/hisi_hikey_usb.c > @@ -0,0 +1,167 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Support for usb functionality of Hikey series boards > + * based on Hisilicon Kirin Soc. > + * > + * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd. > + * http://www.huawei.com > + * > + * Authors: Yu Chen > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define DEVICE_DRIVER_NAME "hisi_hikey_usb" > + > +#define HUB_VBUS_POWER_ON 1 > +#define HUB_VBUS_POWER_OFF 0 > +#define USB_SWITCH_TO_HUB 1 > +#define USB_SWITCH_TO_TYPEC 0 > +#define TYPEC_VBUS_POWER_ON 1 > +#define TYPEC_VBUS_POWER_OFF 0 > + > +struct hisi_hikey_usb { > + struct gpio_desc *otg_switch; > + struct gpio_desc *typec_vbus; > + struct gpio_desc *hub_vbus; > + > + struct usb_role_switch *role_sw; > + struct notifier_block nb; > +}; > + > +static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value) > +{ > + gpiod_set_value_cansleep(hisi_hikey_usb->hub_vbus, value); > +} > + > +static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, > + int switch_to) > +{ > + gpiod_set_value_cansleep(hisi_hikey_usb->otg_switch, switch_to); > +} > + > +static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, > + int value) > +{ > + gpiod_set_value_cansleep(hisi_hikey_usb->typec_vbus, value); > +} > + > +static int hisi_hikey_role_switch(struct notifier_block *nb, > + unsigned long state, void *data) > +{ > + struct hisi_hikey_usb *hisi_hikey_usb; > + > + hisi_hikey_usb = container_of(nb, struct hisi_hikey_usb, nb); > + > + switch (state) { > + case USB_ROLE_NONE: > + usb_typec_power_ctrl(hisi_hikey_usb, TYPEC_VBUS_POWER_OFF); > + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB); > + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON); > + break; > + case USB_ROLE_HOST: > + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); >
[PATCH] usb: introduce usb_ep_type_string() function
In some places, the code prints a human-readable USB endpoint transfer type (e.g. "bulk"). This involves a switch statement sometimes wrapped around in ({ ... }) block leading to code repetition. To make this scenario easier, here introduces usb_ep_type_string() function, which returns a human-readable name of provided endpoint type. It also changes a few places switch was used to use this new function. Signed-off-by: Chunfeng Yun --- drivers/usb/common/common.c | 16 drivers/usb/core/endpoint.c | 18 ++ drivers/usb/core/hcd.c | 17 ++--- drivers/usb/dwc3/debugfs.c | 23 --- drivers/usb/gadget/udc/aspeed-vhub/epn.c | 6 +- drivers/usb/gadget/udc/dummy_hcd.c | 16 +--- drivers/usb/host/xhci-trace.h| 19 ++- include/linux/usb/ch9.h | 8 8 files changed, 36 insertions(+), 87 deletions(-) diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index 48277bbc15e4..2174dd9ec176 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -16,6 +16,22 @@ #include #include +static const char *const ep_type_names[] = { + [USB_ENDPOINT_XFER_CONTROL] = "ctrl", + [USB_ENDPOINT_XFER_ISOC] = "isoc", + [USB_ENDPOINT_XFER_BULK] = "bulk", + [USB_ENDPOINT_XFER_INT] = "intr", +}; + +const char *usb_ep_type_string(int ep_type) +{ + if (ep_type < 0 || ep_type >= ARRAY_SIZE(ep_type_names)) + return "unknown"; + + return ep_type_names[ep_type]; +} +EXPORT_SYMBOL_GPL(usb_ep_type_string); + const char *usb_otg_state_string(enum usb_otg_state state) { static const char *const names[] = { diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 1c2c04079676..afa43f9a47b2 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -60,23 +60,9 @@ static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ep_device *ep = to_ep_device(dev); - char *type = "unknown"; + int ep_type = usb_endpoint_type(ep->desc); - switch (usb_endpoint_type(ep->desc)) { - case USB_ENDPOINT_XFER_CONTROL: - type = "Control"; - break; - case USB_ENDPOINT_XFER_ISOC: - type = "Isoc"; - break; - case USB_ENDPOINT_XFER_BULK: - type = "Bulk"; - break; - case USB_ENDPOINT_XFER_INT: - type = "Interrupt"; - break; - } - return sprintf(buf, "%s\n", type); + return sprintf(buf, "%s\n", usb_ep_type_string(ep_type)); } static DEVICE_ATTR_RO(type); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 015b126ce455..193ee92b2fdb 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1875,23 +1875,10 @@ void usb_hcd_flush_endpoint(struct usb_device *udev, /* kick hcd */ unlink1(hcd, urb, -ESHUTDOWN); dev_dbg (hcd->self.controller, - "shutdown urb %pK ep%d%s%s\n", + "shutdown urb %pK ep%d%s-%s\n", urb, usb_endpoint_num(&ep->desc), is_in ? "in" : "out", - ({ char *s; - -switch (usb_endpoint_type(&ep->desc)) { -case USB_ENDPOINT_XFER_CONTROL: - s = ""; break; -case USB_ENDPOINT_XFER_BULK: - s = "-bulk"; break; -case USB_ENDPOINT_XFER_INT: - s = "-intr"; break; -default: - s = "-iso"; break; - }; - s; - })); + usb_ep_type_string(usb_endpoint_type(&ep->desc))); usb_put_urb (urb); /* list contents may have changed */ diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 1c792710348f..d9e2a63835fe 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -750,28 +750,13 @@ static int dwc3_transfer_type_show(struct seq_file *s, void *unused) unsigned long flags; spin_lock_irqsave(&dwc->lock, flags); - if (!(dep->flags & DWC3_EP_ENABLED) || - !dep->endpoint.desc) { - seq_printf(s, "--\n"); +
Re: [PATCH v2 08/10] hikey960: Support usb functionality of Hikey960
On Tue, 2019-02-19 at 11:20 +0800, Chen Yu wrote: > Hi, > > On 2019/2/19 10:50, Chunfeng Yun wrote: > >> + if (ret) > >> + hisi_hikey_usb->typec_vbus_enable_val = 1; > >> + > >> + hisi_hikey_usb->typec_vbus = devm_gpiod_get(dev, "typec-vbus", > >> + hisi_hikey_usb->typec_vbus_enable_val ? > >> + GPIOD_OUT_LOW : GPIOD_OUT_HIGH); > >> + if (!hisi_hikey_usb->typec_vbus) > >> + return -ENOENT; > >> + else if (IS_ERR(hisi_hikey_usb->typec_vbus)) > >> + return PTR_ERR(hisi_hikey_usb->typec_vbus); > >> + > >> + gpiod_direction_output(hisi_hikey_usb->typec_vbus, > >> + !hisi_hikey_usb->typec_vbus_enable_val); > > maybe a simple way if use fixed regulator? > > > The hardware of the Hikey960 board has been fixed, and the type-c > port can act as UFP. So it is better to close the vbus when Hikey960 > connect to host(e.g PC). I guess you misunderstand what I mean? Please refer to bindings/regulator/fixed-regulator.txt If you control vbus by gpio, you can use fixed-regulator, it will be easy to make compatible with other cases, think about using a LDO to control vbus > >> + > >> + hisi_hikey_usb->otg_switch = devm_gpiod_get(dev, "otg-switch", > >> GPIOD_IN); > >> + if (!hisi_hikey_usb->otg_switch) > >> + return -ENOENT; > >> + else if (IS_ERR(hisi_hikey_usb->otg_switch)) > >> + return PTR_ERR(hisi_hikey_usb->otg_switch); > >> + > >> + gpiod_direction_output(hisi_hikey_usb->otg_switch, USB_SWITCH_TO_HUB); > >> + > >> + /* hub-vdd33-en is optional */ > >> + hisi_hikey_usb->hub_vbus = devm_gpiod_get(dev, "hub-vdd33-en", > >> + GPIOD_OUT_LOW); > >> + if (IS_ERR(hisi_hikey_usb->hub_vbus)) > >> + return PTR_ERR(hisi_hikey_usb->hub_vbus); > >> + > >> + gpiod_direction_output(hisi_hikey_usb->hub_vbus, HUB_VBUS_POWER_ON); > > ditto > >> + > >> + hisi_hikey_usb->role_sw = usb_role_switch_get(dev); > >> + if (!hisi_hikey_usb->role_sw) > >> + return -EPROBE_DEFER; > >> + else if (IS_ERR(hisi_hikey_usb->role_sw)) > >> + return PTR_ERR(hisi_hikey_usb->role_sw); > >> + > > Thanks > Yu Chen >
Re: [PATCH v2 01/10] dt-bindings: phy: Add support for HiSilicon's hi3660 USB PHY
Hi, On Tue, 2019-02-19 at 09:50 +0800, Chen Yu wrote: > Hi, > > On 2019/2/19 4:18, Rob Herring wrote: > > On Mon, Feb 18, 2019 at 07:23:01PM +0800, Yu Chen wrote: > >> This patch adds binding documentation for supporting the hi3660 usb > >> phy on boards like the HiKey960. > >> > >> Cc: Rob Herring > >> Cc: Mark Rutland > >> Cc: John Stultz > >> Cc: Binghui Wang > >> Signed-off-by: Yu Chen > >> --- > >> v1: > >> * Fix some format error as suggested by Rob. > >> v2: > >> * Change hi3660 usb PHY to hi3660 USB PHY > >> --- > >> --- > >> .../devicetree/bindings/phy/phy-hi3660-usb3.txt | 21 > >> + > >> 1 file changed, 21 insertions(+) > >> create mode 100644 > >> Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt > >> > >> diff --git a/Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt > >> b/Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt > >> new file mode 100644 > >> index ..f9a3d56cfdd2 > >> --- /dev/null > >> +++ b/Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt > >> @@ -0,0 +1,21 @@ > >> +Hisilicon hi3660 USB PHY > >> +--- > >> + > >> +Required properties: > >> +- compatible: should be "hisilicon,hi3660-usb-phy" > >> +- #phy-cells: must be 0 > >> +- hisilicon,pericrg-syscon: phandle of syscon used to control phy. > >> +- hisilicon,pctrl-syscon: phandle of syscon used to control phy. > >> +- hisilicon,usb3-otg-bc-syscon: phandle of syscon used to control phy. > >> +- hisilicon,eye-diagram-param: parameter set for phy > >> +Refer to phy/phy-bindings.txt for the generic PHY binding properties > >> + > >> +Example: > >> + usb-phy { > >> + compatible = "hisilicon,hi3660-usb-phy"; > >> + #phy-cells = <0>; > >> + hisilicon,pericrg-syscon = <&crg_ctrl>; > >> + hisilicon,pctrl-syscon = <&pctrl>; > >> + hisilicon,usb3-otg-bc-syscon = <&usb3_otg_bc>; > > > > Are most of the registers within one of these blocks? If so, make this > > node a child of that node. > I met a problem when I made this node a child of the syscon node, > the driver "phy-hi3660-usb3" was not probed. > Do you have any idea about how to make it probed when it is a child node? call of_platform_populate() in parent node's driver, but I don't know whether it's a standard way > > > >> + hisilicon,eye-diagram-param = <0x22466e4>; > >> + }; > >> -- > >> 2.15.0-rc2 > >> > > > > . > > > > Thanks > Yu Chen >
Re: [PATCH v2 08/10] hikey960: Support usb functionality of Hikey960
Hi, On Mon, 2019-02-18 at 19:23 +0800, Yu Chen wrote: > This driver handles usb hub power on and typeC port event of HiKey960 board: > 1)DP&DM switching between usb hub and typeC port base on typeC port > state > 2)Control power of usb hub on Hikey960 > 3)Control vbus of typeC port > > Cc: Andy Shevchenko > Cc: Arnd Bergmann > Cc: Greg Kroah-Hartman > Cc: John Stultz > Cc: Binghui Wang > Cc: Heikki Krogerus > Signed-off-by: Yu Chen > > --- > v1: > * Using gpiod API with the gpios. > * Removing registering usb role switch. > * Registering usb role switch notifier. > v2: > * Fix license declaration. > * Add configuration of gpio direction. > * Remove some log print. > --- > --- > drivers/misc/Kconfig | 6 ++ > drivers/misc/Makefile | 1 + > drivers/misc/hisi_hikey_usb.c | 181 > ++ > 3 files changed, 188 insertions(+) > create mode 100644 drivers/misc/hisi_hikey_usb.c > > diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig > index f417b06e11c5..8d8b717759e2 100644 > --- a/drivers/misc/Kconfig > +++ b/drivers/misc/Kconfig > @@ -521,6 +521,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" > diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile > index e39ccbbc1b3a..dc8892b13a1a 100644 > --- a/drivers/misc/Makefile > +++ b/drivers/misc/Makefile > @@ -59,3 +59,4 @@ obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o > obj-$(CONFIG_OCXL) += ocxl/ > obj-y+= cardreader/ > obj-$(CONFIG_PVPANIC)+= pvpanic.o > +obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o > diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c > new file mode 100644 > index ..70013f8e76f0 > --- /dev/null > +++ b/drivers/misc/hisi_hikey_usb.c > @@ -0,0 +1,181 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Support for usb functionality of Hikey series boards > + * based on Hisilicon Kirin Soc. > + * > + * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd. > + * http://www.huawei.com > + * > + * Authors: Yu Chen > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define DEVICE_DRIVER_NAME "hisi_hikey_usb" > + > +#define HUB_VBUS_POWER_ON 1 > +#define HUB_VBUS_POWER_OFF 0 > +#define USB_SWITCH_TO_HUB 1 > +#define USB_SWITCH_TO_TYPEC 0 > + > +struct hisi_hikey_usb { > + struct gpio_desc *otg_switch; > + struct gpio_desc *typec_vbus; > + struct gpio_desc *hub_vbus; > + int typec_vbus_enable_val; > + > + struct usb_role_switch *role_sw; > + struct notifier_block nb; > +}; > + > +static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value) > +{ > + gpiod_set_value_cansleep(hisi_hikey_usb->hub_vbus, value); > +} > + > +static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, > + int switch_to) > +{ > + gpiod_set_value_cansleep(hisi_hikey_usb->otg_switch, switch_to); > +} > + > +static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, > + int value) > +{ > + gpiod_set_value_cansleep(hisi_hikey_usb->typec_vbus, value); > +} > + > +static int hisi_hikey_role_switch(struct notifier_block *nb, > + unsigned long state, void *data) > +{ > + struct hisi_hikey_usb *hisi_hikey_usb; > + > + hisi_hikey_usb = container_of(nb, struct hisi_hikey_usb, nb); > + > + switch (state) { > + case USB_ROLE_NONE: > + usb_typec_power_ctrl(hisi_hikey_usb, > + !hisi_hikey_usb->typec_vbus_enable_val); > + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB); > + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON); > + break; > + case USB_ROLE_HOST: > + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); > + usb_typec_power_ctrl(hisi_hikey_usb, > + hisi_hikey_usb->typec_vbus_enable_val); > + break; > + case USB_ROLE_DEVICE: > + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF); > + usb_typec_power_ctrl(hisi_hikey_usb, > + !hisi_hikey_usb->typec_vbus_enable_val); > + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); > + break; > + default: > + break; > + } > + > + return 0; > +} > + > +static int hisi_hikey_usb_probe(struct platform_device *pdev) > +{ > + struct device *dev =
Re: [PATCH v4 5/6] usb:cdns3 Add Cadence USB3 DRD Driver
hi, On Thu, 2019-02-14 at 19:45 +, Pawel Laszczak wrote: > This patch introduce new Cadence USBSS DRD driver to linux kernel. > > The Cadence USBSS DRD Driver is a highly configurable IP Core whichi > can be instantiated as Dual-Role Device (DRD), Peripheral Only and > Host Only (XHCI)configurations. > > The current driver has been validated with FPGA burned. We have support > for PCIe bus, which is used on FPGA prototyping. > > The host side of USBSS-DRD controller is compliance with XHCI > specification, so it works with standard XHCI linux driver. > > Signed-off-by: Pawel Laszczak > --- > drivers/usb/Kconfig|2 + > drivers/usb/Makefile |2 + > drivers/usb/cdns3/Kconfig | 44 + > drivers/usb/cdns3/Makefile | 14 + > drivers/usb/cdns3/cdns3-pci-wrap.c | 155 +++ > drivers/usb/cdns3/core.c | 403 ++ > drivers/usb/cdns3/core.h | 116 ++ > drivers/usb/cdns3/debug.h | 168 +++ > drivers/usb/cdns3/debugfs.c| 164 +++ > drivers/usb/cdns3/drd.c| 365 + > drivers/usb/cdns3/drd.h| 162 +++ > drivers/usb/cdns3/ep0.c| 907 + > drivers/usb/cdns3/gadget-export.h | 28 + > drivers/usb/cdns3/gadget.c | 2003 > drivers/usb/cdns3/gadget.h | 1207 + > drivers/usb/cdns3/host-export.h| 28 + > drivers/usb/cdns3/host.c | 72 + > drivers/usb/cdns3/trace.c | 23 + > drivers/usb/cdns3/trace.h | 404 ++ > 19 files changed, 6267 insertions(+) > create mode 100644 drivers/usb/cdns3/Kconfig > create mode 100644 drivers/usb/cdns3/Makefile > create mode 100644 drivers/usb/cdns3/cdns3-pci-wrap.c > create mode 100644 drivers/usb/cdns3/core.c > create mode 100644 drivers/usb/cdns3/core.h > create mode 100644 drivers/usb/cdns3/debug.h > create mode 100644 drivers/usb/cdns3/debugfs.c > create mode 100644 drivers/usb/cdns3/drd.c > create mode 100644 drivers/usb/cdns3/drd.h > create mode 100644 drivers/usb/cdns3/ep0.c > create mode 100644 drivers/usb/cdns3/gadget-export.h > create mode 100644 drivers/usb/cdns3/gadget.c > create mode 100644 drivers/usb/cdns3/gadget.h > create mode 100644 drivers/usb/cdns3/host-export.h > create mode 100644 drivers/usb/cdns3/host.c > create mode 100644 drivers/usb/cdns3/trace.c > create mode 100644 drivers/usb/cdns3/trace.h > > diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig > index 987fc5ba6321..5f9334019d04 100644 > --- a/drivers/usb/Kconfig > +++ b/drivers/usb/Kconfig > @@ -112,6 +112,8 @@ source "drivers/usb/usbip/Kconfig" > > endif > > +source "drivers/usb/cdns3/Kconfig" > + > source "drivers/usb/mtu3/Kconfig" > > source "drivers/usb/musb/Kconfig" > diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile > index 7d1b8c82b208..ab125b966cac 100644 > --- a/drivers/usb/Makefile > +++ b/drivers/usb/Makefile > @@ -12,6 +12,8 @@ obj-$(CONFIG_USB_DWC3) += dwc3/ > obj-$(CONFIG_USB_DWC2) += dwc2/ > obj-$(CONFIG_USB_ISP1760)+= isp1760/ > > +obj-$(CONFIG_USB_CDNS3) += cdns3/ > + > obj-$(CONFIG_USB_MON)+= mon/ > obj-$(CONFIG_USB_MTU3) += mtu3/ > > diff --git a/drivers/usb/cdns3/Kconfig b/drivers/usb/cdns3/Kconfig > new file mode 100644 > index ..27cb3d8dbe3d > --- /dev/null > +++ b/drivers/usb/cdns3/Kconfig > @@ -0,0 +1,44 @@ > +config USB_CDNS3 > + tristate "Cadence USB3 Dual-Role Controller" > + depends on USB_SUPPORT && (USB || USB_GADGET) && HAS_DMA > + help > + Say Y here if your system has a cadence USB3 dual-role controller. > + It supports: dual-role switch, Host-only, and Peripheral-only. > + > + If you choose to build this driver is a dynamically linked > + as module, the module will be called cdns3.ko. > + > +if USB_CDNS3 > + > +config USB_CDNS3_GADGET > +bool "Cadence USB3 device controller" > +depends on USB_GADGET > +help > + Say Y here to enable device controller functionality of the > + cadence USBSS-DEV driver. > + > + This controller supports FF, HS and SS mode. It doesn't support > + LS and SSP mode. > + > +config USB_CDNS3_HOST > +bool "Cadence USB3 host controller" > +depends on USB_XHCI_HCD > +help > + Say Y here to enable host controller functionality of the > + cadence driver. > + > + Host controller is compliant with XHCI so it will use > + standard XHCI driver. > + > +config USB_CDNS3_PCI_WRAP > + tristate "Cadence USB3 support on PCIe-based platforms" > + depends on USB_PCI && ACPI > + default USB_CDNS3 > + help > + If you're using the USBSS Core IP with a PCIe, please say > + 'Y' or 'M' here. > + > + If you choose to build this driver as module it will > + be dynamically linked and module will be cal
[PATCH v2] usb: xhci: remove unused member 'parent' in xhci_regset struct
The member @parent of xhci_regset struct is not used in fact, so remove it Signed-off-by: Chunfeng Yun --- v2: remove Change-Id --- drivers/usb/host/xhci-debugfs.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/host/xhci-debugfs.h b/drivers/usb/host/xhci-debugfs.h index ac5bc40f5c3a..f7a4e2492b00 100644 --- a/drivers/usb/host/xhci-debugfs.h +++ b/drivers/usb/host/xhci-debugfs.h @@ -80,7 +80,6 @@ struct xhci_regset { charname[DEBUGFS_NAMELEN]; struct debugfs_regset32 regset; size_t nregs; - struct dentry *parent; struct list_headlist; }; -- 2.20.1
Re: [PATCH] usb: xhci: remove unused member 'parent' in xhci_regset struct
On Wed, 2019-01-30 at 08:12 +0100, Greg Kroah-Hartman wrote: > On Wed, Jan 30, 2019 at 10:12:21AM +0800, Chunfeng Yun wrote: > > The member @parent of xhci_regset struct is not used in fact, > > so remove it > > > > Change-Id: Ic6727c28f7200782fe4516bcb41c789b427318a2 > > No need for this line :( Oh, my bad, I'll resend it, thanks
[PATCH] usb: xhci: remove unused member 'parent' in xhci_regset struct
The member @parent of xhci_regset struct is not used in fact, so remove it Change-Id: Ic6727c28f7200782fe4516bcb41c789b427318a2 Signed-off-by: Chunfeng Yun --- drivers/usb/host/xhci-debugfs.h |1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/host/xhci-debugfs.h b/drivers/usb/host/xhci-debugfs.h index ac5bc40..f7a4e24 100644 --- a/drivers/usb/host/xhci-debugfs.h +++ b/drivers/usb/host/xhci-debugfs.h @@ -80,7 +80,6 @@ struct xhci_regset { charname[DEBUGFS_NAMELEN]; struct debugfs_regset32 regset; size_t nregs; - struct dentry *parent; struct list_headlist; }; -- 1.7.9.5
Re: [PATCH v2 05/10] phy: add A3700 UTMI PHY driver
Hi, On Fri, 2019-01-11 at 14:31 +0100, Miquel Raynal wrote: > Marvell Armada 3700 SoC has two USB controllers, each of them being > wired to an internal UTMI PHY. Add a driver to control them. > > Igal Liberman worked on supporting the PHY, I took the while 'register > configuration' from his work and rewrote almost entirely the > driver/bindings around it. > > Co-developed-by: Igal Liberman > Signed-off-by: Miquel Raynal > Signed-off-by: Igal Liberman > --- > drivers/phy/marvell/Kconfig| 9 + > drivers/phy/marvell/Makefile | 1 + > drivers/phy/marvell/phy-mvebu-a3700-utmi.c | 297 + > 3 files changed, 307 insertions(+) > create mode 100644 drivers/phy/marvell/phy-mvebu-a3700-utmi.c > > diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig > index 9c90c0408ea3..b8e9dd38ad0d 100644 > --- a/drivers/phy/marvell/Kconfig > +++ b/drivers/phy/marvell/Kconfig > @@ -33,6 +33,15 @@ config PHY_MVEBU_A3700_COMPHY > shared serdes PHYs on Marvell Armada 3700. Its serdes lanes can be > used by various controllers: Ethernet, SATA, USB3, PCIe. > > +config PHY_MVEBU_A3700_UTMI > + tristate "Marvell A3700 UTMI driver" > + depends on ARCH_MVEBU || COMPILE_TEST > + depends on OF > + default y > + select GENERIC_PHY > + help > + Enable this to support Marvell A3700 UTMI PHY driver. > + > config PHY_MVEBU_CP110_COMPHY > tristate "Marvell CP110 comphy driver" > depends on ARCH_MVEBU || COMPILE_TEST > diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile > index c13a0c8ab6f0..82f291cf59ee 100644 > --- a/drivers/phy/marvell/Makefile > +++ b/drivers/phy/marvell/Makefile > @@ -3,6 +3,7 @@ obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY)+= > phy-armada375-usb2.o > obj-$(CONFIG_PHY_BERLIN_SATA)+= phy-berlin-sata.o > obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o > obj-$(CONFIG_PHY_MVEBU_A3700_COMPHY) += phy-mvebu-a3700-comphy.o > +obj-$(CONFIG_PHY_MVEBU_A3700_UTMI) += phy-mvebu-a3700-utmi.o > obj-$(CONFIG_PHY_MVEBU_CP110_COMPHY) += phy-mvebu-cp110-comphy.o > obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o > obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o > diff --git a/drivers/phy/marvell/phy-mvebu-a3700-utmi.c > b/drivers/phy/marvell/phy-mvebu-a3700-utmi.c > new file mode 100644 > index ..97d8235d661d > --- /dev/null > +++ b/drivers/phy/marvell/phy-mvebu-a3700-utmi.c > @@ -0,0 +1,297 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (C) 2018 Marvell > + * > + * Authors: > + * Evan Wang > + * Miquèl Raynal > + * > + * Marvell A3700 UTMI PHY driver > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* Armada 3700 UTMI PHY registers */ > +#define USB2_PHY_PLL_CTRL_REG0 0x0 > +#define PLL_REF_DIV_OFF0 > +#define PLL_REF_DIV_MASK (0x7F << PLL_REF_DIV_OFF) use GENMASK? > +#define PLL_REF_DIV_5 0x5 > +#define PLL_FB_DIV_OFF 16 > +#define PLL_FB_DIV_MASK(0x1FF << PLL_FB_DIV_OFF) > +#define PLL_FB_DIV_96 96 > +#define PLL_SEL_LPFR_OFF 28 > +#define PLL_SEL_LPFR_MASK (0x3 << PLL_SEL_LPFR_OFF) > +#define PLL_READY BIT(31) > +#define USB2_PHY_CAL_CTRL0x8 > +#define PHY_PLLCAL_DONEBIT(31) > +#define PHY_IMPCAL_DONEBIT(23) > +#define USB2_RX_CHAN_CTRL1 0x18 > +#define USB2PHY_SQCAL_DONE BIT(31) > +#define USB2_PHY_OTG_CTRL0x34 > +#define PHY_PU_OTG BIT(4) > +#define USB2_PHY_CHRGR_DETECT0x38 > +#define PHY_CDP_EN BIT(2) > +#define PHY_DCP_EN BIT(3) > +#define PHY_PD_EN BIT(4) > +#define PHY_PU_CHRG_DTCBIT(5) > +#define PHY_CDP_DM_AUTOBIT(7) > +#define PHY_ENSWITCH_DPBIT(12) > +#define PHY_ENSWITCH_DMBIT(13) > + > +/* Armada 3700 USB miscellaneous registers */ > +#define USB2_PHY_CTRL(usb32) (usb32 ? 0x20 : 0x4) > +#define RB_USB2PHY_PU BIT(0) > +#define USB2_DP_PULLDN_DEV_MODEBIT(5) > +#define USB2_DM_PULLDN_DEV_MODEBIT(6) > +#define RB_USB2PHY_SUSPM(usb32)(usb32 ? BIT(14) : BIT(7)) > + > +#define PLL_LOCK_DELAY_US1 > +#define PLL_LOCK_TIMEOUT_US 100 > + > +/** > + * struct mvebu_a3700_utmi_caps - PHY capabilities > + * > + * @usb32: Flag indicating which PHY is in use (impacts the register map): > + * - The UTMI PHY wired to
[PATCH v2] usb: devio: update max count of DPs per interval for ISOC
The failure happened when I tried to send up to 96DPs per an interval for SSP ISOC transations by libusb, this is used to verify SSP ISOC function of USB3 GEN2 controller, so update it as 96DPs. (refer usb3.1r1.0 section 8.12.6 Isochronous Transactions) Signed-off-by: Chunfeng Yun --- v2: update changelog text suggested by Greg --- drivers/usb/core/devio.c | 8 +++- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index a75bc0b8a50f..82c16210e34c 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1564,12 +1564,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb } for (totlen = u = 0; u < number_of_packets; u++) { /* -* arbitrary limit need for USB 3.0 -* bMaxBurst (0~15 allowed, 1~16 packets) -* bmAttributes (bit 1:0, mult 0~2, 1~3 packets) -* sizemax: 1024 * 16 * 3 = 49152 +* arbitrary limit need for USB 3.1 Gen2 +* sizemax: 96 DPs at SSP, 96 * 1024 = 98304 */ - if (isopkt[u].length > 49152) { + if (isopkt[u].length > 98304) { ret = -EINVAL; goto error; } -- 2.19.1