Re: [PATCH] usb: mtu3: fix missing include of mtu3_dr.h

2019-10-20 Thread Chunfeng Yun
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

2019-09-05 Thread Chunfeng Yun
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

2019-08-27 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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()

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-23 Thread Chunfeng Yun
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

2019-08-22 Thread Chunfeng Yun
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

2019-08-22 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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()

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-13 Thread Chunfeng Yun
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

2019-08-12 Thread Chunfeng Yun
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

2019-08-12 Thread Chunfeng Yun
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

2019-08-06 Thread Chunfeng Yun
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

2019-07-30 Thread Chunfeng Yun
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

2019-07-30 Thread Chunfeng Yun
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

2019-07-30 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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()

2019-07-24 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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.

2019-07-24 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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

2019-07-24 Thread Chunfeng Yun
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

2019-07-11 Thread Chunfeng Yun
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

2019-06-11 Thread Chunfeng Yun
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

2019-05-29 Thread Chunfeng Yun
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

2019-05-16 Thread Chunfeng Yun
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

2019-05-15 Thread Chunfeng Yun
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

2019-05-15 Thread Chunfeng Yun
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

2019-05-14 Thread Chunfeng Yun
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

2019-05-14 Thread Chunfeng Yun
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

2019-05-14 Thread Chunfeng Yun
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

2019-05-14 Thread Chunfeng Yun
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

2019-05-14 Thread Chunfeng Yun
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

2019-05-14 Thread Chunfeng Yun
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

2019-05-14 Thread Chunfeng Yun
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

2019-05-14 Thread Chunfeng Yun
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

2019-05-07 Thread Chunfeng Yun
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

2019-03-07 Thread Chunfeng Yun
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

2019-03-07 Thread Chunfeng Yun
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

2019-03-07 Thread Chunfeng Yun
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

2019-03-07 Thread Chunfeng Yun
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

2019-03-07 Thread Chunfeng Yun
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

2019-03-07 Thread Chunfeng Yun
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

2019-03-07 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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()

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-06 Thread Chunfeng Yun
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

2019-03-04 Thread Chunfeng Yun
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

2019-03-04 Thread Chunfeng Yun
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

2019-03-03 Thread Chunfeng Yun
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

2019-03-03 Thread Chunfeng Yun
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

2019-02-28 Thread Chunfeng Yun
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

2019-02-21 Thread Chunfeng Yun
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

2019-02-18 Thread Chunfeng Yun
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

2019-02-18 Thread Chunfeng Yun
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

2019-02-15 Thread Chunfeng Yun
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

2019-01-30 Thread Chunfeng Yun
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

2019-01-30 Thread Chunfeng Yun
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

2019-01-29 Thread Chunfeng Yun
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

2019-01-14 Thread Chunfeng Yun
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

2019-01-01 Thread Chunfeng Yun
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



  1   2   3   4   5   6   7   >