All of lore.kernel.org
 help / color / mirror / Atom feed
* [v4 PATCH 0/6] add USB Type-B GPIO connector driver
@ 2019-04-26  6:47 ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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.

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          |  49 +++
 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                     |  25 ++
 drivers/usb/roles/typeb-conn-gpio.c           | 305 ++++++++++++++++++
 include/linux/usb/role.h                      |   8 +
 14 files changed, 481 insertions(+), 9 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


^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4 PATCH 0/6] add USB Type-B GPIO connector driver
@ 2019-04-26  6:47 ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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.

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          |  49 +++
 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                     |  25 ++
 drivers/usb/roles/typeb-conn-gpio.c           | 305 ++++++++++++++++++
 include/linux/usb/role.h                      |   8 +
 14 files changed, 481 insertions(+), 9 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

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4 PATCH 0/6] add USB Type-B GPIO connector driver
@ 2019-04-26  6:47 ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Badhri Jagan Sridharan,
	Linus Walleij, linux-usb, linux-kernel, Biju Das,
	Matthias Brugger, Andy Shevchenko, linux-mediatek, Min Guo,
	Chunfeng Yun, Adam Thomson, linux-arm-kernel, Li Jun

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.

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          |  49 +++
 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                     |  25 ++
 drivers/usb/roles/typeb-conn-gpio.c           | 305 ++++++++++++++++++
 include/linux/usb/role.h                      |   8 +
 14 files changed, 481 insertions(+), 9 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


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH v4 1/6] dt-bindings: connector: add optional properties for Type-B
  2019-04-26  6:47 ` Chunfeng Yun
  (?)
  (?)
@ 2019-04-26  6:47   ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for
usb-b-connector

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
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


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 1/6] dt-bindings: connector: add optional properties for Type-B
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Badhri Jagan Sridharan,
	Linus Walleij, linux-usb, linux-kernel, Biju Das,
	Matthias Brugger, Andy Shevchenko, linux-mediatek, Min Guo,
	Chunfeng Yun, Adam Thomson, linux-arm-kernel, Li Jun

Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for
usb-b-connector

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
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

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [v4,1/6] dt-bindings: connector: add optional properties for Type-B
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for
usb-b-connector

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
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.

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 1/6] dt-bindings: connector: add optional properties for Type-B
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Badhri Jagan Sridharan,
	Linus Walleij, linux-usb, linux-kernel, Biju Das,
	Matthias Brugger, Andy Shevchenko, linux-mediatek, Min Guo,
	Chunfeng Yun, Adam Thomson, linux-arm-kernel, Li Jun

Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for
usb-b-connector

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
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


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
  2019-04-26  6:47 ` Chunfeng Yun
  (?)
  (?)
@ 2019-04-26  6:47   ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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          | 49 +++++++++++++++++++
 1 file changed, 49 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 000000000000..d2e1c4e01b6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
@@ -0,0 +1,49 @@
+USB Type-B GPIO Connector
+
+This is a virtual device used to switch dual role mode from the USB ID pin
+connected to an input GPIO pin.
+
+Required properties:
+- compatible : Should be "linux,typeb-conn-gpio"
+
+Sub-nodes:
+- connector : should be present.
+	- compatible : should be "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.
+	see connector/usb-connector.txt
+
+- port : should be present.
+	see graph.txt
+
+Example:
+
+rsw_iddig: role_sw_iddig {
+	compatible = "linux,typeb-conn-gpio";
+	status = "okay";
+
+	connector {
+		compatible = "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>;
+		};
+	};
+};
+
+&mtu3 {
+	status = "okay";
+
+	port {
+		usb_role_sw: endpoint@0 {
+			remote-endpoint = <&bconn_ep>;
+		};
+	};
+};
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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          | 49 +++++++++++++++++++
 1 file changed, 49 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 000000000000..d2e1c4e01b6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
@@ -0,0 +1,49 @@
+USB Type-B GPIO Connector
+
+This is a virtual device used to switch dual role mode from the USB ID pin
+connected to an input GPIO pin.
+
+Required properties:
+- compatible : Should be "linux,typeb-conn-gpio"
+
+Sub-nodes:
+- connector : should be present.
+	- compatible : should be "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.
+	see connector/usb-connector.txt
+
+- port : should be present.
+	see graph.txt
+
+Example:
+
+rsw_iddig: role_sw_iddig {
+	compatible = "linux,typeb-conn-gpio";
+	status = "okay";
+
+	connector {
+		compatible = "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>;
+		};
+	};
+};
+
+&mtu3 {
+	status = "okay";
+
+	port {
+		usb_role_sw: endpoint@0 {
+			remote-endpoint = <&bconn_ep>;
+		};
+	};
+};
-- 
2.21.0

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [v4,2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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          | 49 +++++++++++++++++++
 1 file changed, 49 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 000000000000..d2e1c4e01b6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
@@ -0,0 +1,49 @@
+USB Type-B GPIO Connector
+
+This is a virtual device used to switch dual role mode from the USB ID pin
+connected to an input GPIO pin.
+
+Required properties:
+- compatible : Should be "linux,typeb-conn-gpio"
+
+Sub-nodes:
+- connector : should be present.
+	- compatible : should be "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.
+	see connector/usb-connector.txt
+
+- port : should be present.
+	see graph.txt
+
+Example:
+
+rsw_iddig: role_sw_iddig {
+	compatible = "linux,typeb-conn-gpio";
+	status = "okay";
+
+	connector {
+		compatible = "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>;
+		};
+	};
+};
+
+&mtu3 {
+	status = "okay";
+
+	port {
+		usb_role_sw: endpoint@0 {
+			remote-endpoint = <&bconn_ep>;
+		};
+	};
+};

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Badhri Jagan Sridharan,
	Linus Walleij, linux-usb, linux-kernel, Biju Das,
	Matthias Brugger, Andy Shevchenko, linux-mediatek, Min Guo,
	Chunfeng Yun, Adam Thomson, linux-arm-kernel, Li Jun

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 <chunfeng.yun@mediatek.com>
---
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          | 49 +++++++++++++++++++
 1 file changed, 49 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 000000000000..d2e1c4e01b6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
@@ -0,0 +1,49 @@
+USB Type-B GPIO Connector
+
+This is a virtual device used to switch dual role mode from the USB ID pin
+connected to an input GPIO pin.
+
+Required properties:
+- compatible : Should be "linux,typeb-conn-gpio"
+
+Sub-nodes:
+- connector : should be present.
+	- compatible : should be "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.
+	see connector/usb-connector.txt
+
+- port : should be present.
+	see graph.txt
+
+Example:
+
+rsw_iddig: role_sw_iddig {
+	compatible = "linux,typeb-conn-gpio";
+	status = "okay";
+
+	connector {
+		compatible = "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>;
+		};
+	};
+};
+
+&mtu3 {
+	status = "okay";
+
+	port {
+		usb_role_sw: endpoint@0 {
+			remote-endpoint = <&bconn_ep>;
+		};
+	};
+};
-- 
2.21.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
  2019-04-26  6:47 ` Chunfeng Yun
  (?)
  (?)
@ 2019-04-26  6:47   ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

Now the USB Role Switch is supported, so add properties about it

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
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, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index 3382b5cb471d..6e004c4a89af 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 switch, 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 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


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

Now the USB Role Switch is supported, so add properties about it

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
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, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index 3382b5cb471d..6e004c4a89af 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 switch, 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 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

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [v4,3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

Now the USB Role Switch is supported, so add properties about it

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
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, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index 3382b5cb471d..6e004c4a89af 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 switch, 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 port would be added as subnode if use usb-role-switch property
+	see graph.txt
+
 Example:
 ssusb: usb@11271000 {
 	compatible = "mediatek,mt8173-mtu3";

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Badhri Jagan Sridharan,
	Linus Walleij, linux-usb, linux-kernel, Biju Das,
	Matthias Brugger, Andy Shevchenko, linux-mediatek, Min Guo,
	Chunfeng Yun, Adam Thomson, linux-arm-kernel, Li Jun

Now the USB Role Switch is supported, so add properties about it

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
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, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
index 3382b5cb471d..6e004c4a89af 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 switch, 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 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


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
  2019-04-26  6:47 ` Chunfeng Yun
  (?)
  (?)
@ 2019-04-26  6:47   ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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 | 25 +++++++++++++++++++++++++
 include/linux/usb/role.h  |  8 ++++++++
 2 files changed, 33 insertions(+)

diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index f45d8df5cfb8..994fcb979795 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -12,6 +12,7 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 
 static struct class *role_class;
@@ -135,6 +136,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


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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 | 25 +++++++++++++++++++++++++
 include/linux/usb/role.h  |  8 ++++++++
 2 files changed, 33 insertions(+)

diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index f45d8df5cfb8..994fcb979795 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -12,6 +12,7 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 
 static struct class *role_class;
@@ -135,6 +136,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

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [v4,4/6] usb: roles: add API to get usb_role_switch by node
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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 | 25 +++++++++++++++++++++++++
 include/linux/usb/role.h  |  8 ++++++++
 2 files changed, 33 insertions(+)

diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index f45d8df5cfb8..994fcb979795 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -12,6 +12,7 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 
 static struct class *role_class;
@@ -135,6 +136,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)

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Badhri Jagan Sridharan,
	Linus Walleij, linux-usb, linux-kernel, Biju Das,
	Matthias Brugger, Andy Shevchenko, linux-mediatek, Min Guo,
	Chunfeng Yun, Adam Thomson, linux-arm-kernel, Li Jun

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 <chunfeng.yun@mediatek.com>
---
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 | 25 +++++++++++++++++++++++++
 include/linux/usb/role.h  |  8 ++++++++
 2 files changed, 33 insertions(+)

diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index f45d8df5cfb8..994fcb979795 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -12,6 +12,7 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 
 static struct class *role_class;
@@ -135,6 +136,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


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
  2019-04-26  6:47 ` Chunfeng Yun
  (?)
  (?)
@ 2019-04-26  6:47   ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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 | 305 ++++++++++++++++++++++++++++
 3 files changed, 317 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 000000000000..097d2ca12a12
--- /dev/null
+++ b/drivers/usb/roles/typeb-conn-gpio.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USB Type-B GPIO Connector Driver
+ *
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
+ *
+ * Some code borrowed from drivers/extcon/extcon-usb-gpio.c
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/role.h>
+
+#define USB_GPIO_DEB_MS		20	/* 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 (ret)
+		dev_err(info->dev, "failed to set role: %d\n", ret);
+
+	if (role == USB_ROLE_HOST) {
+		ret = regulator_enable(info->vbus);
+		if (ret)
+			dev_err(info->dev, "enable vbus regulator failed\n");
+	}
+
+	info->last_role = role;
+
+	dev_dbg(info->dev, "vbus regulator is %s\n",
+		regulator_is_enabled(info->vbus) ? "enabled" : "disabled");
+}
+
+static void usb_conn_queue_dwork(struct usb_conn_info *info,
+				 unsigned long delay)
+{
+	queue_delayed_work(system_power_efficient_wq, &info->dw_det, delay);
+}
+
+static irqreturn_t usb_conn_isr(int irq, void *dev_id)
+{
+	struct usb_conn_info *info = dev_id;
+
+	usb_conn_queue_dwork(info, info->debounce_jiffies);
+
+	return IRQ_HANDLED;
+}
+
+static int usb_conn_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *parent;
+	struct device_node *child;
+	struct usb_conn_info *info;
+	int ret = 0;
+
+	if (!np)
+		return -EINVAL;
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = dev;
+
+	child = of_get_child_by_name(np, "connector");
+	if (!child) {
+		dev_err(dev, "failed to find connector node\n");
+		return -ENODEV;
+	}
+
+	info->id_gpiod = devm_gpiod_get_from_of_node(
+				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
+	if (IS_ERR(info->id_gpiod)) {
+		of_node_put(child);
+		return PTR_ERR(info->id_gpiod);
+	}
+
+	info->vbus_gpiod = devm_gpiod_get_from_of_node(
+				dev, child, "vbus-gpios", 0, GPIOD_IN,
+				"vbuspin");
+	if (IS_ERR(info->vbus_gpiod)) {
+		of_node_put(child);
+		return PTR_ERR(info->vbus_gpiod);
+	}
+
+	if (!info->id_gpiod && !info->vbus_gpiod) {
+		dev_err(dev, "failed to get gpios\n");
+		return -ENODEV;
+	}
+
+	of_node_put(child);
+
+	if (info->id_gpiod)
+		ret = gpiod_set_debounce(info->id_gpiod, USB_GPIO_DEB_US);
+	if (!ret && info->vbus_gpiod)
+		ret = gpiod_set_debounce(info->vbus_gpiod, USB_GPIO_DEB_US);
+	if (ret < 0)
+		info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEB_MS);
+
+	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
+
+	info->vbus = devm_regulator_get(dev, "vbus");
+	if (IS_ERR(info->vbus)) {
+		dev_err(dev, "failed to get vbus\n");
+		return PTR_ERR(info->vbus);
+	}
+
+	child = of_graph_get_endpoint_by_regs(np, -1, 0);
+	parent = of_graph_get_remote_port_parent(child);
+	info->role_sw = fwnode_usb_role_switch_get(of_fwnode_handle(parent));
+	of_node_put(child);
+	of_node_put(parent);
+	if (IS_ERR(info->role_sw)) {
+		dev_err(dev, "failed to get role switch\n");
+		return PTR_ERR(info->role_sw);
+	}
+
+	if (info->id_gpiod) {
+		info->id_irq = gpiod_to_irq(info->id_gpiod);
+		if (info->id_irq < 0) {
+			dev_err(dev, "failed to get ID IRQ\n");
+			return info->id_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
+						usb_conn_isr, USB_CONN_IRQF,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request ID IRQ\n");
+			return ret;
+		}
+	}
+
+	if (info->vbus_gpiod) {
+		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
+		if (info->vbus_irq < 0) {
+			dev_err(dev, "failed to get VBUS IRQ\n");
+			return info->vbus_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
+						usb_conn_isr, USB_CONN_IRQF,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request VBUS IRQ\n");
+			return ret;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+
+	/* Perform initial detection */
+	usb_conn_queue_dwork(info, 0);
+
+	return 0;
+}
+
+static int usb_conn_remove(struct platform_device *pdev)
+{
+	struct usb_conn_info *info = platform_get_drvdata(pdev);
+
+	cancel_delayed_work_sync(&info->dw_det);
+
+	if (info->last_role == USB_ROLE_HOST)
+		regulator_disable(info->vbus);
+
+	usb_role_switch_put(info->role_sw);
+
+	return 0;
+}
+
+static int __maybe_unused usb_conn_suspend(struct device *dev)
+{
+	struct usb_conn_info *info = dev_get_drvdata(dev);
+
+	if (info->id_gpiod)
+		disable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		disable_irq(info->vbus_irq);
+
+	pinctrl_pm_select_sleep_state(dev);
+
+	return 0;
+}
+
+static int __maybe_unused usb_conn_resume(struct device *dev)
+{
+	struct usb_conn_info *info = dev_get_drvdata(dev);
+
+	pinctrl_pm_select_default_state(dev);
+
+	if (info->id_gpiod)
+		enable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		enable_irq(info->vbus_irq);
+
+	usb_conn_queue_dwork(info, 0);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
+			 usb_conn_suspend, usb_conn_resume);
+
+#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ? &usb_conn_pm_ops : NULL)
+
+static const struct of_device_id usb_conn_dt_match[] = {
+	{ .compatible = "linux,typeb-conn-gpio", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
+
+static struct platform_driver usb_conn_driver = {
+	.probe		= usb_conn_probe,
+	.remove		= usb_conn_remove,
+	.driver		= {
+		.name	= "typeb-conn-gpio",
+		.pm	= DEV_PMS_OPS,
+		.of_match_table = usb_conn_dt_match,
+	},
+};
+
+module_platform_driver(usb_conn_driver);
+
+MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
+MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
+MODULE_LICENSE("GPL v2");
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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 | 305 ++++++++++++++++++++++++++++
 3 files changed, 317 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 000000000000..097d2ca12a12
--- /dev/null
+++ b/drivers/usb/roles/typeb-conn-gpio.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USB Type-B GPIO Connector Driver
+ *
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
+ *
+ * Some code borrowed from drivers/extcon/extcon-usb-gpio.c
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/role.h>
+
+#define USB_GPIO_DEB_MS		20	/* 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 (ret)
+		dev_err(info->dev, "failed to set role: %d\n", ret);
+
+	if (role == USB_ROLE_HOST) {
+		ret = regulator_enable(info->vbus);
+		if (ret)
+			dev_err(info->dev, "enable vbus regulator failed\n");
+	}
+
+	info->last_role = role;
+
+	dev_dbg(info->dev, "vbus regulator is %s\n",
+		regulator_is_enabled(info->vbus) ? "enabled" : "disabled");
+}
+
+static void usb_conn_queue_dwork(struct usb_conn_info *info,
+				 unsigned long delay)
+{
+	queue_delayed_work(system_power_efficient_wq, &info->dw_det, delay);
+}
+
+static irqreturn_t usb_conn_isr(int irq, void *dev_id)
+{
+	struct usb_conn_info *info = dev_id;
+
+	usb_conn_queue_dwork(info, info->debounce_jiffies);
+
+	return IRQ_HANDLED;
+}
+
+static int usb_conn_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *parent;
+	struct device_node *child;
+	struct usb_conn_info *info;
+	int ret = 0;
+
+	if (!np)
+		return -EINVAL;
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = dev;
+
+	child = of_get_child_by_name(np, "connector");
+	if (!child) {
+		dev_err(dev, "failed to find connector node\n");
+		return -ENODEV;
+	}
+
+	info->id_gpiod = devm_gpiod_get_from_of_node(
+				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
+	if (IS_ERR(info->id_gpiod)) {
+		of_node_put(child);
+		return PTR_ERR(info->id_gpiod);
+	}
+
+	info->vbus_gpiod = devm_gpiod_get_from_of_node(
+				dev, child, "vbus-gpios", 0, GPIOD_IN,
+				"vbuspin");
+	if (IS_ERR(info->vbus_gpiod)) {
+		of_node_put(child);
+		return PTR_ERR(info->vbus_gpiod);
+	}
+
+	if (!info->id_gpiod && !info->vbus_gpiod) {
+		dev_err(dev, "failed to get gpios\n");
+		return -ENODEV;
+	}
+
+	of_node_put(child);
+
+	if (info->id_gpiod)
+		ret = gpiod_set_debounce(info->id_gpiod, USB_GPIO_DEB_US);
+	if (!ret && info->vbus_gpiod)
+		ret = gpiod_set_debounce(info->vbus_gpiod, USB_GPIO_DEB_US);
+	if (ret < 0)
+		info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEB_MS);
+
+	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
+
+	info->vbus = devm_regulator_get(dev, "vbus");
+	if (IS_ERR(info->vbus)) {
+		dev_err(dev, "failed to get vbus\n");
+		return PTR_ERR(info->vbus);
+	}
+
+	child = of_graph_get_endpoint_by_regs(np, -1, 0);
+	parent = of_graph_get_remote_port_parent(child);
+	info->role_sw = fwnode_usb_role_switch_get(of_fwnode_handle(parent));
+	of_node_put(child);
+	of_node_put(parent);
+	if (IS_ERR(info->role_sw)) {
+		dev_err(dev, "failed to get role switch\n");
+		return PTR_ERR(info->role_sw);
+	}
+
+	if (info->id_gpiod) {
+		info->id_irq = gpiod_to_irq(info->id_gpiod);
+		if (info->id_irq < 0) {
+			dev_err(dev, "failed to get ID IRQ\n");
+			return info->id_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
+						usb_conn_isr, USB_CONN_IRQF,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request ID IRQ\n");
+			return ret;
+		}
+	}
+
+	if (info->vbus_gpiod) {
+		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
+		if (info->vbus_irq < 0) {
+			dev_err(dev, "failed to get VBUS IRQ\n");
+			return info->vbus_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
+						usb_conn_isr, USB_CONN_IRQF,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request VBUS IRQ\n");
+			return ret;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+
+	/* Perform initial detection */
+	usb_conn_queue_dwork(info, 0);
+
+	return 0;
+}
+
+static int usb_conn_remove(struct platform_device *pdev)
+{
+	struct usb_conn_info *info = platform_get_drvdata(pdev);
+
+	cancel_delayed_work_sync(&info->dw_det);
+
+	if (info->last_role == USB_ROLE_HOST)
+		regulator_disable(info->vbus);
+
+	usb_role_switch_put(info->role_sw);
+
+	return 0;
+}
+
+static int __maybe_unused usb_conn_suspend(struct device *dev)
+{
+	struct usb_conn_info *info = dev_get_drvdata(dev);
+
+	if (info->id_gpiod)
+		disable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		disable_irq(info->vbus_irq);
+
+	pinctrl_pm_select_sleep_state(dev);
+
+	return 0;
+}
+
+static int __maybe_unused usb_conn_resume(struct device *dev)
+{
+	struct usb_conn_info *info = dev_get_drvdata(dev);
+
+	pinctrl_pm_select_default_state(dev);
+
+	if (info->id_gpiod)
+		enable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		enable_irq(info->vbus_irq);
+
+	usb_conn_queue_dwork(info, 0);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
+			 usb_conn_suspend, usb_conn_resume);
+
+#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ? &usb_conn_pm_ops : NULL)
+
+static const struct of_device_id usb_conn_dt_match[] = {
+	{ .compatible = "linux,typeb-conn-gpio", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
+
+static struct platform_driver usb_conn_driver = {
+	.probe		= usb_conn_probe,
+	.remove		= usb_conn_remove,
+	.driver		= {
+		.name	= "typeb-conn-gpio",
+		.pm	= DEV_PMS_OPS,
+		.of_match_table = usb_conn_dt_match,
+	},
+};
+
+module_platform_driver(usb_conn_driver);
+
+MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
+MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
+MODULE_LICENSE("GPL v2");
-- 
2.21.0

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [v4,5/6] usb: roles: add USB Type-B GPIO connector driver
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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 | 305 ++++++++++++++++++++++++++++
 3 files changed, 317 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 000000000000..097d2ca12a12
--- /dev/null
+++ b/drivers/usb/roles/typeb-conn-gpio.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USB Type-B GPIO Connector Driver
+ *
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
+ *
+ * Some code borrowed from drivers/extcon/extcon-usb-gpio.c
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/role.h>
+
+#define USB_GPIO_DEB_MS		20	/* 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 (ret)
+		dev_err(info->dev, "failed to set role: %d\n", ret);
+
+	if (role == USB_ROLE_HOST) {
+		ret = regulator_enable(info->vbus);
+		if (ret)
+			dev_err(info->dev, "enable vbus regulator failed\n");
+	}
+
+	info->last_role = role;
+
+	dev_dbg(info->dev, "vbus regulator is %s\n",
+		regulator_is_enabled(info->vbus) ? "enabled" : "disabled");
+}
+
+static void usb_conn_queue_dwork(struct usb_conn_info *info,
+				 unsigned long delay)
+{
+	queue_delayed_work(system_power_efficient_wq, &info->dw_det, delay);
+}
+
+static irqreturn_t usb_conn_isr(int irq, void *dev_id)
+{
+	struct usb_conn_info *info = dev_id;
+
+	usb_conn_queue_dwork(info, info->debounce_jiffies);
+
+	return IRQ_HANDLED;
+}
+
+static int usb_conn_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *parent;
+	struct device_node *child;
+	struct usb_conn_info *info;
+	int ret = 0;
+
+	if (!np)
+		return -EINVAL;
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = dev;
+
+	child = of_get_child_by_name(np, "connector");
+	if (!child) {
+		dev_err(dev, "failed to find connector node\n");
+		return -ENODEV;
+	}
+
+	info->id_gpiod = devm_gpiod_get_from_of_node(
+				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
+	if (IS_ERR(info->id_gpiod)) {
+		of_node_put(child);
+		return PTR_ERR(info->id_gpiod);
+	}
+
+	info->vbus_gpiod = devm_gpiod_get_from_of_node(
+				dev, child, "vbus-gpios", 0, GPIOD_IN,
+				"vbuspin");
+	if (IS_ERR(info->vbus_gpiod)) {
+		of_node_put(child);
+		return PTR_ERR(info->vbus_gpiod);
+	}
+
+	if (!info->id_gpiod && !info->vbus_gpiod) {
+		dev_err(dev, "failed to get gpios\n");
+		return -ENODEV;
+	}
+
+	of_node_put(child);
+
+	if (info->id_gpiod)
+		ret = gpiod_set_debounce(info->id_gpiod, USB_GPIO_DEB_US);
+	if (!ret && info->vbus_gpiod)
+		ret = gpiod_set_debounce(info->vbus_gpiod, USB_GPIO_DEB_US);
+	if (ret < 0)
+		info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEB_MS);
+
+	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
+
+	info->vbus = devm_regulator_get(dev, "vbus");
+	if (IS_ERR(info->vbus)) {
+		dev_err(dev, "failed to get vbus\n");
+		return PTR_ERR(info->vbus);
+	}
+
+	child = of_graph_get_endpoint_by_regs(np, -1, 0);
+	parent = of_graph_get_remote_port_parent(child);
+	info->role_sw = fwnode_usb_role_switch_get(of_fwnode_handle(parent));
+	of_node_put(child);
+	of_node_put(parent);
+	if (IS_ERR(info->role_sw)) {
+		dev_err(dev, "failed to get role switch\n");
+		return PTR_ERR(info->role_sw);
+	}
+
+	if (info->id_gpiod) {
+		info->id_irq = gpiod_to_irq(info->id_gpiod);
+		if (info->id_irq < 0) {
+			dev_err(dev, "failed to get ID IRQ\n");
+			return info->id_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
+						usb_conn_isr, USB_CONN_IRQF,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request ID IRQ\n");
+			return ret;
+		}
+	}
+
+	if (info->vbus_gpiod) {
+		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
+		if (info->vbus_irq < 0) {
+			dev_err(dev, "failed to get VBUS IRQ\n");
+			return info->vbus_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
+						usb_conn_isr, USB_CONN_IRQF,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request VBUS IRQ\n");
+			return ret;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+
+	/* Perform initial detection */
+	usb_conn_queue_dwork(info, 0);
+
+	return 0;
+}
+
+static int usb_conn_remove(struct platform_device *pdev)
+{
+	struct usb_conn_info *info = platform_get_drvdata(pdev);
+
+	cancel_delayed_work_sync(&info->dw_det);
+
+	if (info->last_role == USB_ROLE_HOST)
+		regulator_disable(info->vbus);
+
+	usb_role_switch_put(info->role_sw);
+
+	return 0;
+}
+
+static int __maybe_unused usb_conn_suspend(struct device *dev)
+{
+	struct usb_conn_info *info = dev_get_drvdata(dev);
+
+	if (info->id_gpiod)
+		disable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		disable_irq(info->vbus_irq);
+
+	pinctrl_pm_select_sleep_state(dev);
+
+	return 0;
+}
+
+static int __maybe_unused usb_conn_resume(struct device *dev)
+{
+	struct usb_conn_info *info = dev_get_drvdata(dev);
+
+	pinctrl_pm_select_default_state(dev);
+
+	if (info->id_gpiod)
+		enable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		enable_irq(info->vbus_irq);
+
+	usb_conn_queue_dwork(info, 0);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
+			 usb_conn_suspend, usb_conn_resume);
+
+#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ? &usb_conn_pm_ops : NULL)
+
+static const struct of_device_id usb_conn_dt_match[] = {
+	{ .compatible = "linux,typeb-conn-gpio", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
+
+static struct platform_driver usb_conn_driver = {
+	.probe		= usb_conn_probe,
+	.remove		= usb_conn_remove,
+	.driver		= {
+		.name	= "typeb-conn-gpio",
+		.pm	= DEV_PMS_OPS,
+		.of_match_table = usb_conn_dt_match,
+	},
+};
+
+module_platform_driver(usb_conn_driver);
+
+MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
+MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
+MODULE_LICENSE("GPL v2");

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Badhri Jagan Sridharan,
	Linus Walleij, linux-usb, linux-kernel, Biju Das,
	Matthias Brugger, Andy Shevchenko, linux-mediatek, Min Guo,
	Chunfeng Yun, Adam Thomson, linux-arm-kernel, Li Jun

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 <chunfeng.yun@mediatek.com>
---
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 | 305 ++++++++++++++++++++++++++++
 3 files changed, 317 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 000000000000..097d2ca12a12
--- /dev/null
+++ b/drivers/usb/roles/typeb-conn-gpio.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USB Type-B GPIO Connector Driver
+ *
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
+ *
+ * Some code borrowed from drivers/extcon/extcon-usb-gpio.c
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/role.h>
+
+#define USB_GPIO_DEB_MS		20	/* 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 (ret)
+		dev_err(info->dev, "failed to set role: %d\n", ret);
+
+	if (role == USB_ROLE_HOST) {
+		ret = regulator_enable(info->vbus);
+		if (ret)
+			dev_err(info->dev, "enable vbus regulator failed\n");
+	}
+
+	info->last_role = role;
+
+	dev_dbg(info->dev, "vbus regulator is %s\n",
+		regulator_is_enabled(info->vbus) ? "enabled" : "disabled");
+}
+
+static void usb_conn_queue_dwork(struct usb_conn_info *info,
+				 unsigned long delay)
+{
+	queue_delayed_work(system_power_efficient_wq, &info->dw_det, delay);
+}
+
+static irqreturn_t usb_conn_isr(int irq, void *dev_id)
+{
+	struct usb_conn_info *info = dev_id;
+
+	usb_conn_queue_dwork(info, info->debounce_jiffies);
+
+	return IRQ_HANDLED;
+}
+
+static int usb_conn_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *parent;
+	struct device_node *child;
+	struct usb_conn_info *info;
+	int ret = 0;
+
+	if (!np)
+		return -EINVAL;
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = dev;
+
+	child = of_get_child_by_name(np, "connector");
+	if (!child) {
+		dev_err(dev, "failed to find connector node\n");
+		return -ENODEV;
+	}
+
+	info->id_gpiod = devm_gpiod_get_from_of_node(
+				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
+	if (IS_ERR(info->id_gpiod)) {
+		of_node_put(child);
+		return PTR_ERR(info->id_gpiod);
+	}
+
+	info->vbus_gpiod = devm_gpiod_get_from_of_node(
+				dev, child, "vbus-gpios", 0, GPIOD_IN,
+				"vbuspin");
+	if (IS_ERR(info->vbus_gpiod)) {
+		of_node_put(child);
+		return PTR_ERR(info->vbus_gpiod);
+	}
+
+	if (!info->id_gpiod && !info->vbus_gpiod) {
+		dev_err(dev, "failed to get gpios\n");
+		return -ENODEV;
+	}
+
+	of_node_put(child);
+
+	if (info->id_gpiod)
+		ret = gpiod_set_debounce(info->id_gpiod, USB_GPIO_DEB_US);
+	if (!ret && info->vbus_gpiod)
+		ret = gpiod_set_debounce(info->vbus_gpiod, USB_GPIO_DEB_US);
+	if (ret < 0)
+		info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEB_MS);
+
+	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
+
+	info->vbus = devm_regulator_get(dev, "vbus");
+	if (IS_ERR(info->vbus)) {
+		dev_err(dev, "failed to get vbus\n");
+		return PTR_ERR(info->vbus);
+	}
+
+	child = of_graph_get_endpoint_by_regs(np, -1, 0);
+	parent = of_graph_get_remote_port_parent(child);
+	info->role_sw = fwnode_usb_role_switch_get(of_fwnode_handle(parent));
+	of_node_put(child);
+	of_node_put(parent);
+	if (IS_ERR(info->role_sw)) {
+		dev_err(dev, "failed to get role switch\n");
+		return PTR_ERR(info->role_sw);
+	}
+
+	if (info->id_gpiod) {
+		info->id_irq = gpiod_to_irq(info->id_gpiod);
+		if (info->id_irq < 0) {
+			dev_err(dev, "failed to get ID IRQ\n");
+			return info->id_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
+						usb_conn_isr, USB_CONN_IRQF,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request ID IRQ\n");
+			return ret;
+		}
+	}
+
+	if (info->vbus_gpiod) {
+		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
+		if (info->vbus_irq < 0) {
+			dev_err(dev, "failed to get VBUS IRQ\n");
+			return info->vbus_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
+						usb_conn_isr, USB_CONN_IRQF,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request VBUS IRQ\n");
+			return ret;
+		}
+	}
+
+	platform_set_drvdata(pdev, info);
+
+	/* Perform initial detection */
+	usb_conn_queue_dwork(info, 0);
+
+	return 0;
+}
+
+static int usb_conn_remove(struct platform_device *pdev)
+{
+	struct usb_conn_info *info = platform_get_drvdata(pdev);
+
+	cancel_delayed_work_sync(&info->dw_det);
+
+	if (info->last_role == USB_ROLE_HOST)
+		regulator_disable(info->vbus);
+
+	usb_role_switch_put(info->role_sw);
+
+	return 0;
+}
+
+static int __maybe_unused usb_conn_suspend(struct device *dev)
+{
+	struct usb_conn_info *info = dev_get_drvdata(dev);
+
+	if (info->id_gpiod)
+		disable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		disable_irq(info->vbus_irq);
+
+	pinctrl_pm_select_sleep_state(dev);
+
+	return 0;
+}
+
+static int __maybe_unused usb_conn_resume(struct device *dev)
+{
+	struct usb_conn_info *info = dev_get_drvdata(dev);
+
+	pinctrl_pm_select_default_state(dev);
+
+	if (info->id_gpiod)
+		enable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		enable_irq(info->vbus_irq);
+
+	usb_conn_queue_dwork(info, 0);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
+			 usb_conn_suspend, usb_conn_resume);
+
+#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ? &usb_conn_pm_ops : NULL)
+
+static const struct of_device_id usb_conn_dt_match[] = {
+	{ .compatible = "linux,typeb-conn-gpio", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
+
+static struct platform_driver usb_conn_driver = {
+	.probe		= usb_conn_probe,
+	.remove		= usb_conn_remove,
+	.driver		= {
+		.name	= "typeb-conn-gpio",
+		.pm	= DEV_PMS_OPS,
+		.of_match_table = usb_conn_dt_match,
+	},
+};
+
+module_platform_driver(usb_conn_driver);
+
+MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
+MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
+MODULE_LICENSE("GPL v2");
-- 
2.21.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 6/6] usb: mtu3: register a USB Role Switch for dual role mode
  2019-04-26  6:47 ` Chunfeng Yun
  (?)
  (?)
@ 2019-04-26  6:47   ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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 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 <chunfeng.yun@mediatek.com>
  */
 
+#include <linux/usb/role.h>
+
 #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->role_sw_used)
+		return 0;
+
+	role_sx_desc.set = ssusb_role_sw_set;
+	role_sx_desc.get = ssusb_role_sw_get;
+	role_sx_desc.fwnode = dev_fwnode(ssusb->dev);
+	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;
@@ -328,6 +371,8 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 
 	if (otg_sx->manual_drd_enabled)
 		ssusb_dr_debugfs_init(ssusb);
+	else if (otg_sx->role_sw_used)
+		ret = ssusb_role_sw_register(otg_sx);
 	else
 		ret = ssusb_extcon_register(otg_sx);
 
@@ -340,4 +385,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_dr.h b/drivers/usb/mtu3/mtu3_dr.h
index ba6fe357ce29..5e58c4dbd54a 100644
--- a/drivers/usb/mtu3/mtu3_dr.h
+++ b/drivers/usb/mtu3/mtu3_dr.h
@@ -71,7 +71,7 @@ static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb)
 #if IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE)
 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb);
 void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb);
-void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host);
+void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host);
 int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on);
 void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
 			  enum mtu3_dr_force_mode mode);
@@ -86,8 +86,8 @@ static inline int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 static inline void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
 {}
 
-static inline void
-ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) {}
+static inline void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host)
+{}
 
 static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on)
 {
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index fd0f6c5dfbc1..9c256ea3cdf5 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -299,8 +299,9 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 	otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd");
 	otg_sx->manual_drd_enabled =
 		of_property_read_bool(node, "enable-manual-drd");
+	otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch");
 
-	if (of_property_read_bool(node, "extcon")) {
+	if (!otg_sx->role_sw_used && of_property_read_bool(node, "extcon")) {
 		otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0);
 		if (IS_ERR(otg_sx->edev)) {
 			dev_err(ssusb->dev, "couldn't get extcon device\n");
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 6/6] usb: mtu3: register a USB Role Switch for dual role mode
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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 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 <chunfeng.yun@mediatek.com>
  */
 
+#include <linux/usb/role.h>
+
 #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->role_sw_used)
+		return 0;
+
+	role_sx_desc.set = ssusb_role_sw_set;
+	role_sx_desc.get = ssusb_role_sw_get;
+	role_sx_desc.fwnode = dev_fwnode(ssusb->dev);
+	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;
@@ -328,6 +371,8 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 
 	if (otg_sx->manual_drd_enabled)
 		ssusb_dr_debugfs_init(ssusb);
+	else if (otg_sx->role_sw_used)
+		ret = ssusb_role_sw_register(otg_sx);
 	else
 		ret = ssusb_extcon_register(otg_sx);
 
@@ -340,4 +385,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_dr.h b/drivers/usb/mtu3/mtu3_dr.h
index ba6fe357ce29..5e58c4dbd54a 100644
--- a/drivers/usb/mtu3/mtu3_dr.h
+++ b/drivers/usb/mtu3/mtu3_dr.h
@@ -71,7 +71,7 @@ static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb)
 #if IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE)
 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb);
 void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb);
-void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host);
+void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host);
 int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on);
 void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
 			  enum mtu3_dr_force_mode mode);
@@ -86,8 +86,8 @@ static inline int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 static inline void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
 {}
 
-static inline void
-ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) {}
+static inline void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host)
+{}
 
 static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on)
 {
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index fd0f6c5dfbc1..9c256ea3cdf5 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -299,8 +299,9 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 	otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd");
 	otg_sx->manual_drd_enabled =
 		of_property_read_bool(node, "enable-manual-drd");
+	otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch");
 
-	if (of_property_read_bool(node, "extcon")) {
+	if (!otg_sx->role_sw_used && of_property_read_bool(node, "extcon")) {
 		otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0);
 		if (IS_ERR(otg_sx->edev)) {
 			dev_err(ssusb->dev, "couldn't get extcon device\n");
-- 
2.21.0

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [v4,6/6] usb: mtu3: register a USB Role Switch for dual role mode
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Chunfeng Yun, Matthias Brugger, Adam Thomson,
	Li Jun, Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko,
	Min Guo, devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Biju Das, Linus Walleij

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 <chunfeng.yun@mediatek.com>
---
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 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 <chunfeng.yun@mediatek.com>
  */
 
+#include <linux/usb/role.h>
+
 #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->role_sw_used)
+		return 0;
+
+	role_sx_desc.set = ssusb_role_sw_set;
+	role_sx_desc.get = ssusb_role_sw_get;
+	role_sx_desc.fwnode = dev_fwnode(ssusb->dev);
+	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;
@@ -328,6 +371,8 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 
 	if (otg_sx->manual_drd_enabled)
 		ssusb_dr_debugfs_init(ssusb);
+	else if (otg_sx->role_sw_used)
+		ret = ssusb_role_sw_register(otg_sx);
 	else
 		ret = ssusb_extcon_register(otg_sx);
 
@@ -340,4 +385,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_dr.h b/drivers/usb/mtu3/mtu3_dr.h
index ba6fe357ce29..5e58c4dbd54a 100644
--- a/drivers/usb/mtu3/mtu3_dr.h
+++ b/drivers/usb/mtu3/mtu3_dr.h
@@ -71,7 +71,7 @@ static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb)
 #if IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE)
 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb);
 void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb);
-void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host);
+void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host);
 int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on);
 void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
 			  enum mtu3_dr_force_mode mode);
@@ -86,8 +86,8 @@ static inline int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 static inline void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
 {}
 
-static inline void
-ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) {}
+static inline void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host)
+{}
 
 static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on)
 {
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index fd0f6c5dfbc1..9c256ea3cdf5 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -299,8 +299,9 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 	otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd");
 	otg_sx->manual_drd_enabled =
 		of_property_read_bool(node, "enable-manual-drd");
+	otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch");
 
-	if (of_property_read_bool(node, "extcon")) {
+	if (!otg_sx->role_sw_used && of_property_read_bool(node, "extcon")) {
 		otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0);
 		if (IS_ERR(otg_sx->edev)) {
 			dev_err(ssusb->dev, "couldn't get extcon device\n");

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH v4 6/6] usb: mtu3: register a USB Role Switch for dual role mode
@ 2019-04-26  6:47   ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  6:47 UTC (permalink / raw)
  To: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Badhri Jagan Sridharan,
	Linus Walleij, linux-usb, linux-kernel, Biju Das,
	Matthias Brugger, Andy Shevchenko, linux-mediatek, Min Guo,
	Chunfeng Yun, Adam Thomson, linux-arm-kernel, Li Jun

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 <chunfeng.yun@mediatek.com>
---
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 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 <chunfeng.yun@mediatek.com>
  */
 
+#include <linux/usb/role.h>
+
 #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->role_sw_used)
+		return 0;
+
+	role_sx_desc.set = ssusb_role_sw_set;
+	role_sx_desc.get = ssusb_role_sw_get;
+	role_sx_desc.fwnode = dev_fwnode(ssusb->dev);
+	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;
@@ -328,6 +371,8 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 
 	if (otg_sx->manual_drd_enabled)
 		ssusb_dr_debugfs_init(ssusb);
+	else if (otg_sx->role_sw_used)
+		ret = ssusb_role_sw_register(otg_sx);
 	else
 		ret = ssusb_extcon_register(otg_sx);
 
@@ -340,4 +385,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_dr.h b/drivers/usb/mtu3/mtu3_dr.h
index ba6fe357ce29..5e58c4dbd54a 100644
--- a/drivers/usb/mtu3/mtu3_dr.h
+++ b/drivers/usb/mtu3/mtu3_dr.h
@@ -71,7 +71,7 @@ static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb)
 #if IS_ENABLED(CONFIG_USB_MTU3_DUAL_ROLE)
 int ssusb_otg_switch_init(struct ssusb_mtk *ssusb);
 void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb);
-void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host);
+void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host);
 int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on);
 void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
 			  enum mtu3_dr_force_mode mode);
@@ -86,8 +86,8 @@ static inline int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
 static inline void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb)
 {}
 
-static inline void
-ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) {}
+static inline void ssusb_mode_switch(struct ssusb_mtk *ssusb, int to_host)
+{}
 
 static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on)
 {
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index fd0f6c5dfbc1..9c256ea3cdf5 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -299,8 +299,9 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
 	otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd");
 	otg_sx->manual_drd_enabled =
 		of_property_read_bool(node, "enable-manual-drd");
+	otg_sx->role_sw_used = of_property_read_bool(node, "usb-role-switch");
 
-	if (of_property_read_bool(node, "extcon")) {
+	if (!otg_sx->role_sw_used && of_property_read_bool(node, "extcon")) {
 		otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0);
 		if (IS_ERR(otg_sx->edev)) {
 			dev_err(ssusb->dev, "couldn't get extcon device\n");
-- 
2.21.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
  2019-04-26  6:47   ` [PATCH v4 4/6] " Chunfeng Yun
  (?)
  (?)
@ 2019-04-26  7:02     ` Biju Das
  -1 siblings, 0 replies; 69+ messages in thread
From: Biju Das @ 2019-04-26  7:02 UTC (permalink / raw)
  To: Chunfeng Yun, Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Matthias Brugger, Adam Thomson, Li Jun,
	Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko, Min Guo,
	devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Linus Walleij

Hi Chunfeng Yun,

Thanks for the patch.

> Subject: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
> 
> Add fwnode_usb_role_switch_get() to make easier to get usb_role_switch
> by fwnode which register it.
> It's useful when there is not device_connection registered between two
> drivers and only knows the fwnode which register usb_role_switch.
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Tested-by: Biju Das <biju.das@bp.renesas.com>
> ---
> 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 | 25 +++++++++++++++++++++++++
> include/linux/usb/role.h  |  8 ++++++++
>  2 files changed, 33 insertions(+)
> 
> diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index
> f45d8df5cfb8..994fcb979795 100644
> --- a/drivers/usb/roles/class.c
> +++ b/drivers/usb/roles/class.c
> @@ -12,6 +12,7 @@
>  #include <linux/device.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
> +#include <linux/of.h>

Is it required?

>  #include <linux/slab.h>
> 
>  static struct class *role_class;
> @@ -135,6 +136,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 *c(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


^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
@ 2019-04-26  7:02     ` Biju Das
  0 siblings, 0 replies; 69+ messages in thread
From: Biju Das @ 2019-04-26  7:02 UTC (permalink / raw)
  To: Chunfeng Yun, Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Linus Walleij,
	linux-usb, linux-kernel, Badhri Jagan Sridharan, Andy Shevchenko,
	linux-mediatek, Min Guo, Matthias Brugger, Adam Thomson,
	linux-arm-kernel, Li Jun

Hi Chunfeng Yun,

Thanks for the patch.

> Subject: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
> 
> Add fwnode_usb_role_switch_get() to make easier to get usb_role_switch
> by fwnode which register it.
> It's useful when there is not device_connection registered between two
> drivers and only knows the fwnode which register usb_role_switch.
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Tested-by: Biju Das <biju.das@bp.renesas.com>
> ---
> 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 | 25 +++++++++++++++++++++++++
> include/linux/usb/role.h  |  8 ++++++++
>  2 files changed, 33 insertions(+)
> 
> diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index
> f45d8df5cfb8..994fcb979795 100644
> --- a/drivers/usb/roles/class.c
> +++ b/drivers/usb/roles/class.c
> @@ -12,6 +12,7 @@
>  #include <linux/device.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
> +#include <linux/of.h>

Is it required?

>  #include <linux/slab.h>
> 
>  static struct class *role_class;
> @@ -135,6 +136,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 *c(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

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,4/6] usb: roles: add API to get usb_role_switch by node
@ 2019-04-26  7:02     ` Biju Das
  0 siblings, 0 replies; 69+ messages in thread
From: Biju Das @ 2019-04-26  7:02 UTC (permalink / raw)
  To: Chunfeng Yun, Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Matthias Brugger, Adam Thomson, Li Jun,
	Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko, Min Guo,
	devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Linus Walleij

Hi Chunfeng Yun,

Thanks for the patch.

> Subject: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
> 
> Add fwnode_usb_role_switch_get() to make easier to get usb_role_switch
> by fwnode which register it.
> It's useful when there is not device_connection registered between two
> drivers and only knows the fwnode which register usb_role_switch.
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Tested-by: Biju Das <biju.das@bp.renesas.com>
> ---
> 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 | 25 +++++++++++++++++++++++++
> include/linux/usb/role.h  |  8 ++++++++
>  2 files changed, 33 insertions(+)
> 
> diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index
> f45d8df5cfb8..994fcb979795 100644
> --- a/drivers/usb/roles/class.c
> +++ b/drivers/usb/roles/class.c
> @@ -12,6 +12,7 @@
>  #include <linux/device.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
> +#include <linux/of.h>

Is it required?

>  #include <linux/slab.h>
> 
>  static struct class *role_class;
> @@ -135,6 +136,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 *c(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

^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
@ 2019-04-26  7:02     ` Biju Das
  0 siblings, 0 replies; 69+ messages in thread
From: Biju Das @ 2019-04-26  7:02 UTC (permalink / raw)
  To: Chunfeng Yun, Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Linus Walleij,
	linux-usb, linux-kernel, Badhri Jagan Sridharan, Andy Shevchenko,
	linux-mediatek, Min Guo, Matthias Brugger, Adam Thomson,
	linux-arm-kernel, Li Jun

Hi Chunfeng Yun,

Thanks for the patch.

> Subject: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
> 
> Add fwnode_usb_role_switch_get() to make easier to get usb_role_switch
> by fwnode which register it.
> It's useful when there is not device_connection registered between two
> drivers and only knows the fwnode which register usb_role_switch.
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Tested-by: Biju Das <biju.das@bp.renesas.com>
> ---
> 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 | 25 +++++++++++++++++++++++++
> include/linux/usb/role.h  |  8 ++++++++
>  2 files changed, 33 insertions(+)
> 
> diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index
> f45d8df5cfb8..994fcb979795 100644
> --- a/drivers/usb/roles/class.c
> +++ b/drivers/usb/roles/class.c
> @@ -12,6 +12,7 @@
>  #include <linux/device.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
> +#include <linux/of.h>

Is it required?

>  #include <linux/slab.h>
> 
>  static struct class *role_class;
> @@ -135,6 +136,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 *c(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


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
  2019-04-26  7:02     ` [PATCH v4 4/6] " Biju Das
  (?)
  (?)
@ 2019-04-26  7:16       ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  7:16 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Linus Walleij

Hi Biju,
On Fri, 2019-04-26 at 07:02 +0000, Biju Das wrote:
> Hi Chunfeng Yun,
> 
> Thanks for the patch.
> 
> > Subject: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
> > 
> > Add fwnode_usb_role_switch_get() to make easier to get usb_role_switch
> > by fwnode which register it.
> > It's useful when there is not device_connection registered between two
> > drivers and only knows the fwnode which register usb_role_switch.
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> Tested-by: Biju Das <biju.das@bp.renesas.com>
> > ---
> > 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 | 25 +++++++++++++++++++++++++
> > include/linux/usb/role.h  |  8 ++++++++
> >  2 files changed, 33 insertions(+)
> > 
> > diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index
> > f45d8df5cfb8..994fcb979795 100644
> > --- a/drivers/usb/roles/class.c
> > +++ b/drivers/usb/roles/class.c
> > @@ -12,6 +12,7 @@
> >  #include <linux/device.h>
> >  #include <linux/module.h>
> >  #include <linux/mutex.h>
> > +#include <linux/of.h>
> 
> Is it required?
Forgot to remove it after using fwnode instead of node, will remove it
in next version

Thanks a lot

> 
> >  #include <linux/slab.h>
> > 
> >  static struct class *role_class;
> > @@ -135,6 +136,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 *c(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
> 



^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
@ 2019-04-26  7:16       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  7:16 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek@lists.infradead.org

Hi Biju,
On Fri, 2019-04-26 at 07:02 +0000, Biju Das wrote:
> Hi Chunfeng Yun,
> 
> Thanks for the patch.
> 
> > Subject: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
> > 
> > Add fwnode_usb_role_switch_get() to make easier to get usb_role_switch
> > by fwnode which register it.
> > It's useful when there is not device_connection registered between two
> > drivers and only knows the fwnode which register usb_role_switch.
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> Tested-by: Biju Das <biju.das@bp.renesas.com>
> > ---
> > 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 | 25 +++++++++++++++++++++++++
> > include/linux/usb/role.h  |  8 ++++++++
> >  2 files changed, 33 insertions(+)
> > 
> > diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index
> > f45d8df5cfb8..994fcb979795 100644
> > --- a/drivers/usb/roles/class.c
> > +++ b/drivers/usb/roles/class.c
> > @@ -12,6 +12,7 @@
> >  #include <linux/device.h>
> >  #include <linux/module.h>
> >  #include <linux/mutex.h>
> > +#include <linux/of.h>
> 
> Is it required?
Forgot to remove it after using fwnode instead of node, will remove it
in next version

Thanks a lot

> 
> >  #include <linux/slab.h>
> > 
> >  static struct class *role_class;
> > @@ -135,6 +136,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 *c(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
> 

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,4/6] usb: roles: add API to get usb_role_switch by node
@ 2019-04-26  7:16       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  7:16 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Linus Walleij

Hi Biju,
On Fri, 2019-04-26 at 07:02 +0000, Biju Das wrote:
> Hi Chunfeng Yun,
> 
> Thanks for the patch.
> 
> > Subject: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
> > 
> > Add fwnode_usb_role_switch_get() to make easier to get usb_role_switch
> > by fwnode which register it.
> > It's useful when there is not device_connection registered between two
> > drivers and only knows the fwnode which register usb_role_switch.
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> Tested-by: Biju Das <biju.das@bp.renesas.com>
> > ---
> > 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 | 25 +++++++++++++++++++++++++
> > include/linux/usb/role.h  |  8 ++++++++
> >  2 files changed, 33 insertions(+)
> > 
> > diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index
> > f45d8df5cfb8..994fcb979795 100644
> > --- a/drivers/usb/roles/class.c
> > +++ b/drivers/usb/roles/class.c
> > @@ -12,6 +12,7 @@
> >  #include <linux/device.h>
> >  #include <linux/module.h>
> >  #include <linux/mutex.h>
> > +#include <linux/of.h>
> 
> Is it required?
Forgot to remove it after using fwnode instead of node, will remove it
in next version

Thanks a lot

> 
> >  #include <linux/slab.h>
> > 
> >  static struct class *role_class;
> > @@ -135,6 +136,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 *c(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
>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
@ 2019-04-26  7:16       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-26  7:16 UTC (permalink / raw)
  To: Biju Das
  Cc: Mark Rutland, devicetree, Heikki Krogerus, Hans de Goede,
	Greg Kroah-Hartman, Linus Walleij, linux-usb, linux-kernel,
	Badhri Jagan Sridharan, Andy Shevchenko, Rob Herring,
	linux-mediatek, Min Guo, Matthias Brugger, Adam Thomson,
	linux-arm-kernel, Li Jun

Hi Biju,
On Fri, 2019-04-26 at 07:02 +0000, Biju Das wrote:
> Hi Chunfeng Yun,
> 
> Thanks for the patch.
> 
> > Subject: [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node
> > 
> > Add fwnode_usb_role_switch_get() to make easier to get usb_role_switch
> > by fwnode which register it.
> > It's useful when there is not device_connection registered between two
> > drivers and only knows the fwnode which register usb_role_switch.
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> Tested-by: Biju Das <biju.das@bp.renesas.com>
> > ---
> > 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 | 25 +++++++++++++++++++++++++
> > include/linux/usb/role.h  |  8 ++++++++
> >  2 files changed, 33 insertions(+)
> > 
> > diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index
> > f45d8df5cfb8..994fcb979795 100644
> > --- a/drivers/usb/roles/class.c
> > +++ b/drivers/usb/roles/class.c
> > @@ -12,6 +12,7 @@
> >  #include <linux/device.h>
> >  #include <linux/module.h>
> >  #include <linux/mutex.h>
> > +#include <linux/of.h>
> 
> Is it required?
Forgot to remove it after using fwnode instead of node, will remove it
in next version

Thanks a lot

> 
> >  #include <linux/slab.h>
> > 
> >  static struct class *role_class;
> > @@ -135,6 +136,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 *c(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
> 



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
  2019-04-26  6:47   ` [PATCH v4 5/6] " Chunfeng Yun
  (?)
  (?)
@ 2019-04-26  9:22     ` Biju Das
  -1 siblings, 0 replies; 69+ messages in thread
From: Biju Das @ 2019-04-26  9:22 UTC (permalink / raw)
  To: Chunfeng Yun, Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Matthias Brugger, Adam Thomson, Li Jun,
	Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko, Min Guo,
	devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Linus Walleij

Hi Chunfeng Yun,

Thanks for the patch.

> Subject: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
> 
> Due to the requirement of usb-connector.txt binding, the old way using
> extcon to support USB Dual-Role switch is now deprecated when use Type-B
> connector.
> This patch introduces a driver of Type-B connector which typically uses an
> input GPIO to detect USB ID pin, and try to replace the function provided by
> extcon-usb-gpio driver
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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 | 305
> ++++++++++++++++++++++++++++
>  3 files changed, 317 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 000000000000..097d2ca12a12
> --- /dev/null
> +++ b/drivers/usb/roles/typeb-conn-gpio.c
> @@ -0,0 +1,305 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * USB Type-B GPIO Connector Driver
> + *
> + * Copyright (C) 2019 MediaTek Inc.
> + *
> + * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
> + *
> + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c  */
> +
> +#include <linux/device.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_graph.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/usb/role.h>
> +
> +#define USB_GPIO_DEB_MS		20	/* 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 (ret)
> +		dev_err(info->dev, "failed to set role: %d\n", ret);
> +
> +	if (role == USB_ROLE_HOST) {
> +		ret = regulator_enable(info->vbus);
> +		if (ret)
> +			dev_err(info->dev, "enable vbus regulator failed\n");
> +	}
> +
> +	info->last_role = role;
> +
> +	dev_dbg(info->dev, "vbus regulator is %s\n",
> +		regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); }
> +
> +static void usb_conn_queue_dwork(struct usb_conn_info *info,
> +				 unsigned long delay)
> +{
> +	queue_delayed_work(system_power_efficient_wq, &info-
> >dw_det, delay); }
> +
> +static irqreturn_t usb_conn_isr(int irq, void *dev_id) {
> +	struct usb_conn_info *info = dev_id;
> +
> +	usb_conn_queue_dwork(info, info->debounce_jiffies);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int usb_conn_probe(struct platform_device *pdev) {
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct device_node *parent;
> +	struct device_node *child;
> +	struct usb_conn_info *info;
> +	int ret = 0;
> +
> +	if (!np)
> +		return -EINVAL;
> +
> +	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	info->dev = dev;
> +
> +	child = of_get_child_by_name(np, "connector");
> +	if (!child) {
> +		dev_err(dev, "failed to find connector node\n");
> +		return -ENODEV;
> +	}
> +
> +	info->id_gpiod = devm_gpiod_get_from_of_node(
> +				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
> +	if (IS_ERR(info->id_gpiod)) {
> +		of_node_put(child);
> +		return PTR_ERR(info->id_gpiod);
> +	}
> +
> +	info->vbus_gpiod = devm_gpiod_get_from_of_node(
> +				dev, child, "vbus-gpios", 0, GPIOD_IN,
> +				"vbuspin");
> +	if (IS_ERR(info->vbus_gpiod)) {
> +		of_node_put(child);
> +		return PTR_ERR(info->vbus_gpiod);
> +	}
> +
> +	if (!info->id_gpiod && !info->vbus_gpiod) {
> +		dev_err(dev, "failed to get gpios\n");
> +		return -ENODEV;
> +	}
> +
> +	of_node_put(child);
> +
> +	if (info->id_gpiod)
> +		ret = gpiod_set_debounce(info->id_gpiod,
> USB_GPIO_DEB_US);
> +	if (!ret && info->vbus_gpiod)
> +		ret = gpiod_set_debounce(info->vbus_gpiod,
> USB_GPIO_DEB_US);
> +	if (ret < 0)
> +		info->debounce_jiffies =
> msecs_to_jiffies(USB_GPIO_DEB_MS);
> +
> +	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
> +
> +	info->vbus = devm_regulator_get(dev, "vbus");
> +	if (IS_ERR(info->vbus)) {
> +		dev_err(dev, "failed to get vbus\n");
> +		return PTR_ERR(info->vbus);
> +	}
> +
> +	child = of_graph_get_endpoint_by_regs(np, -1, 0);
> +	parent = of_graph_get_remote_port_parent(child);
> +	info->role_sw =
> fwnode_usb_role_switch_get(of_fwnode_handle(parent));
> +	of_node_put(child);
> +	of_node_put(parent);
> +	if (IS_ERR(info->role_sw)) {
> +		dev_err(dev, "failed to get role switch\n");
> +		return PTR_ERR(info->role_sw);
> +	}
> +
> +	if (info->id_gpiod) {
> +		info->id_irq = gpiod_to_irq(info->id_gpiod);
> +		if (info->id_irq < 0) {
> +			dev_err(dev, "failed to get ID IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return info->id_irq;
> +		}
> +
> +		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
> +						usb_conn_isr,
> USB_CONN_IRQF,
> +						pdev->name, info);
> +		if (ret < 0) {
> +			dev_err(dev, "failed to request ID IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return ret;
> +		}
> +	}
> +
> +	if (info->vbus_gpiod) {
> +		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
> +		if (info->vbus_irq < 0) {
> +			dev_err(dev, "failed to get VBUS IRQ\n");
May be usb_role_switch_put(info->role_sw);
> +			return info->vbus_irq;
> +		}
> +
> +		ret = devm_request_threaded_irq(dev, info->vbus_irq,
> NULL,
> +						usb_conn_isr,
> USB_CONN_IRQF,
> +						pdev->name, info);
> +		if (ret < 0) {
> +			dev_err(dev, "failed to request VBUS IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return ret;
> +		}
> +	}
> +
> +	platform_set_drvdata(pdev, info);
> +
> +	/* Perform initial detection */
> +	usb_conn_queue_dwork(info, 0);
> +
> +	return 0;
> +}
> +
> +static int usb_conn_remove(struct platform_device *pdev) {
> +	struct usb_conn_info *info = platform_get_drvdata(pdev);
> +
> +	cancel_delayed_work_sync(&info->dw_det);
> +
> +	if (info->last_role == USB_ROLE_HOST)
> +		regulator_disable(info->vbus);
> +
> +	usb_role_switch_put(info->role_sw);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused usb_conn_suspend(struct device *dev) {
> +	struct usb_conn_info *info = dev_get_drvdata(dev);
> +
> +	if (info->id_gpiod)
> +		disable_irq(info->id_irq);
> +	if (info->vbus_gpiod)
> +		disable_irq(info->vbus_irq);
> +
> +	pinctrl_pm_select_sleep_state(dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused usb_conn_resume(struct device *dev) {
> +	struct usb_conn_info *info = dev_get_drvdata(dev);
> +
> +	pinctrl_pm_select_default_state(dev);
> +
> +	if (info->id_gpiod)
> +		enable_irq(info->id_irq);
> +	if (info->vbus_gpiod)
> +		enable_irq(info->vbus_irq);
> +
> +	usb_conn_queue_dwork(info, 0);
> +
> +	return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
> +			 usb_conn_suspend, usb_conn_resume);
> +
> +#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ?
> &usb_conn_pm_ops :
> +NULL)
> +
> +static const struct of_device_id usb_conn_dt_match[] = {
> +	{ .compatible = "linux,typeb-conn-gpio", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
> +
> +static struct platform_driver usb_conn_driver = {
> +	.probe		= usb_conn_probe,
> +	.remove		= usb_conn_remove,
> +	.driver		= {
> +		.name	= "typeb-conn-gpio",
> +		.pm	= DEV_PMS_OPS,
> +		.of_match_table = usb_conn_dt_match,
> +	},
> +};
> +
> +module_platform_driver(usb_conn_driver);
> +
> +MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
> +MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.21.0


^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
@ 2019-04-26  9:22     ` Biju Das
  0 siblings, 0 replies; 69+ messages in thread
From: Biju Das @ 2019-04-26  9:22 UTC (permalink / raw)
  To: Chunfeng Yun, Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Matthias Brugger, Adam Thomson, Li Jun,
	Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko, Min Guo,
	devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Linus Walleij

Hi Chunfeng Yun,

Thanks for the patch.

> Subject: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
> 
> Due to the requirement of usb-connector.txt binding, the old way using
> extcon to support USB Dual-Role switch is now deprecated when use Type-B
> connector.
> This patch introduces a driver of Type-B connector which typically uses an
> input GPIO to detect USB ID pin, and try to replace the function provided by
> extcon-usb-gpio driver
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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 | 305
> ++++++++++++++++++++++++++++
>  3 files changed, 317 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 000000000000..097d2ca12a12
> --- /dev/null
> +++ b/drivers/usb/roles/typeb-conn-gpio.c
> @@ -0,0 +1,305 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * USB Type-B GPIO Connector Driver
> + *
> + * Copyright (C) 2019 MediaTek Inc.
> + *
> + * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
> + *
> + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c  */
> +
> +#include <linux/device.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_graph.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/usb/role.h>
> +
> +#define USB_GPIO_DEB_MS		20	/* 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 (ret)
> +		dev_err(info->dev, "failed to set role: %d\n", ret);
> +
> +	if (role == USB_ROLE_HOST) {
> +		ret = regulator_enable(info->vbus);
> +		if (ret)
> +			dev_err(info->dev, "enable vbus regulator failed\n");
> +	}
> +
> +	info->last_role = role;
> +
> +	dev_dbg(info->dev, "vbus regulator is %s\n",
> +		regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); }
> +
> +static void usb_conn_queue_dwork(struct usb_conn_info *info,
> +				 unsigned long delay)
> +{
> +	queue_delayed_work(system_power_efficient_wq, &info-
> >dw_det, delay); }
> +
> +static irqreturn_t usb_conn_isr(int irq, void *dev_id) {
> +	struct usb_conn_info *info = dev_id;
> +
> +	usb_conn_queue_dwork(info, info->debounce_jiffies);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int usb_conn_probe(struct platform_device *pdev) {
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct device_node *parent;
> +	struct device_node *child;
> +	struct usb_conn_info *info;
> +	int ret = 0;
> +
> +	if (!np)
> +		return -EINVAL;
> +
> +	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	info->dev = dev;
> +
> +	child = of_get_child_by_name(np, "connector");
> +	if (!child) {
> +		dev_err(dev, "failed to find connector node\n");
> +		return -ENODEV;
> +	}
> +
> +	info->id_gpiod = devm_gpiod_get_from_of_node(
> +				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
> +	if (IS_ERR(info->id_gpiod)) {
> +		of_node_put(child);
> +		return PTR_ERR(info->id_gpiod);
> +	}
> +
> +	info->vbus_gpiod = devm_gpiod_get_from_of_node(
> +				dev, child, "vbus-gpios", 0, GPIOD_IN,
> +				"vbuspin");
> +	if (IS_ERR(info->vbus_gpiod)) {
> +		of_node_put(child);
> +		return PTR_ERR(info->vbus_gpiod);
> +	}
> +
> +	if (!info->id_gpiod && !info->vbus_gpiod) {
> +		dev_err(dev, "failed to get gpios\n");
> +		return -ENODEV;
> +	}
> +
> +	of_node_put(child);
> +
> +	if (info->id_gpiod)
> +		ret = gpiod_set_debounce(info->id_gpiod,
> USB_GPIO_DEB_US);
> +	if (!ret && info->vbus_gpiod)
> +		ret = gpiod_set_debounce(info->vbus_gpiod,
> USB_GPIO_DEB_US);
> +	if (ret < 0)
> +		info->debounce_jiffies =
> msecs_to_jiffies(USB_GPIO_DEB_MS);
> +
> +	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
> +
> +	info->vbus = devm_regulator_get(dev, "vbus");
> +	if (IS_ERR(info->vbus)) {
> +		dev_err(dev, "failed to get vbus\n");
> +		return PTR_ERR(info->vbus);
> +	}
> +
> +	child = of_graph_get_endpoint_by_regs(np, -1, 0);
> +	parent = of_graph_get_remote_port_parent(child);
> +	info->role_sw =
> fwnode_usb_role_switch_get(of_fwnode_handle(parent));
> +	of_node_put(child);
> +	of_node_put(parent);
> +	if (IS_ERR(info->role_sw)) {
> +		dev_err(dev, "failed to get role switch\n");
> +		return PTR_ERR(info->role_sw);
> +	}
> +
> +	if (info->id_gpiod) {
> +		info->id_irq = gpiod_to_irq(info->id_gpiod);
> +		if (info->id_irq < 0) {
> +			dev_err(dev, "failed to get ID IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return info->id_irq;
> +		}
> +
> +		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
> +						usb_conn_isr,
> USB_CONN_IRQF,
> +						pdev->name, info);
> +		if (ret < 0) {
> +			dev_err(dev, "failed to request ID IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return ret;
> +		}
> +	}
> +
> +	if (info->vbus_gpiod) {
> +		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
> +		if (info->vbus_irq < 0) {
> +			dev_err(dev, "failed to get VBUS IRQ\n");
May be usb_role_switch_put(info->role_sw);
> +			return info->vbus_irq;
> +		}
> +
> +		ret = devm_request_threaded_irq(dev, info->vbus_irq,
> NULL,
> +						usb_conn_isr,
> USB_CONN_IRQF,
> +						pdev->name, info);
> +		if (ret < 0) {
> +			dev_err(dev, "failed to request VBUS IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return ret;
> +		}
> +	}
> +
> +	platform_set_drvdata(pdev, info);
> +
> +	/* Perform initial detection */
> +	usb_conn_queue_dwork(info, 0);
> +
> +	return 0;
> +}
> +
> +static int usb_conn_remove(struct platform_device *pdev) {
> +	struct usb_conn_info *info = platform_get_drvdata(pdev);
> +
> +	cancel_delayed_work_sync(&info->dw_det);
> +
> +	if (info->last_role == USB_ROLE_HOST)
> +		regulator_disable(info->vbus);
> +
> +	usb_role_switch_put(info->role_sw);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused usb_conn_suspend(struct device *dev) {
> +	struct usb_conn_info *info = dev_get_drvdata(dev);
> +
> +	if (info->id_gpiod)
> +		disable_irq(info->id_irq);
> +	if (info->vbus_gpiod)
> +		disable_irq(info->vbus_irq);
> +
> +	pinctrl_pm_select_sleep_state(dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused usb_conn_resume(struct device *dev) {
> +	struct usb_conn_info *info = dev_get_drvdata(dev);
> +
> +	pinctrl_pm_select_default_state(dev);
> +
> +	if (info->id_gpiod)
> +		enable_irq(info->id_irq);
> +	if (info->vbus_gpiod)
> +		enable_irq(info->vbus_irq);
> +
> +	usb_conn_queue_dwork(info, 0);
> +
> +	return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
> +			 usb_conn_suspend, usb_conn_resume);
> +
> +#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ?
> &usb_conn_pm_ops :
> +NULL)
> +
> +static const struct of_device_id usb_conn_dt_match[] = {
> +	{ .compatible = "linux,typeb-conn-gpio", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
> +
> +static struct platform_driver usb_conn_driver = {
> +	.probe		= usb_conn_probe,
> +	.remove		= usb_conn_remove,
> +	.driver		= {
> +		.name	= "typeb-conn-gpio",
> +		.pm	= DEV_PMS_OPS,
> +		.of_match_table = usb_conn_dt_match,
> +	},
> +};
> +
> +module_platform_driver(usb_conn_driver);
> +
> +MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
> +MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.21.0

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,5/6] usb: roles: add USB Type-B GPIO connector driver
@ 2019-04-26  9:22     ` Biju Das
  0 siblings, 0 replies; 69+ messages in thread
From: Biju Das @ 2019-04-26  9:22 UTC (permalink / raw)
  To: Chunfeng Yun, Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, Matthias Brugger, Adam Thomson, Li Jun,
	Badhri Jagan Sridharan, Hans de Goede, Andy Shevchenko, Min Guo,
	devicetree, linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek, Linus Walleij

Hi Chunfeng Yun,

Thanks for the patch.

> Subject: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
> 
> Due to the requirement of usb-connector.txt binding, the old way using
> extcon to support USB Dual-Role switch is now deprecated when use Type-B
> connector.
> This patch introduces a driver of Type-B connector which typically uses an
> input GPIO to detect USB ID pin, and try to replace the function provided by
> extcon-usb-gpio driver
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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 | 305
> ++++++++++++++++++++++++++++
>  3 files changed, 317 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 000000000000..097d2ca12a12
> --- /dev/null
> +++ b/drivers/usb/roles/typeb-conn-gpio.c
> @@ -0,0 +1,305 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * USB Type-B GPIO Connector Driver
> + *
> + * Copyright (C) 2019 MediaTek Inc.
> + *
> + * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
> + *
> + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c  */
> +
> +#include <linux/device.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_graph.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/usb/role.h>
> +
> +#define USB_GPIO_DEB_MS		20	/* 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 (ret)
> +		dev_err(info->dev, "failed to set role: %d\n", ret);
> +
> +	if (role == USB_ROLE_HOST) {
> +		ret = regulator_enable(info->vbus);
> +		if (ret)
> +			dev_err(info->dev, "enable vbus regulator failed\n");
> +	}
> +
> +	info->last_role = role;
> +
> +	dev_dbg(info->dev, "vbus regulator is %s\n",
> +		regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); }
> +
> +static void usb_conn_queue_dwork(struct usb_conn_info *info,
> +				 unsigned long delay)
> +{
> +	queue_delayed_work(system_power_efficient_wq, &info-
> >dw_det, delay); }
> +
> +static irqreturn_t usb_conn_isr(int irq, void *dev_id) {
> +	struct usb_conn_info *info = dev_id;
> +
> +	usb_conn_queue_dwork(info, info->debounce_jiffies);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int usb_conn_probe(struct platform_device *pdev) {
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct device_node *parent;
> +	struct device_node *child;
> +	struct usb_conn_info *info;
> +	int ret = 0;
> +
> +	if (!np)
> +		return -EINVAL;
> +
> +	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	info->dev = dev;
> +
> +	child = of_get_child_by_name(np, "connector");
> +	if (!child) {
> +		dev_err(dev, "failed to find connector node\n");
> +		return -ENODEV;
> +	}
> +
> +	info->id_gpiod = devm_gpiod_get_from_of_node(
> +				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
> +	if (IS_ERR(info->id_gpiod)) {
> +		of_node_put(child);
> +		return PTR_ERR(info->id_gpiod);
> +	}
> +
> +	info->vbus_gpiod = devm_gpiod_get_from_of_node(
> +				dev, child, "vbus-gpios", 0, GPIOD_IN,
> +				"vbuspin");
> +	if (IS_ERR(info->vbus_gpiod)) {
> +		of_node_put(child);
> +		return PTR_ERR(info->vbus_gpiod);
> +	}
> +
> +	if (!info->id_gpiod && !info->vbus_gpiod) {
> +		dev_err(dev, "failed to get gpios\n");
> +		return -ENODEV;
> +	}
> +
> +	of_node_put(child);
> +
> +	if (info->id_gpiod)
> +		ret = gpiod_set_debounce(info->id_gpiod,
> USB_GPIO_DEB_US);
> +	if (!ret && info->vbus_gpiod)
> +		ret = gpiod_set_debounce(info->vbus_gpiod,
> USB_GPIO_DEB_US);
> +	if (ret < 0)
> +		info->debounce_jiffies =
> msecs_to_jiffies(USB_GPIO_DEB_MS);
> +
> +	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
> +
> +	info->vbus = devm_regulator_get(dev, "vbus");
> +	if (IS_ERR(info->vbus)) {
> +		dev_err(dev, "failed to get vbus\n");
> +		return PTR_ERR(info->vbus);
> +	}
> +
> +	child = of_graph_get_endpoint_by_regs(np, -1, 0);
> +	parent = of_graph_get_remote_port_parent(child);
> +	info->role_sw =
> fwnode_usb_role_switch_get(of_fwnode_handle(parent));
> +	of_node_put(child);
> +	of_node_put(parent);
> +	if (IS_ERR(info->role_sw)) {
> +		dev_err(dev, "failed to get role switch\n");
> +		return PTR_ERR(info->role_sw);
> +	}
> +
> +	if (info->id_gpiod) {
> +		info->id_irq = gpiod_to_irq(info->id_gpiod);
> +		if (info->id_irq < 0) {
> +			dev_err(dev, "failed to get ID IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return info->id_irq;
> +		}
> +
> +		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
> +						usb_conn_isr,
> USB_CONN_IRQF,
> +						pdev->name, info);
> +		if (ret < 0) {
> +			dev_err(dev, "failed to request ID IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return ret;
> +		}
> +	}
> +
> +	if (info->vbus_gpiod) {
> +		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
> +		if (info->vbus_irq < 0) {
> +			dev_err(dev, "failed to get VBUS IRQ\n");
May be usb_role_switch_put(info->role_sw);
> +			return info->vbus_irq;
> +		}
> +
> +		ret = devm_request_threaded_irq(dev, info->vbus_irq,
> NULL,
> +						usb_conn_isr,
> USB_CONN_IRQF,
> +						pdev->name, info);
> +		if (ret < 0) {
> +			dev_err(dev, "failed to request VBUS IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return ret;
> +		}
> +	}
> +
> +	platform_set_drvdata(pdev, info);
> +
> +	/* Perform initial detection */
> +	usb_conn_queue_dwork(info, 0);
> +
> +	return 0;
> +}
> +
> +static int usb_conn_remove(struct platform_device *pdev) {
> +	struct usb_conn_info *info = platform_get_drvdata(pdev);
> +
> +	cancel_delayed_work_sync(&info->dw_det);
> +
> +	if (info->last_role == USB_ROLE_HOST)
> +		regulator_disable(info->vbus);
> +
> +	usb_role_switch_put(info->role_sw);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused usb_conn_suspend(struct device *dev) {
> +	struct usb_conn_info *info = dev_get_drvdata(dev);
> +
> +	if (info->id_gpiod)
> +		disable_irq(info->id_irq);
> +	if (info->vbus_gpiod)
> +		disable_irq(info->vbus_irq);
> +
> +	pinctrl_pm_select_sleep_state(dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused usb_conn_resume(struct device *dev) {
> +	struct usb_conn_info *info = dev_get_drvdata(dev);
> +
> +	pinctrl_pm_select_default_state(dev);
> +
> +	if (info->id_gpiod)
> +		enable_irq(info->id_irq);
> +	if (info->vbus_gpiod)
> +		enable_irq(info->vbus_irq);
> +
> +	usb_conn_queue_dwork(info, 0);
> +
> +	return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
> +			 usb_conn_suspend, usb_conn_resume);
> +
> +#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ?
> &usb_conn_pm_ops :
> +NULL)
> +
> +static const struct of_device_id usb_conn_dt_match[] = {
> +	{ .compatible = "linux,typeb-conn-gpio", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
> +
> +static struct platform_driver usb_conn_driver = {
> +	.probe		= usb_conn_probe,
> +	.remove		= usb_conn_remove,
> +	.driver		= {
> +		.name	= "typeb-conn-gpio",
> +		.pm	= DEV_PMS_OPS,
> +		.of_match_table = usb_conn_dt_match,
> +	},
> +};
> +
> +module_platform_driver(usb_conn_driver);
> +
> +MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
> +MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.21.0

^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
@ 2019-04-26  9:22     ` Biju Das
  0 siblings, 0 replies; 69+ messages in thread
From: Biju Das @ 2019-04-26  9:22 UTC (permalink / raw)
  To: Chunfeng Yun, Rob Herring, Greg Kroah-Hartman, Heikki Krogerus
  Cc: Mark Rutland, devicetree, Hans de Goede, Linus Walleij,
	linux-usb, linux-kernel, Badhri Jagan Sridharan, Andy Shevchenko,
	linux-mediatek, Min Guo, Matthias Brugger, Adam Thomson,
	linux-arm-kernel, Li Jun

Hi Chunfeng Yun,

Thanks for the patch.

> Subject: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
> 
> Due to the requirement of usb-connector.txt binding, the old way using
> extcon to support USB Dual-Role switch is now deprecated when use Type-B
> connector.
> This patch introduces a driver of Type-B connector which typically uses an
> input GPIO to detect USB ID pin, and try to replace the function provided by
> extcon-usb-gpio driver
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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 | 305
> ++++++++++++++++++++++++++++
>  3 files changed, 317 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 000000000000..097d2ca12a12
> --- /dev/null
> +++ b/drivers/usb/roles/typeb-conn-gpio.c
> @@ -0,0 +1,305 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * USB Type-B GPIO Connector Driver
> + *
> + * Copyright (C) 2019 MediaTek Inc.
> + *
> + * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
> + *
> + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c  */
> +
> +#include <linux/device.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_graph.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/usb/role.h>
> +
> +#define USB_GPIO_DEB_MS		20	/* 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 (ret)
> +		dev_err(info->dev, "failed to set role: %d\n", ret);
> +
> +	if (role == USB_ROLE_HOST) {
> +		ret = regulator_enable(info->vbus);
> +		if (ret)
> +			dev_err(info->dev, "enable vbus regulator failed\n");
> +	}
> +
> +	info->last_role = role;
> +
> +	dev_dbg(info->dev, "vbus regulator is %s\n",
> +		regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); }
> +
> +static void usb_conn_queue_dwork(struct usb_conn_info *info,
> +				 unsigned long delay)
> +{
> +	queue_delayed_work(system_power_efficient_wq, &info-
> >dw_det, delay); }
> +
> +static irqreturn_t usb_conn_isr(int irq, void *dev_id) {
> +	struct usb_conn_info *info = dev_id;
> +
> +	usb_conn_queue_dwork(info, info->debounce_jiffies);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int usb_conn_probe(struct platform_device *pdev) {
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct device_node *parent;
> +	struct device_node *child;
> +	struct usb_conn_info *info;
> +	int ret = 0;
> +
> +	if (!np)
> +		return -EINVAL;
> +
> +	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	info->dev = dev;
> +
> +	child = of_get_child_by_name(np, "connector");
> +	if (!child) {
> +		dev_err(dev, "failed to find connector node\n");
> +		return -ENODEV;
> +	}
> +
> +	info->id_gpiod = devm_gpiod_get_from_of_node(
> +				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
> +	if (IS_ERR(info->id_gpiod)) {
> +		of_node_put(child);
> +		return PTR_ERR(info->id_gpiod);
> +	}
> +
> +	info->vbus_gpiod = devm_gpiod_get_from_of_node(
> +				dev, child, "vbus-gpios", 0, GPIOD_IN,
> +				"vbuspin");
> +	if (IS_ERR(info->vbus_gpiod)) {
> +		of_node_put(child);
> +		return PTR_ERR(info->vbus_gpiod);
> +	}
> +
> +	if (!info->id_gpiod && !info->vbus_gpiod) {
> +		dev_err(dev, "failed to get gpios\n");
> +		return -ENODEV;
> +	}
> +
> +	of_node_put(child);
> +
> +	if (info->id_gpiod)
> +		ret = gpiod_set_debounce(info->id_gpiod,
> USB_GPIO_DEB_US);
> +	if (!ret && info->vbus_gpiod)
> +		ret = gpiod_set_debounce(info->vbus_gpiod,
> USB_GPIO_DEB_US);
> +	if (ret < 0)
> +		info->debounce_jiffies =
> msecs_to_jiffies(USB_GPIO_DEB_MS);
> +
> +	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
> +
> +	info->vbus = devm_regulator_get(dev, "vbus");
> +	if (IS_ERR(info->vbus)) {
> +		dev_err(dev, "failed to get vbus\n");
> +		return PTR_ERR(info->vbus);
> +	}
> +
> +	child = of_graph_get_endpoint_by_regs(np, -1, 0);
> +	parent = of_graph_get_remote_port_parent(child);
> +	info->role_sw =
> fwnode_usb_role_switch_get(of_fwnode_handle(parent));
> +	of_node_put(child);
> +	of_node_put(parent);
> +	if (IS_ERR(info->role_sw)) {
> +		dev_err(dev, "failed to get role switch\n");
> +		return PTR_ERR(info->role_sw);
> +	}
> +
> +	if (info->id_gpiod) {
> +		info->id_irq = gpiod_to_irq(info->id_gpiod);
> +		if (info->id_irq < 0) {
> +			dev_err(dev, "failed to get ID IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return info->id_irq;
> +		}
> +
> +		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
> +						usb_conn_isr,
> USB_CONN_IRQF,
> +						pdev->name, info);
> +		if (ret < 0) {
> +			dev_err(dev, "failed to request ID IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return ret;
> +		}
> +	}
> +
> +	if (info->vbus_gpiod) {
> +		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
> +		if (info->vbus_irq < 0) {
> +			dev_err(dev, "failed to get VBUS IRQ\n");
May be usb_role_switch_put(info->role_sw);
> +			return info->vbus_irq;
> +		}
> +
> +		ret = devm_request_threaded_irq(dev, info->vbus_irq,
> NULL,
> +						usb_conn_isr,
> USB_CONN_IRQF,
> +						pdev->name, info);
> +		if (ret < 0) {
> +			dev_err(dev, "failed to request VBUS IRQ\n");
May be usb_role_switch_put(info->role_sw); ??
> +			return ret;
> +		}
> +	}
> +
> +	platform_set_drvdata(pdev, info);
> +
> +	/* Perform initial detection */
> +	usb_conn_queue_dwork(info, 0);
> +
> +	return 0;
> +}
> +
> +static int usb_conn_remove(struct platform_device *pdev) {
> +	struct usb_conn_info *info = platform_get_drvdata(pdev);
> +
> +	cancel_delayed_work_sync(&info->dw_det);
> +
> +	if (info->last_role == USB_ROLE_HOST)
> +		regulator_disable(info->vbus);
> +
> +	usb_role_switch_put(info->role_sw);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused usb_conn_suspend(struct device *dev) {
> +	struct usb_conn_info *info = dev_get_drvdata(dev);
> +
> +	if (info->id_gpiod)
> +		disable_irq(info->id_irq);
> +	if (info->vbus_gpiod)
> +		disable_irq(info->vbus_irq);
> +
> +	pinctrl_pm_select_sleep_state(dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused usb_conn_resume(struct device *dev) {
> +	struct usb_conn_info *info = dev_get_drvdata(dev);
> +
> +	pinctrl_pm_select_default_state(dev);
> +
> +	if (info->id_gpiod)
> +		enable_irq(info->id_irq);
> +	if (info->vbus_gpiod)
> +		enable_irq(info->vbus_irq);
> +
> +	usb_conn_queue_dwork(info, 0);
> +
> +	return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
> +			 usb_conn_suspend, usb_conn_resume);
> +
> +#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ?
> &usb_conn_pm_ops :
> +NULL)
> +
> +static const struct of_device_id usb_conn_dt_match[] = {
> +	{ .compatible = "linux,typeb-conn-gpio", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
> +
> +static struct platform_driver usb_conn_driver = {
> +	.probe		= usb_conn_probe,
> +	.remove		= usb_conn_remove,
> +	.driver		= {
> +		.name	= "typeb-conn-gpio",
> +		.pm	= DEV_PMS_OPS,
> +		.of_match_table = usb_conn_dt_match,
> +	},
> +};
> +
> +module_platform_driver(usb_conn_driver);
> +
> +MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
> +MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.21.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 1/6] dt-bindings: connector: add optional properties for Type-B
  2019-04-26  6:47   ` [PATCH v4 1/6] " Chunfeng Yun
  (?)
  (?)
@ 2019-04-26 13:19     ` Rob Herring
  -1 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 13:19 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, Linux USB List,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/Mediatek SoC support, Biju Das, Linus Walleij

On Fri, Apr 26, 2019 at 1:47 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
>
> Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for
> usb-b-connector
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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(+)

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 1/6] dt-bindings: connector: add optional properties for Type-B
@ 2019-04-26 13:19     ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 13:19 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, Linux USB List,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/Mediatek SoC support, Biju Das

On Fri, Apr 26, 2019 at 1:47 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
>
> Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for
> usb-b-connector
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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(+)

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,1/6] dt-bindings: connector: add optional properties for Type-B
@ 2019-04-26 13:19     ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 13:19 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, Linux USB List,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/Mediatek SoC support, Biju Das, Linus Walleij

On Fri, Apr 26, 2019 at 1:47 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
>
> Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for
> usb-b-connector
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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(+)

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 1/6] dt-bindings: connector: add optional properties for Type-B
@ 2019-04-26 13:19     ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 13:19 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Mark Rutland, devicetree, Heikki Krogerus, Hans de Goede,
	Greg Kroah-Hartman, Linus Walleij, Linux USB List, linux-kernel,
	Biju Das, Badhri Jagan Sridharan, Andy Shevchenko,
	moderated list:ARM/Mediatek SoC support, Min Guo,
	Matthias Brugger, Adam Thomson,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE, Li Jun

On Fri, Apr 26, 2019 at 1:47 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
>
> Add id-gpios, vbus-gpios, vbus-supply and pinctrl properties for
> usb-b-connector
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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(+)

Reviewed-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
@ 2019-04-26 20:45     ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 20:45 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, Apr 26, 2019 at 02:47: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 pin
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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          | 49 +++++++++++++++++++
>  1 file changed, 49 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 000000000000..d2e1c4e01b6d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
> @@ -0,0 +1,49 @@
> +USB Type-B GPIO Connector
> +
> +This is a virtual device used to switch dual role mode from the USB ID pin
> +connected to an input GPIO pin.
> +
> +Required properties:
> +- compatible : Should be "linux,typeb-conn-gpio"

There's no need for this virtual node. The USB host or device driver can 
instantiate a connector driver by walking the OF graph to the connector 
and creating a device.

> +
> +Sub-nodes:
> +- connector : should be present.
> +	- compatible : should be "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.
> +	see connector/usb-connector.txt
> +
> +- port : should be present.
> +	see graph.txt
> +
> +Example:
> +
> +rsw_iddig: role_sw_iddig {
> +	compatible = "linux,typeb-conn-gpio";
> +	status = "okay";
> +
> +	connector {
> +		compatible = "usb-b-connector";
> +		label = "micro-USB";
> +		type = "micro";
> +		id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>;
> +		vbus-supply = <&usb_p0_vbus>;
> +	};
> +
> +	port {

Humm, same mistake as Hikey patches...

This goes under the connector node as defined in the connector binding.

> +		bconn_ep: endpoint@0 {
> +			remote-endpoint = <&usb_role_sw>;
> +		};
> +	};
> +};
> +
> +&mtu3 {
> +	status = "okay";
> +
> +	port {
> +		usb_role_sw: endpoint@0 {
> +			remote-endpoint = <&bconn_ep>;
> +		};
> +	};
> +};
> -- 
> 2.21.0
> 

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
@ 2019-04-26 20:45     ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 20:45 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, Apr 26, 2019 at 02:47: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 pin
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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          | 49 +++++++++++++++++++
>  1 file changed, 49 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 000000000000..d2e1c4e01b6d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
> @@ -0,0 +1,49 @@
> +USB Type-B GPIO Connector
> +
> +This is a virtual device used to switch dual role mode from the USB ID pin
> +connected to an input GPIO pin.
> +
> +Required properties:
> +- compatible : Should be "linux,typeb-conn-gpio"

There's no need for this virtual node. The USB host or device driver can 
instantiate a connector driver by walking the OF graph to the connector 
and creating a device.

> +
> +Sub-nodes:
> +- connector : should be present.
> +	- compatible : should be "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.
> +	see connector/usb-connector.txt
> +
> +- port : should be present.
> +	see graph.txt
> +
> +Example:
> +
> +rsw_iddig: role_sw_iddig {
> +	compatible = "linux,typeb-conn-gpio";
> +	status = "okay";
> +
> +	connector {
> +		compatible = "usb-b-connector";
> +		label = "micro-USB";
> +		type = "micro";
> +		id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>;
> +		vbus-supply = <&usb_p0_vbus>;
> +	};
> +
> +	port {

Humm, same mistake as Hikey patches...

This goes under the connector node as defined in the connector binding.

> +		bconn_ep: endpoint@0 {
> +			remote-endpoint = <&usb_role_sw>;
> +		};
> +	};
> +};
> +
> +&mtu3 {
> +	status = "okay";
> +
> +	port {
> +		usb_role_sw: endpoint@0 {
> +			remote-endpoint = <&bconn_ep>;
> +		};
> +	};
> +};
> -- 
> 2.21.0
>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
@ 2019-04-26 20:45     ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 20:45 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Mark Rutland, devicetree, Heikki Krogerus, Hans de Goede,
	Greg Kroah-Hartman, Linus Walleij, linux-usb, linux-kernel,
	Biju Das, Badhri Jagan Sridharan, Andy Shevchenko,
	linux-mediatek, Min Guo, Matthias Brugger, Adam Thomson,
	linux-arm-kernel, Li Jun

On Fri, Apr 26, 2019 at 02:47: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 pin
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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          | 49 +++++++++++++++++++
>  1 file changed, 49 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 000000000000..d2e1c4e01b6d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
> @@ -0,0 +1,49 @@
> +USB Type-B GPIO Connector
> +
> +This is a virtual device used to switch dual role mode from the USB ID pin
> +connected to an input GPIO pin.
> +
> +Required properties:
> +- compatible : Should be "linux,typeb-conn-gpio"

There's no need for this virtual node. The USB host or device driver can 
instantiate a connector driver by walking the OF graph to the connector 
and creating a device.

> +
> +Sub-nodes:
> +- connector : should be present.
> +	- compatible : should be "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.
> +	see connector/usb-connector.txt
> +
> +- port : should be present.
> +	see graph.txt
> +
> +Example:
> +
> +rsw_iddig: role_sw_iddig {
> +	compatible = "linux,typeb-conn-gpio";
> +	status = "okay";
> +
> +	connector {
> +		compatible = "usb-b-connector";
> +		label = "micro-USB";
> +		type = "micro";
> +		id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>;
> +		vbus-supply = <&usb_p0_vbus>;
> +	};
> +
> +	port {

Humm, same mistake as Hikey patches...

This goes under the connector node as defined in the connector binding.

> +		bconn_ep: endpoint@0 {
> +			remote-endpoint = <&usb_role_sw>;
> +		};
> +	};
> +};
> +
> +&mtu3 {
> +	status = "okay";
> +
> +	port {
> +		usb_role_sw: endpoint@0 {
> +			remote-endpoint = <&bconn_ep>;
> +		};
> +	};
> +};
> -- 
> 2.21.0
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-26 20:49     ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 20:49 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> Now the USB Role Switch is supported, so add properties about it
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> index 3382b5cb471d..6e004c4a89af 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 switch, but
> +	not extcon

Coordinate with the Renesas and HiSilicon folks implementing the same 
thing and put this in a common spot. However, I think this should not 
even be needed as knowing the controller capabilities (based on the 
compatible) and knowing the type of connector should be enough 
information to tell you if dual role is supported or not.

>   - 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 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
> 

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-26 20:49     ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 20:49 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> Now the USB Role Switch is supported, so add properties about it
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> index 3382b5cb471d..6e004c4a89af 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 switch, but
> +	not extcon

Coordinate with the Renesas and HiSilicon folks implementing the same 
thing and put this in a common spot. However, I think this should not 
even be needed as knowing the controller capabilities (based on the 
compatible) and knowing the type of connector should be enough 
information to tell you if dual role is supported or not.

>   - 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 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
>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-26 20:49     ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-26 20:49 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Mark Rutland, devicetree, Heikki Krogerus, Hans de Goede,
	Greg Kroah-Hartman, Linus Walleij, linux-usb, linux-kernel,
	Biju Das, Badhri Jagan Sridharan, Andy Shevchenko,
	linux-mediatek, Min Guo, Matthias Brugger, Adam Thomson,
	linux-arm-kernel, Li Jun

On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> Now the USB Role Switch is supported, so add properties about it
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> 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, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> index 3382b5cb471d..6e004c4a89af 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 switch, but
> +	not extcon

Coordinate with the Renesas and HiSilicon folks implementing the same 
thing and put this in a common spot. However, I think this should not 
even be needed as knowing the controller capabilities (based on the 
compatible) and knowing the type of connector should be enough 
information to tell you if dual role is supported or not.

>   - 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 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
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
  2019-04-26 20:45     ` [v4,2/6] " Rob Herring
  (?)
  (?)
@ 2019-04-28  1:50       ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28  1:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, 2019-04-26 at 15:45 -0500, Rob Herring wrote:
> On Fri, Apr 26, 2019 at 02:47: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 pin
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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          | 49 +++++++++++++++++++
> >  1 file changed, 49 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 000000000000..d2e1c4e01b6d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
> > @@ -0,0 +1,49 @@
> > +USB Type-B GPIO Connector
> > +
> > +This is a virtual device used to switch dual role mode from the USB ID pin
> > +connected to an input GPIO pin.
> > +
> > +Required properties:
> > +- compatible : Should be "linux,typeb-conn-gpio"
> 
> There's no need for this virtual node. The USB host or device driver can 
> instantiate a connector driver by walking the OF graph to the connector 
> and creating a device.
Got it.
> 
> > +
> > +Sub-nodes:
> > +- connector : should be present.
> > +	- compatible : should be "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.
> > +	see connector/usb-connector.txt
> > +
> > +- port : should be present.
> > +	see graph.txt
> > +
> > +Example:
> > +
> > +rsw_iddig: role_sw_iddig {
> > +	compatible = "linux,typeb-conn-gpio";
> > +	status = "okay";
> > +
> > +	connector {
> > +		compatible = "usb-b-connector";
> > +		label = "micro-USB";
> > +		type = "micro";
> > +		id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>;
> > +		vbus-supply = <&usb_p0_vbus>;
> > +	};
> > +
> > +	port {
> 
> Humm, same mistake as Hikey patches...
> 
> This goes under the connector node as defined in the connector binding.
Ok, will fix it.

Thanks a lot.

> 
> > +		bconn_ep: endpoint@0 {
> > +			remote-endpoint = <&usb_role_sw>;
> > +		};
> > +	};
> > +};
> > +
> > +&mtu3 {
> > +	status = "okay";
> > +
> > +	port {
> > +		usb_role_sw: endpoint@0 {
> > +			remote-endpoint = <&bconn_ep>;
> > +		};
> > +	};
> > +};
> > -- 
> > 2.21.0
> > 



^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
@ 2019-04-28  1:50       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28  1:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, 2019-04-26 at 15:45 -0500, Rob Herring wrote:
> On Fri, Apr 26, 2019 at 02:47: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 pin
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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          | 49 +++++++++++++++++++
> >  1 file changed, 49 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 000000000000..d2e1c4e01b6d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
> > @@ -0,0 +1,49 @@
> > +USB Type-B GPIO Connector
> > +
> > +This is a virtual device used to switch dual role mode from the USB ID pin
> > +connected to an input GPIO pin.
> > +
> > +Required properties:
> > +- compatible : Should be "linux,typeb-conn-gpio"
> 
> There's no need for this virtual node. The USB host or device driver can 
> instantiate a connector driver by walking the OF graph to the connector 
> and creating a device.
Got it.
> 
> > +
> > +Sub-nodes:
> > +- connector : should be present.
> > +	- compatible : should be "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.
> > +	see connector/usb-connector.txt
> > +
> > +- port : should be present.
> > +	see graph.txt
> > +
> > +Example:
> > +
> > +rsw_iddig: role_sw_iddig {
> > +	compatible = "linux,typeb-conn-gpio";
> > +	status = "okay";
> > +
> > +	connector {
> > +		compatible = "usb-b-connector";
> > +		label = "micro-USB";
> > +		type = "micro";
> > +		id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>;
> > +		vbus-supply = <&usb_p0_vbus>;
> > +	};
> > +
> > +	port {
> 
> Humm, same mistake as Hikey patches...
> 
> This goes under the connector node as defined in the connector binding.
Ok, will fix it.

Thanks a lot.

> 
> > +		bconn_ep: endpoint@0 {
> > +			remote-endpoint = <&usb_role_sw>;
> > +		};
> > +	};
> > +};
> > +
> > +&mtu3 {
> > +	status = "okay";
> > +
> > +	port {
> > +		usb_role_sw: endpoint@0 {
> > +			remote-endpoint = <&bconn_ep>;
> > +		};
> > +	};
> > +};
> > -- 
> > 2.21.0
> > 

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
@ 2019-04-28  1:50       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28  1:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, 2019-04-26 at 15:45 -0500, Rob Herring wrote:
> On Fri, Apr 26, 2019 at 02:47: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 pin
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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          | 49 +++++++++++++++++++
> >  1 file changed, 49 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 000000000000..d2e1c4e01b6d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
> > @@ -0,0 +1,49 @@
> > +USB Type-B GPIO Connector
> > +
> > +This is a virtual device used to switch dual role mode from the USB ID pin
> > +connected to an input GPIO pin.
> > +
> > +Required properties:
> > +- compatible : Should be "linux,typeb-conn-gpio"
> 
> There's no need for this virtual node. The USB host or device driver can 
> instantiate a connector driver by walking the OF graph to the connector 
> and creating a device.
Got it.
> 
> > +
> > +Sub-nodes:
> > +- connector : should be present.
> > +	- compatible : should be "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.
> > +	see connector/usb-connector.txt
> > +
> > +- port : should be present.
> > +	see graph.txt
> > +
> > +Example:
> > +
> > +rsw_iddig: role_sw_iddig {
> > +	compatible = "linux,typeb-conn-gpio";
> > +	status = "okay";
> > +
> > +	connector {
> > +		compatible = "usb-b-connector";
> > +		label = "micro-USB";
> > +		type = "micro";
> > +		id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>;
> > +		vbus-supply = <&usb_p0_vbus>;
> > +	};
> > +
> > +	port {
> 
> Humm, same mistake as Hikey patches...
> 
> This goes under the connector node as defined in the connector binding.
Ok, will fix it.

Thanks a lot.

> 
> > +		bconn_ep: endpoint@0 {
> > +			remote-endpoint = <&usb_role_sw>;
> > +		};
> > +	};
> > +};
> > +
> > +&mtu3 {
> > +	status = "okay";
> > +
> > +	port {
> > +		usb_role_sw: endpoint@0 {
> > +			remote-endpoint = <&bconn_ep>;
> > +		};
> > +	};
> > +};
> > -- 
> > 2.21.0
> >

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver
@ 2019-04-28  1:50       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28  1:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Rutland, devicetree, Heikki Krogerus, Hans de Goede,
	Greg Kroah-Hartman, Linus Walleij, linux-usb, linux-kernel,
	Biju Das, Badhri Jagan Sridharan, Andy Shevchenko,
	linux-mediatek, Min Guo, Matthias Brugger, Adam Thomson,
	linux-arm-kernel, Li Jun

On Fri, 2019-04-26 at 15:45 -0500, Rob Herring wrote:
> On Fri, Apr 26, 2019 at 02:47: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 pin
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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          | 49 +++++++++++++++++++
> >  1 file changed, 49 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 000000000000..d2e1c4e01b6d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/usb/typeb-conn-gpio.txt
> > @@ -0,0 +1,49 @@
> > +USB Type-B GPIO Connector
> > +
> > +This is a virtual device used to switch dual role mode from the USB ID pin
> > +connected to an input GPIO pin.
> > +
> > +Required properties:
> > +- compatible : Should be "linux,typeb-conn-gpio"
> 
> There's no need for this virtual node. The USB host or device driver can 
> instantiate a connector driver by walking the OF graph to the connector 
> and creating a device.
Got it.
> 
> > +
> > +Sub-nodes:
> > +- connector : should be present.
> > +	- compatible : should be "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.
> > +	see connector/usb-connector.txt
> > +
> > +- port : should be present.
> > +	see graph.txt
> > +
> > +Example:
> > +
> > +rsw_iddig: role_sw_iddig {
> > +	compatible = "linux,typeb-conn-gpio";
> > +	status = "okay";
> > +
> > +	connector {
> > +		compatible = "usb-b-connector";
> > +		label = "micro-USB";
> > +		type = "micro";
> > +		id-gpios = <&pio 12 GPIO_ACTIVE_HIGH>;
> > +		vbus-supply = <&usb_p0_vbus>;
> > +	};
> > +
> > +	port {
> 
> Humm, same mistake as Hikey patches...
> 
> This goes under the connector node as defined in the connector binding.
Ok, will fix it.

Thanks a lot.

> 
> > +		bconn_ep: endpoint@0 {
> > +			remote-endpoint = <&usb_role_sw>;
> > +		};
> > +	};
> > +};
> > +
> > +&mtu3 {
> > +	status = "okay";
> > +
> > +	port {
> > +		usb_role_sw: endpoint@0 {
> > +			remote-endpoint = <&bconn_ep>;
> > +		};
> > +	};
> > +};
> > -- 
> > 2.21.0
> > 



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
  2019-04-26  9:22     ` [PATCH v4 5/6] " Biju Das
  (?)
  (?)
@ 2019-04-28  9:26       ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28  9:26 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek

Hi Biju,
On Fri, 2019-04-26 at 09:22 +0000, Biju Das wrote:
> Hi Chunfeng Yun,
> 
> Thanks for the patch.
> 
> > Subject: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
> > 
> > Due to the requirement of usb-connector.txt binding, the old way using
> > extcon to support USB Dual-Role switch is now deprecated when use Type-B
> > connector.
> > This patch introduces a driver of Type-B connector which typically uses an
> > input GPIO to detect USB ID pin, and try to replace the function provided by
> > extcon-usb-gpio driver
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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 | 305
> > ++++++++++++++++++++++++++++
> >  3 files changed, 317 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 000000000000..097d2ca12a12
> > --- /dev/null
> > +++ b/drivers/usb/roles/typeb-conn-gpio.c
> > @@ -0,0 +1,305 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * USB Type-B GPIO Connector Driver
> > + *
> > + * Copyright (C) 2019 MediaTek Inc.
> > + *
> > + * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > + *
> > + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c  */
> > +
> > +#include <linux/device.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_graph.h>
> > +#include <linux/pinctrl/consumer.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regulator/consumer.h>
> > +#include <linux/usb/role.h>
> > +
> > +#define USB_GPIO_DEB_MS		20	/* 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 (ret)
> > +		dev_err(info->dev, "failed to set role: %d\n", ret);
> > +
> > +	if (role == USB_ROLE_HOST) {
> > +		ret = regulator_enable(info->vbus);
> > +		if (ret)
> > +			dev_err(info->dev, "enable vbus regulator failed\n");
> > +	}
> > +
> > +	info->last_role = role;
> > +
> > +	dev_dbg(info->dev, "vbus regulator is %s\n",
> > +		regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); }
> > +
> > +static void usb_conn_queue_dwork(struct usb_conn_info *info,
> > +				 unsigned long delay)
> > +{
> > +	queue_delayed_work(system_power_efficient_wq, &info-
> > >dw_det, delay); }
> > +
> > +static irqreturn_t usb_conn_isr(int irq, void *dev_id) {
> > +	struct usb_conn_info *info = dev_id;
> > +
> > +	usb_conn_queue_dwork(info, info->debounce_jiffies);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int usb_conn_probe(struct platform_device *pdev) {
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *np = dev->of_node;
> > +	struct device_node *parent;
> > +	struct device_node *child;
> > +	struct usb_conn_info *info;
> > +	int ret = 0;
> > +
> > +	if (!np)
> > +		return -EINVAL;
> > +
> > +	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> > +	if (!info)
> > +		return -ENOMEM;
> > +
> > +	info->dev = dev;
> > +
> > +	child = of_get_child_by_name(np, "connector");
> > +	if (!child) {
> > +		dev_err(dev, "failed to find connector node\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	info->id_gpiod = devm_gpiod_get_from_of_node(
> > +				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
> > +	if (IS_ERR(info->id_gpiod)) {
> > +		of_node_put(child);
> > +		return PTR_ERR(info->id_gpiod);
> > +	}
> > +
> > +	info->vbus_gpiod = devm_gpiod_get_from_of_node(
> > +				dev, child, "vbus-gpios", 0, GPIOD_IN,
> > +				"vbuspin");
> > +	if (IS_ERR(info->vbus_gpiod)) {
> > +		of_node_put(child);
> > +		return PTR_ERR(info->vbus_gpiod);
> > +	}
> > +
> > +	if (!info->id_gpiod && !info->vbus_gpiod) {
> > +		dev_err(dev, "failed to get gpios\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	of_node_put(child);
> > +
> > +	if (info->id_gpiod)
> > +		ret = gpiod_set_debounce(info->id_gpiod,
> > USB_GPIO_DEB_US);
> > +	if (!ret && info->vbus_gpiod)
> > +		ret = gpiod_set_debounce(info->vbus_gpiod,
> > USB_GPIO_DEB_US);
> > +	if (ret < 0)
> > +		info->debounce_jiffies =
> > msecs_to_jiffies(USB_GPIO_DEB_MS);
> > +
> > +	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
> > +
> > +	info->vbus = devm_regulator_get(dev, "vbus");
> > +	if (IS_ERR(info->vbus)) {
> > +		dev_err(dev, "failed to get vbus\n");
> > +		return PTR_ERR(info->vbus);
> > +	}
> > +
> > +	child = of_graph_get_endpoint_by_regs(np, -1, 0);
> > +	parent = of_graph_get_remote_port_parent(child);
> > +	info->role_sw =
> > fwnode_usb_role_switch_get(of_fwnode_handle(parent));
> > +	of_node_put(child);
> > +	of_node_put(parent);
> > +	if (IS_ERR(info->role_sw)) {
> > +		dev_err(dev, "failed to get role switch\n");
> > +		return PTR_ERR(info->role_sw);
> > +	}
> > +
> > +	if (info->id_gpiod) {
> > +		info->id_irq = gpiod_to_irq(info->id_gpiod);
> > +		if (info->id_irq < 0) {
> > +			dev_err(dev, "failed to get ID IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
Good catch, will fix it.

Thanks
> > +			return info->id_irq;
> > +		}
> > +
> > +		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
> > +						usb_conn_isr,
> > USB_CONN_IRQF,
> > +						pdev->name, info);
> > +		if (ret < 0) {
> > +			dev_err(dev, "failed to request ID IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	if (info->vbus_gpiod) {
> > +		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
> > +		if (info->vbus_irq < 0) {
> > +			dev_err(dev, "failed to get VBUS IRQ\n");
> May be usb_role_switch_put(info->role_sw);
> > +			return info->vbus_irq;
> > +		}
> > +
> > +		ret = devm_request_threaded_irq(dev, info->vbus_irq,
> > NULL,
> > +						usb_conn_isr,
> > USB_CONN_IRQF,
> > +						pdev->name, info);
> > +		if (ret < 0) {
> > +			dev_err(dev, "failed to request VBUS IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	platform_set_drvdata(pdev, info);
> > +
> > +	/* Perform initial detection */
> > +	usb_conn_queue_dwork(info, 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int usb_conn_remove(struct platform_device *pdev) {
> > +	struct usb_conn_info *info = platform_get_drvdata(pdev);
> > +
> > +	cancel_delayed_work_sync(&info->dw_det);
> > +
> > +	if (info->last_role == USB_ROLE_HOST)
> > +		regulator_disable(info->vbus);
> > +
> > +	usb_role_switch_put(info->role_sw);
> > +
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused usb_conn_suspend(struct device *dev) {
> > +	struct usb_conn_info *info = dev_get_drvdata(dev);
> > +
> > +	if (info->id_gpiod)
> > +		disable_irq(info->id_irq);
> > +	if (info->vbus_gpiod)
> > +		disable_irq(info->vbus_irq);
> > +
> > +	pinctrl_pm_select_sleep_state(dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused usb_conn_resume(struct device *dev) {
> > +	struct usb_conn_info *info = dev_get_drvdata(dev);
> > +
> > +	pinctrl_pm_select_default_state(dev);
> > +
> > +	if (info->id_gpiod)
> > +		enable_irq(info->id_irq);
> > +	if (info->vbus_gpiod)
> > +		enable_irq(info->vbus_irq);
> > +
> > +	usb_conn_queue_dwork(info, 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
> > +			 usb_conn_suspend, usb_conn_resume);
> > +
> > +#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ?
> > &usb_conn_pm_ops :
> > +NULL)
> > +
> > +static const struct of_device_id usb_conn_dt_match[] = {
> > +	{ .compatible = "linux,typeb-conn-gpio", },
> > +	{ }
> > +};
> > +MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
> > +
> > +static struct platform_driver usb_conn_driver = {
> > +	.probe		= usb_conn_probe,
> > +	.remove		= usb_conn_remove,
> > +	.driver		= {
> > +		.name	= "typeb-conn-gpio",
> > +		.pm	= DEV_PMS_OPS,
> > +		.of_match_table = usb_conn_dt_match,
> > +	},
> > +};
> > +
> > +module_platform_driver(usb_conn_driver);
> > +
> > +MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
> > +MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
> > +MODULE_LICENSE("GPL v2");
> > --
> > 2.21.0
> 



^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
@ 2019-04-28  9:26       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28  9:26 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel,
	linux-mediatek@lists.infradead.org

Hi Biju,
On Fri, 2019-04-26 at 09:22 +0000, Biju Das wrote:
> Hi Chunfeng Yun,
> 
> Thanks for the patch.
> 
> > Subject: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
> > 
> > Due to the requirement of usb-connector.txt binding, the old way using
> > extcon to support USB Dual-Role switch is now deprecated when use Type-B
> > connector.
> > This patch introduces a driver of Type-B connector which typically uses an
> > input GPIO to detect USB ID pin, and try to replace the function provided by
> > extcon-usb-gpio driver
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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 | 305
> > ++++++++++++++++++++++++++++
> >  3 files changed, 317 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 000000000000..097d2ca12a12
> > --- /dev/null
> > +++ b/drivers/usb/roles/typeb-conn-gpio.c
> > @@ -0,0 +1,305 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * USB Type-B GPIO Connector Driver
> > + *
> > + * Copyright (C) 2019 MediaTek Inc.
> > + *
> > + * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > + *
> > + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c  */
> > +
> > +#include <linux/device.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_graph.h>
> > +#include <linux/pinctrl/consumer.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regulator/consumer.h>
> > +#include <linux/usb/role.h>
> > +
> > +#define USB_GPIO_DEB_MS		20	/* 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 (ret)
> > +		dev_err(info->dev, "failed to set role: %d\n", ret);
> > +
> > +	if (role == USB_ROLE_HOST) {
> > +		ret = regulator_enable(info->vbus);
> > +		if (ret)
> > +			dev_err(info->dev, "enable vbus regulator failed\n");
> > +	}
> > +
> > +	info->last_role = role;
> > +
> > +	dev_dbg(info->dev, "vbus regulator is %s\n",
> > +		regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); }
> > +
> > +static void usb_conn_queue_dwork(struct usb_conn_info *info,
> > +				 unsigned long delay)
> > +{
> > +	queue_delayed_work(system_power_efficient_wq, &info-
> > >dw_det, delay); }
> > +
> > +static irqreturn_t usb_conn_isr(int irq, void *dev_id) {
> > +	struct usb_conn_info *info = dev_id;
> > +
> > +	usb_conn_queue_dwork(info, info->debounce_jiffies);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int usb_conn_probe(struct platform_device *pdev) {
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *np = dev->of_node;
> > +	struct device_node *parent;
> > +	struct device_node *child;
> > +	struct usb_conn_info *info;
> > +	int ret = 0;
> > +
> > +	if (!np)
> > +		return -EINVAL;
> > +
> > +	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> > +	if (!info)
> > +		return -ENOMEM;
> > +
> > +	info->dev = dev;
> > +
> > +	child = of_get_child_by_name(np, "connector");
> > +	if (!child) {
> > +		dev_err(dev, "failed to find connector node\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	info->id_gpiod = devm_gpiod_get_from_of_node(
> > +				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
> > +	if (IS_ERR(info->id_gpiod)) {
> > +		of_node_put(child);
> > +		return PTR_ERR(info->id_gpiod);
> > +	}
> > +
> > +	info->vbus_gpiod = devm_gpiod_get_from_of_node(
> > +				dev, child, "vbus-gpios", 0, GPIOD_IN,
> > +				"vbuspin");
> > +	if (IS_ERR(info->vbus_gpiod)) {
> > +		of_node_put(child);
> > +		return PTR_ERR(info->vbus_gpiod);
> > +	}
> > +
> > +	if (!info->id_gpiod && !info->vbus_gpiod) {
> > +		dev_err(dev, "failed to get gpios\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	of_node_put(child);
> > +
> > +	if (info->id_gpiod)
> > +		ret = gpiod_set_debounce(info->id_gpiod,
> > USB_GPIO_DEB_US);
> > +	if (!ret && info->vbus_gpiod)
> > +		ret = gpiod_set_debounce(info->vbus_gpiod,
> > USB_GPIO_DEB_US);
> > +	if (ret < 0)
> > +		info->debounce_jiffies =
> > msecs_to_jiffies(USB_GPIO_DEB_MS);
> > +
> > +	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
> > +
> > +	info->vbus = devm_regulator_get(dev, "vbus");
> > +	if (IS_ERR(info->vbus)) {
> > +		dev_err(dev, "failed to get vbus\n");
> > +		return PTR_ERR(info->vbus);
> > +	}
> > +
> > +	child = of_graph_get_endpoint_by_regs(np, -1, 0);
> > +	parent = of_graph_get_remote_port_parent(child);
> > +	info->role_sw =
> > fwnode_usb_role_switch_get(of_fwnode_handle(parent));
> > +	of_node_put(child);
> > +	of_node_put(parent);
> > +	if (IS_ERR(info->role_sw)) {
> > +		dev_err(dev, "failed to get role switch\n");
> > +		return PTR_ERR(info->role_sw);
> > +	}
> > +
> > +	if (info->id_gpiod) {
> > +		info->id_irq = gpiod_to_irq(info->id_gpiod);
> > +		if (info->id_irq < 0) {
> > +			dev_err(dev, "failed to get ID IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
Good catch, will fix it.

Thanks
> > +			return info->id_irq;
> > +		}
> > +
> > +		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
> > +						usb_conn_isr,
> > USB_CONN_IRQF,
> > +						pdev->name, info);
> > +		if (ret < 0) {
> > +			dev_err(dev, "failed to request ID IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	if (info->vbus_gpiod) {
> > +		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
> > +		if (info->vbus_irq < 0) {
> > +			dev_err(dev, "failed to get VBUS IRQ\n");
> May be usb_role_switch_put(info->role_sw);
> > +			return info->vbus_irq;
> > +		}
> > +
> > +		ret = devm_request_threaded_irq(dev, info->vbus_irq,
> > NULL,
> > +						usb_conn_isr,
> > USB_CONN_IRQF,
> > +						pdev->name, info);
> > +		if (ret < 0) {
> > +			dev_err(dev, "failed to request VBUS IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	platform_set_drvdata(pdev, info);
> > +
> > +	/* Perform initial detection */
> > +	usb_conn_queue_dwork(info, 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int usb_conn_remove(struct platform_device *pdev) {
> > +	struct usb_conn_info *info = platform_get_drvdata(pdev);
> > +
> > +	cancel_delayed_work_sync(&info->dw_det);
> > +
> > +	if (info->last_role == USB_ROLE_HOST)
> > +		regulator_disable(info->vbus);
> > +
> > +	usb_role_switch_put(info->role_sw);
> > +
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused usb_conn_suspend(struct device *dev) {
> > +	struct usb_conn_info *info = dev_get_drvdata(dev);
> > +
> > +	if (info->id_gpiod)
> > +		disable_irq(info->id_irq);
> > +	if (info->vbus_gpiod)
> > +		disable_irq(info->vbus_irq);
> > +
> > +	pinctrl_pm_select_sleep_state(dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused usb_conn_resume(struct device *dev) {
> > +	struct usb_conn_info *info = dev_get_drvdata(dev);
> > +
> > +	pinctrl_pm_select_default_state(dev);
> > +
> > +	if (info->id_gpiod)
> > +		enable_irq(info->id_irq);
> > +	if (info->vbus_gpiod)
> > +		enable_irq(info->vbus_irq);
> > +
> > +	usb_conn_queue_dwork(info, 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
> > +			 usb_conn_suspend, usb_conn_resume);
> > +
> > +#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ?
> > &usb_conn_pm_ops :
> > +NULL)
> > +
> > +static const struct of_device_id usb_conn_dt_match[] = {
> > +	{ .compatible = "linux,typeb-conn-gpio", },
> > +	{ }
> > +};
> > +MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
> > +
> > +static struct platform_driver usb_conn_driver = {
> > +	.probe		= usb_conn_probe,
> > +	.remove		= usb_conn_remove,
> > +	.driver		= {
> > +		.name	= "typeb-conn-gpio",
> > +		.pm	= DEV_PMS_OPS,
> > +		.of_match_table = usb_conn_dt_match,
> > +	},
> > +};
> > +
> > +module_platform_driver(usb_conn_driver);
> > +
> > +MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
> > +MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
> > +MODULE_LICENSE("GPL v2");
> > --
> > 2.21.0
> 

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,5/6] usb: roles: add USB Type-B GPIO connector driver
@ 2019-04-28  9:26       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28  9:26 UTC (permalink / raw)
  To: Biju Das
  Cc: Rob Herring, Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek

Hi Biju,
On Fri, 2019-04-26 at 09:22 +0000, Biju Das wrote:
> Hi Chunfeng Yun,
> 
> Thanks for the patch.
> 
> > Subject: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
> > 
> > Due to the requirement of usb-connector.txt binding, the old way using
> > extcon to support USB Dual-Role switch is now deprecated when use Type-B
> > connector.
> > This patch introduces a driver of Type-B connector which typically uses an
> > input GPIO to detect USB ID pin, and try to replace the function provided by
> > extcon-usb-gpio driver
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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 | 305
> > ++++++++++++++++++++++++++++
> >  3 files changed, 317 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 000000000000..097d2ca12a12
> > --- /dev/null
> > +++ b/drivers/usb/roles/typeb-conn-gpio.c
> > @@ -0,0 +1,305 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * USB Type-B GPIO Connector Driver
> > + *
> > + * Copyright (C) 2019 MediaTek Inc.
> > + *
> > + * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > + *
> > + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c  */
> > +
> > +#include <linux/device.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_graph.h>
> > +#include <linux/pinctrl/consumer.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regulator/consumer.h>
> > +#include <linux/usb/role.h>
> > +
> > +#define USB_GPIO_DEB_MS		20	/* 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 (ret)
> > +		dev_err(info->dev, "failed to set role: %d\n", ret);
> > +
> > +	if (role == USB_ROLE_HOST) {
> > +		ret = regulator_enable(info->vbus);
> > +		if (ret)
> > +			dev_err(info->dev, "enable vbus regulator failed\n");
> > +	}
> > +
> > +	info->last_role = role;
> > +
> > +	dev_dbg(info->dev, "vbus regulator is %s\n",
> > +		regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); }
> > +
> > +static void usb_conn_queue_dwork(struct usb_conn_info *info,
> > +				 unsigned long delay)
> > +{
> > +	queue_delayed_work(system_power_efficient_wq, &info-
> > >dw_det, delay); }
> > +
> > +static irqreturn_t usb_conn_isr(int irq, void *dev_id) {
> > +	struct usb_conn_info *info = dev_id;
> > +
> > +	usb_conn_queue_dwork(info, info->debounce_jiffies);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int usb_conn_probe(struct platform_device *pdev) {
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *np = dev->of_node;
> > +	struct device_node *parent;
> > +	struct device_node *child;
> > +	struct usb_conn_info *info;
> > +	int ret = 0;
> > +
> > +	if (!np)
> > +		return -EINVAL;
> > +
> > +	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> > +	if (!info)
> > +		return -ENOMEM;
> > +
> > +	info->dev = dev;
> > +
> > +	child = of_get_child_by_name(np, "connector");
> > +	if (!child) {
> > +		dev_err(dev, "failed to find connector node\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	info->id_gpiod = devm_gpiod_get_from_of_node(
> > +				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
> > +	if (IS_ERR(info->id_gpiod)) {
> > +		of_node_put(child);
> > +		return PTR_ERR(info->id_gpiod);
> > +	}
> > +
> > +	info->vbus_gpiod = devm_gpiod_get_from_of_node(
> > +				dev, child, "vbus-gpios", 0, GPIOD_IN,
> > +				"vbuspin");
> > +	if (IS_ERR(info->vbus_gpiod)) {
> > +		of_node_put(child);
> > +		return PTR_ERR(info->vbus_gpiod);
> > +	}
> > +
> > +	if (!info->id_gpiod && !info->vbus_gpiod) {
> > +		dev_err(dev, "failed to get gpios\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	of_node_put(child);
> > +
> > +	if (info->id_gpiod)
> > +		ret = gpiod_set_debounce(info->id_gpiod,
> > USB_GPIO_DEB_US);
> > +	if (!ret && info->vbus_gpiod)
> > +		ret = gpiod_set_debounce(info->vbus_gpiod,
> > USB_GPIO_DEB_US);
> > +	if (ret < 0)
> > +		info->debounce_jiffies =
> > msecs_to_jiffies(USB_GPIO_DEB_MS);
> > +
> > +	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
> > +
> > +	info->vbus = devm_regulator_get(dev, "vbus");
> > +	if (IS_ERR(info->vbus)) {
> > +		dev_err(dev, "failed to get vbus\n");
> > +		return PTR_ERR(info->vbus);
> > +	}
> > +
> > +	child = of_graph_get_endpoint_by_regs(np, -1, 0);
> > +	parent = of_graph_get_remote_port_parent(child);
> > +	info->role_sw =
> > fwnode_usb_role_switch_get(of_fwnode_handle(parent));
> > +	of_node_put(child);
> > +	of_node_put(parent);
> > +	if (IS_ERR(info->role_sw)) {
> > +		dev_err(dev, "failed to get role switch\n");
> > +		return PTR_ERR(info->role_sw);
> > +	}
> > +
> > +	if (info->id_gpiod) {
> > +		info->id_irq = gpiod_to_irq(info->id_gpiod);
> > +		if (info->id_irq < 0) {
> > +			dev_err(dev, "failed to get ID IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
Good catch, will fix it.

Thanks
> > +			return info->id_irq;
> > +		}
> > +
> > +		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
> > +						usb_conn_isr,
> > USB_CONN_IRQF,
> > +						pdev->name, info);
> > +		if (ret < 0) {
> > +			dev_err(dev, "failed to request ID IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	if (info->vbus_gpiod) {
> > +		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
> > +		if (info->vbus_irq < 0) {
> > +			dev_err(dev, "failed to get VBUS IRQ\n");
> May be usb_role_switch_put(info->role_sw);
> > +			return info->vbus_irq;
> > +		}
> > +
> > +		ret = devm_request_threaded_irq(dev, info->vbus_irq,
> > NULL,
> > +						usb_conn_isr,
> > USB_CONN_IRQF,
> > +						pdev->name, info);
> > +		if (ret < 0) {
> > +			dev_err(dev, "failed to request VBUS IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	platform_set_drvdata(pdev, info);
> > +
> > +	/* Perform initial detection */
> > +	usb_conn_queue_dwork(info, 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int usb_conn_remove(struct platform_device *pdev) {
> > +	struct usb_conn_info *info = platform_get_drvdata(pdev);
> > +
> > +	cancel_delayed_work_sync(&info->dw_det);
> > +
> > +	if (info->last_role == USB_ROLE_HOST)
> > +		regulator_disable(info->vbus);
> > +
> > +	usb_role_switch_put(info->role_sw);
> > +
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused usb_conn_suspend(struct device *dev) {
> > +	struct usb_conn_info *info = dev_get_drvdata(dev);
> > +
> > +	if (info->id_gpiod)
> > +		disable_irq(info->id_irq);
> > +	if (info->vbus_gpiod)
> > +		disable_irq(info->vbus_irq);
> > +
> > +	pinctrl_pm_select_sleep_state(dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused usb_conn_resume(struct device *dev) {
> > +	struct usb_conn_info *info = dev_get_drvdata(dev);
> > +
> > +	pinctrl_pm_select_default_state(dev);
> > +
> > +	if (info->id_gpiod)
> > +		enable_irq(info->id_irq);
> > +	if (info->vbus_gpiod)
> > +		enable_irq(info->vbus_irq);
> > +
> > +	usb_conn_queue_dwork(info, 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
> > +			 usb_conn_suspend, usb_conn_resume);
> > +
> > +#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ?
> > &usb_conn_pm_ops :
> > +NULL)
> > +
> > +static const struct of_device_id usb_conn_dt_match[] = {
> > +	{ .compatible = "linux,typeb-conn-gpio", },
> > +	{ }
> > +};
> > +MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
> > +
> > +static struct platform_driver usb_conn_driver = {
> > +	.probe		= usb_conn_probe,
> > +	.remove		= usb_conn_remove,
> > +	.driver		= {
> > +		.name	= "typeb-conn-gpio",
> > +		.pm	= DEV_PMS_OPS,
> > +		.of_match_table = usb_conn_dt_match,
> > +	},
> > +};
> > +
> > +module_platform_driver(usb_conn_driver);
> > +
> > +MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
> > +MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
> > +MODULE_LICENSE("GPL v2");
> > --
> > 2.21.0
>

^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
@ 2019-04-28  9:26       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28  9:26 UTC (permalink / raw)
  To: Biju Das
  Cc: Mark Rutland, devicetree, Heikki Krogerus, Hans de Goede,
	Greg Kroah-Hartman, linux-usb, linux-kernel,
	Badhri Jagan Sridharan, Andy Shevchenko, Rob Herring,
	linux-mediatek, Min Guo, Matthias Brugger, Adam Thomson,
	linux-arm-kernel, Li Jun

Hi Biju,
On Fri, 2019-04-26 at 09:22 +0000, Biju Das wrote:
> Hi Chunfeng Yun,
> 
> Thanks for the patch.
> 
> > Subject: [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver
> > 
> > Due to the requirement of usb-connector.txt binding, the old way using
> > extcon to support USB Dual-Role switch is now deprecated when use Type-B
> > connector.
> > This patch introduces a driver of Type-B connector which typically uses an
> > input GPIO to detect USB ID pin, and try to replace the function provided by
> > extcon-usb-gpio driver
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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 | 305
> > ++++++++++++++++++++++++++++
> >  3 files changed, 317 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 000000000000..097d2ca12a12
> > --- /dev/null
> > +++ b/drivers/usb/roles/typeb-conn-gpio.c
> > @@ -0,0 +1,305 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * USB Type-B GPIO Connector Driver
> > + *
> > + * Copyright (C) 2019 MediaTek Inc.
> > + *
> > + * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > + *
> > + * Some code borrowed from drivers/extcon/extcon-usb-gpio.c  */
> > +
> > +#include <linux/device.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_graph.h>
> > +#include <linux/pinctrl/consumer.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regulator/consumer.h>
> > +#include <linux/usb/role.h>
> > +
> > +#define USB_GPIO_DEB_MS		20	/* 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 (ret)
> > +		dev_err(info->dev, "failed to set role: %d\n", ret);
> > +
> > +	if (role == USB_ROLE_HOST) {
> > +		ret = regulator_enable(info->vbus);
> > +		if (ret)
> > +			dev_err(info->dev, "enable vbus regulator failed\n");
> > +	}
> > +
> > +	info->last_role = role;
> > +
> > +	dev_dbg(info->dev, "vbus regulator is %s\n",
> > +		regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); }
> > +
> > +static void usb_conn_queue_dwork(struct usb_conn_info *info,
> > +				 unsigned long delay)
> > +{
> > +	queue_delayed_work(system_power_efficient_wq, &info-
> > >dw_det, delay); }
> > +
> > +static irqreturn_t usb_conn_isr(int irq, void *dev_id) {
> > +	struct usb_conn_info *info = dev_id;
> > +
> > +	usb_conn_queue_dwork(info, info->debounce_jiffies);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int usb_conn_probe(struct platform_device *pdev) {
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *np = dev->of_node;
> > +	struct device_node *parent;
> > +	struct device_node *child;
> > +	struct usb_conn_info *info;
> > +	int ret = 0;
> > +
> > +	if (!np)
> > +		return -EINVAL;
> > +
> > +	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> > +	if (!info)
> > +		return -ENOMEM;
> > +
> > +	info->dev = dev;
> > +
> > +	child = of_get_child_by_name(np, "connector");
> > +	if (!child) {
> > +		dev_err(dev, "failed to find connector node\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	info->id_gpiod = devm_gpiod_get_from_of_node(
> > +				dev, child, "id-gpios", 0, GPIOD_IN, "idpin");
> > +	if (IS_ERR(info->id_gpiod)) {
> > +		of_node_put(child);
> > +		return PTR_ERR(info->id_gpiod);
> > +	}
> > +
> > +	info->vbus_gpiod = devm_gpiod_get_from_of_node(
> > +				dev, child, "vbus-gpios", 0, GPIOD_IN,
> > +				"vbuspin");
> > +	if (IS_ERR(info->vbus_gpiod)) {
> > +		of_node_put(child);
> > +		return PTR_ERR(info->vbus_gpiod);
> > +	}
> > +
> > +	if (!info->id_gpiod && !info->vbus_gpiod) {
> > +		dev_err(dev, "failed to get gpios\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	of_node_put(child);
> > +
> > +	if (info->id_gpiod)
> > +		ret = gpiod_set_debounce(info->id_gpiod,
> > USB_GPIO_DEB_US);
> > +	if (!ret && info->vbus_gpiod)
> > +		ret = gpiod_set_debounce(info->vbus_gpiod,
> > USB_GPIO_DEB_US);
> > +	if (ret < 0)
> > +		info->debounce_jiffies =
> > msecs_to_jiffies(USB_GPIO_DEB_MS);
> > +
> > +	INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable);
> > +
> > +	info->vbus = devm_regulator_get(dev, "vbus");
> > +	if (IS_ERR(info->vbus)) {
> > +		dev_err(dev, "failed to get vbus\n");
> > +		return PTR_ERR(info->vbus);
> > +	}
> > +
> > +	child = of_graph_get_endpoint_by_regs(np, -1, 0);
> > +	parent = of_graph_get_remote_port_parent(child);
> > +	info->role_sw =
> > fwnode_usb_role_switch_get(of_fwnode_handle(parent));
> > +	of_node_put(child);
> > +	of_node_put(parent);
> > +	if (IS_ERR(info->role_sw)) {
> > +		dev_err(dev, "failed to get role switch\n");
> > +		return PTR_ERR(info->role_sw);
> > +	}
> > +
> > +	if (info->id_gpiod) {
> > +		info->id_irq = gpiod_to_irq(info->id_gpiod);
> > +		if (info->id_irq < 0) {
> > +			dev_err(dev, "failed to get ID IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
Good catch, will fix it.

Thanks
> > +			return info->id_irq;
> > +		}
> > +
> > +		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
> > +						usb_conn_isr,
> > USB_CONN_IRQF,
> > +						pdev->name, info);
> > +		if (ret < 0) {
> > +			dev_err(dev, "failed to request ID IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	if (info->vbus_gpiod) {
> > +		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
> > +		if (info->vbus_irq < 0) {
> > +			dev_err(dev, "failed to get VBUS IRQ\n");
> May be usb_role_switch_put(info->role_sw);
> > +			return info->vbus_irq;
> > +		}
> > +
> > +		ret = devm_request_threaded_irq(dev, info->vbus_irq,
> > NULL,
> > +						usb_conn_isr,
> > USB_CONN_IRQF,
> > +						pdev->name, info);
> > +		if (ret < 0) {
> > +			dev_err(dev, "failed to request VBUS IRQ\n");
> May be usb_role_switch_put(info->role_sw); ??
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	platform_set_drvdata(pdev, info);
> > +
> > +	/* Perform initial detection */
> > +	usb_conn_queue_dwork(info, 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int usb_conn_remove(struct platform_device *pdev) {
> > +	struct usb_conn_info *info = platform_get_drvdata(pdev);
> > +
> > +	cancel_delayed_work_sync(&info->dw_det);
> > +
> > +	if (info->last_role == USB_ROLE_HOST)
> > +		regulator_disable(info->vbus);
> > +
> > +	usb_role_switch_put(info->role_sw);
> > +
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused usb_conn_suspend(struct device *dev) {
> > +	struct usb_conn_info *info = dev_get_drvdata(dev);
> > +
> > +	if (info->id_gpiod)
> > +		disable_irq(info->id_irq);
> > +	if (info->vbus_gpiod)
> > +		disable_irq(info->vbus_irq);
> > +
> > +	pinctrl_pm_select_sleep_state(dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused usb_conn_resume(struct device *dev) {
> > +	struct usb_conn_info *info = dev_get_drvdata(dev);
> > +
> > +	pinctrl_pm_select_default_state(dev);
> > +
> > +	if (info->id_gpiod)
> > +		enable_irq(info->id_irq);
> > +	if (info->vbus_gpiod)
> > +		enable_irq(info->vbus_irq);
> > +
> > +	usb_conn_queue_dwork(info, 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static SIMPLE_DEV_PM_OPS(usb_conn_pm_ops,
> > +			 usb_conn_suspend, usb_conn_resume);
> > +
> > +#define DEV_PMS_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ?
> > &usb_conn_pm_ops :
> > +NULL)
> > +
> > +static const struct of_device_id usb_conn_dt_match[] = {
> > +	{ .compatible = "linux,typeb-conn-gpio", },
> > +	{ }
> > +};
> > +MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
> > +
> > +static struct platform_driver usb_conn_driver = {
> > +	.probe		= usb_conn_probe,
> > +	.remove		= usb_conn_remove,
> > +	.driver		= {
> > +		.name	= "typeb-conn-gpio",
> > +		.pm	= DEV_PMS_OPS,
> > +		.of_match_table = usb_conn_dt_match,
> > +	},
> > +};
> > +
> > +module_platform_driver(usb_conn_driver);
> > +
> > +MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
> > +MODULE_DESCRIPTION("USB Type-B GPIO connector driver");
> > +MODULE_LICENSE("GPL v2");
> > --
> > 2.21.0
> 



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
  2019-04-26 20:49     ` [v4,3/6] " Rob Herring
  (?)
  (?)
@ 2019-04-28 12:16       ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28 12:16 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > Now the USB Role Switch is supported, so add properties about it
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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, 8 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > +	not extcon
> 
> Coordinate with the Renesas and HiSilicon folks implementing the same 
> thing and put this in a common spot. 
I'll prepare a patch for it, and CC Biju and Yu

> However, I think this should not 
> even be needed as knowing the controller capabilities (based on the 
> compatible) and knowing the type of connector should be enough 
> information to tell you if dual role is supported or not.
Some Dual-Role controller drivers already used extcon framework to
handle role switch, if try to support the new USB Role Switch framework,
the driver may want to know which way will be used.

Sometimes users also want to use dual-role even use the type-A, such as
use sys interface to handle role switch, so only knowing the connector
type can't tell driver which way to use
> 
> >   - 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 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
> > 



^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-28 12:16       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28 12:16 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > Now the USB Role Switch is supported, so add properties about it
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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, 8 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > +	not extcon
> 
> Coordinate with the Renesas and HiSilicon folks implementing the same 
> thing and put this in a common spot. 
I'll prepare a patch for it, and CC Biju and Yu

> However, I think this should not 
> even be needed as knowing the controller capabilities (based on the 
> compatible) and knowing the type of connector should be enough 
> information to tell you if dual role is supported or not.
Some Dual-Role controller drivers already used extcon framework to
handle role switch, if try to support the new USB Role Switch framework,
the driver may want to know which way will be used.

Sometimes users also want to use dual-role even use the type-A, such as
use sys interface to handle role switch, so only knowing the connector
type can't tell driver which way to use
> 
> >   - 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 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
> > 

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-28 12:16       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28 12:16 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, linux-usb, linux-arm-kernel, linux-mediatek,
	Biju Das, Linus Walleij

On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > Now the USB Role Switch is supported, so add properties about it
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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, 8 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > +	not extcon
> 
> Coordinate with the Renesas and HiSilicon folks implementing the same 
> thing and put this in a common spot. 
I'll prepare a patch for it, and CC Biju and Yu

> However, I think this should not 
> even be needed as knowing the controller capabilities (based on the 
> compatible) and knowing the type of connector should be enough 
> information to tell you if dual role is supported or not.
Some Dual-Role controller drivers already used extcon framework to
handle role switch, if try to support the new USB Role Switch framework,
the driver may want to know which way will be used.

Sometimes users also want to use dual-role even use the type-A, such as
use sys interface to handle role switch, so only knowing the connector
type can't tell driver which way to use
> 
> >   - 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 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
> >

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-28 12:16       ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-28 12:16 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Rutland, devicetree, Heikki Krogerus, Hans de Goede,
	Greg Kroah-Hartman, Linus Walleij, linux-usb, linux-kernel,
	Biju Das, Badhri Jagan Sridharan, Andy Shevchenko,
	linux-mediatek, Min Guo, Matthias Brugger, Adam Thomson,
	linux-arm-kernel, Li Jun

On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > Now the USB Role Switch is supported, so add properties about it
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > 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, 8 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > +	not extcon
> 
> Coordinate with the Renesas and HiSilicon folks implementing the same 
> thing and put this in a common spot. 
I'll prepare a patch for it, and CC Biju and Yu

> However, I think this should not 
> even be needed as knowing the controller capabilities (based on the 
> compatible) and knowing the type of connector should be enough 
> information to tell you if dual role is supported or not.
Some Dual-Role controller drivers already used extcon framework to
handle role switch, if try to support the new USB Role Switch framework,
the driver may want to know which way will be used.

Sometimes users also want to use dual-role even use the type-A, such as
use sys interface to handle role switch, so only knowing the connector
type can't tell driver which way to use
> 
> >   - 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 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
> > 



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
  2019-04-28 12:16       ` [PATCH v4 3/6] " Chunfeng Yun
  (?)
  (?)
@ 2019-04-29 16:25         ` Rob Herring
  -1 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-29 16:25 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, Linux USB List,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/Mediatek SoC support, Biju Das, Linus Walleij

On Sun, Apr 28, 2019 at 7:16 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
>
> On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> > On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > > Now the USB Role Switch is supported, so add properties about it
> > >
> > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > > ---
> > > 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, 8 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > > +   not extcon
> >
> > Coordinate with the Renesas and HiSilicon folks implementing the same
> > thing and put this in a common spot.
> I'll prepare a patch for it, and CC Biju and Yu
>
> > However, I think this should not
> > even be needed as knowing the controller capabilities (based on the
> > compatible) and knowing the type of connector should be enough
> > information to tell you if dual role is supported or not.
> Some Dual-Role controller drivers already used extcon framework to
> handle role switch, if try to support the new USB Role Switch framework,
> the driver may want to know which way will be used.

Wouldn't it know by presence of 'extcon' property or not?

> Sometimes users also want to use dual-role even use the type-A, such as
> use sys interface to handle role switch, so only knowing the connector
> type can't tell driver which way to use

That use case doesn't sound like something that should be in DT
though. That would be possible for any controller that supports
dual-role. Though perhaps that requires some specific Vbus wiring? Or
a cable with Vbus disconnected. Either way, doesn't sound USB
compliant.

Rob

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-29 16:25         ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-29 16:25 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, Linux USB List,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/Mediatek SoC support, Biju Das

On Sun, Apr 28, 2019 at 7:16 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
>
> On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> > On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > > Now the USB Role Switch is supported, so add properties about it
> > >
> > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > > ---
> > > 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, 8 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > > +   not extcon
> >
> > Coordinate with the Renesas and HiSilicon folks implementing the same
> > thing and put this in a common spot.
> I'll prepare a patch for it, and CC Biju and Yu
>
> > However, I think this should not
> > even be needed as knowing the controller capabilities (based on the
> > compatible) and knowing the type of connector should be enough
> > information to tell you if dual role is supported or not.
> Some Dual-Role controller drivers already used extcon framework to
> handle role switch, if try to support the new USB Role Switch framework,
> the driver may want to know which way will be used.

Wouldn't it know by presence of 'extcon' property or not?

> Sometimes users also want to use dual-role even use the type-A, such as
> use sys interface to handle role switch, so only knowing the connector
> type can't tell driver which way to use

That use case doesn't sound like something that should be in DT
though. That would be possible for any controller that supports
dual-role. Though perhaps that requires some specific Vbus wiring? Or
a cable with Vbus disconnected. Either way, doesn't sound USB
compliant.

Rob

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-29 16:25         ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-29 16:25 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, Linux USB List,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/Mediatek SoC support, Biju Das, Linus Walleij

On Sun, Apr 28, 2019 at 7:16 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
>
> On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> > On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > > Now the USB Role Switch is supported, so add properties about it
> > >
> > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > > ---
> > > 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, 8 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > > +   not extcon
> >
> > Coordinate with the Renesas and HiSilicon folks implementing the same
> > thing and put this in a common spot.
> I'll prepare a patch for it, and CC Biju and Yu
>
> > However, I think this should not
> > even be needed as knowing the controller capabilities (based on the
> > compatible) and knowing the type of connector should be enough
> > information to tell you if dual role is supported or not.
> Some Dual-Role controller drivers already used extcon framework to
> handle role switch, if try to support the new USB Role Switch framework,
> the driver may want to know which way will be used.

Wouldn't it know by presence of 'extcon' property or not?

> Sometimes users also want to use dual-role even use the type-A, such as
> use sys interface to handle role switch, so only knowing the connector
> type can't tell driver which way to use

That use case doesn't sound like something that should be in DT
though. That would be possible for any controller that supports
dual-role. Though perhaps that requires some specific Vbus wiring? Or
a cable with Vbus disconnected. Either way, doesn't sound USB
compliant.

Rob

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-29 16:25         ` Rob Herring
  0 siblings, 0 replies; 69+ messages in thread
From: Rob Herring @ 2019-04-29 16:25 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Mark Rutland, devicetree, Heikki Krogerus, Hans de Goede,
	Greg Kroah-Hartman, Linus Walleij, Linux USB List, linux-kernel,
	Biju Das, Badhri Jagan Sridharan, Andy Shevchenko,
	moderated list:ARM/Mediatek SoC support, Min Guo,
	Matthias Brugger, Adam Thomson,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE, Li Jun

On Sun, Apr 28, 2019 at 7:16 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
>
> On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> > On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > > Now the USB Role Switch is supported, so add properties about it
> > >
> > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > > ---
> > > 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, 8 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > > +   not extcon
> >
> > Coordinate with the Renesas and HiSilicon folks implementing the same
> > thing and put this in a common spot.
> I'll prepare a patch for it, and CC Biju and Yu
>
> > However, I think this should not
> > even be needed as knowing the controller capabilities (based on the
> > compatible) and knowing the type of connector should be enough
> > information to tell you if dual role is supported or not.
> Some Dual-Role controller drivers already used extcon framework to
> handle role switch, if try to support the new USB Role Switch framework,
> the driver may want to know which way will be used.

Wouldn't it know by presence of 'extcon' property or not?

> Sometimes users also want to use dual-role even use the type-A, such as
> use sys interface to handle role switch, so only knowing the connector
> type can't tell driver which way to use

That use case doesn't sound like something that should be in DT
though. That would be possible for any controller that supports
dual-role. Though perhaps that requires some specific Vbus wiring? Or
a cable with Vbus disconnected. Either way, doesn't sound USB
compliant.

Rob

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
  2019-04-29 16:25         ` [PATCH v4 3/6] " Rob Herring
  (?)
  (?)
@ 2019-04-30  6:57           ` Chunfeng Yun
  -1 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-30  6:57 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, Linux USB List,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/Mediatek SoC support, Biju Das, Linus Walleij

On Mon, 2019-04-29 at 11:25 -0500, Rob Herring wrote:
> On Sun, Apr 28, 2019 at 7:16 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
> >
> > On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> > > On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > > > Now the USB Role Switch is supported, so add properties about it
> > > >
> > > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > > > ---
> > > > 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, 8 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > > > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > > > +   not extcon
> > >
> > > Coordinate with the Renesas and HiSilicon folks implementing the same
> > > thing and put this in a common spot.
> > I'll prepare a patch for it, and CC Biju and Yu
> >
> > > However, I think this should not
> > > even be needed as knowing the controller capabilities (based on the
> > > compatible) and knowing the type of connector should be enough
> > > information to tell you if dual role is supported or not.
> > Some Dual-Role controller drivers already used extcon framework to
> > handle role switch, if try to support the new USB Role Switch framework,
> > the driver may want to know which way will be used.
> 
> Wouldn't it know by presence of 'extcon' property or not?

non-presence of 'extcon' doesn't mean the driver need USB Role Switch,
e.g. support manual role switch decided by user, of course, we can check
some cases and then decide whether need USB Role Switch or not, maybe
provide a property will make it easier.

> 
> > Sometimes users also want to use dual-role even use the type-A, such as
> > use sys interface to handle role switch, so only knowing the connector
> > type can't tell driver which way to use
> 
> That use case doesn't sound like something that should be in DT
> though. That would be possible for any controller that supports
> dual-role. 
I give manual role switch by sysfs interface a higher priority than
other ways, if manual switch is enabled, e.g. 'extcon' will be ignored.
this may be different from other USB dual-role controller drivers.

> Though perhaps that requires some specific Vbus wiring? Or
> a cable with Vbus disconnected. 
Yes, some projects use PMIC or Charger to detect Vbus, but some don't
have Vbus detection circuit, and some even don't provide vbus pin

> Either way, doesn't sound USB compliant.
Yes, it's more related with customer usage, or cost down, anyway, it's
better to support cases as many as possible.

> 
> Rob



^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-30  6:57           ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-30  6:57 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, Linux USB List,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/Mediatek SoC support, Biju Das

On Mon, 2019-04-29 at 11:25 -0500, Rob Herring wrote:
> On Sun, Apr 28, 2019 at 7:16 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
> >
> > On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> > > On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > > > Now the USB Role Switch is supported, so add properties about it
> > > >
> > > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > > > ---
> > > > 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, 8 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > > > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > > > +   not extcon
> > >
> > > Coordinate with the Renesas and HiSilicon folks implementing the same
> > > thing and put this in a common spot.
> > I'll prepare a patch for it, and CC Biju and Yu
> >
> > > However, I think this should not
> > > even be needed as knowing the controller capabilities (based on the
> > > compatible) and knowing the type of connector should be enough
> > > information to tell you if dual role is supported or not.
> > Some Dual-Role controller drivers already used extcon framework to
> > handle role switch, if try to support the new USB Role Switch framework,
> > the driver may want to know which way will be used.
> 
> Wouldn't it know by presence of 'extcon' property or not?

non-presence of 'extcon' doesn't mean the driver need USB Role Switch,
e.g. support manual role switch decided by user, of course, we can check
some cases and then decide whether need USB Role Switch or not, maybe
provide a property will make it easier.

> 
> > Sometimes users also want to use dual-role even use the type-A, such as
> > use sys interface to handle role switch, so only knowing the connector
> > type can't tell driver which way to use
> 
> That use case doesn't sound like something that should be in DT
> though. That would be possible for any controller that supports
> dual-role. 
I give manual role switch by sysfs interface a higher priority than
other ways, if manual switch is enabled, e.g. 'extcon' will be ignored.
this may be different from other USB dual-role controller drivers.

> Though perhaps that requires some specific Vbus wiring? Or
> a cable with Vbus disconnected. 
Yes, some projects use PMIC or Charger to detect Vbus, but some don't
have Vbus detection circuit, and some even don't provide vbus pin

> Either way, doesn't sound USB compliant.
Yes, it's more related with customer usage, or cost down, anyway, it's
better to support cases as many as possible.

> 
> Rob

^ permalink raw reply	[flat|nested] 69+ messages in thread

* [v4,3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-30  6:57           ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-30  6:57 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greg Kroah-Hartman, Heikki Krogerus, Mark Rutland,
	Matthias Brugger, Adam Thomson, Li Jun, Badhri Jagan Sridharan,
	Hans de Goede, Andy Shevchenko, Min Guo, devicetree,
	linux-kernel, Linux USB List,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	moderated list:ARM/Mediatek SoC support, Biju Das, Linus Walleij

On Mon, 2019-04-29 at 11:25 -0500, Rob Herring wrote:
> On Sun, Apr 28, 2019 at 7:16 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
> >
> > On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> > > On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > > > Now the USB Role Switch is supported, so add properties about it
> > > >
> > > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > > > ---
> > > > 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, 8 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > > > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > > > +   not extcon
> > >
> > > Coordinate with the Renesas and HiSilicon folks implementing the same
> > > thing and put this in a common spot.
> > I'll prepare a patch for it, and CC Biju and Yu
> >
> > > However, I think this should not
> > > even be needed as knowing the controller capabilities (based on the
> > > compatible) and knowing the type of connector should be enough
> > > information to tell you if dual role is supported or not.
> > Some Dual-Role controller drivers already used extcon framework to
> > handle role switch, if try to support the new USB Role Switch framework,
> > the driver may want to know which way will be used.
> 
> Wouldn't it know by presence of 'extcon' property or not?

non-presence of 'extcon' doesn't mean the driver need USB Role Switch,
e.g. support manual role switch decided by user, of course, we can check
some cases and then decide whether need USB Role Switch or not, maybe
provide a property will make it easier.

> 
> > Sometimes users also want to use dual-role even use the type-A, such as
> > use sys interface to handle role switch, so only knowing the connector
> > type can't tell driver which way to use
> 
> That use case doesn't sound like something that should be in DT
> though. That would be possible for any controller that supports
> dual-role. 
I give manual role switch by sysfs interface a higher priority than
other ways, if manual switch is enabled, e.g. 'extcon' will be ignored.
this may be different from other USB dual-role controller drivers.

> Though perhaps that requires some specific Vbus wiring? Or
> a cable with Vbus disconnected. 
Yes, some projects use PMIC or Charger to detect Vbus, but some don't
have Vbus detection circuit, and some even don't provide vbus pin

> Either way, doesn't sound USB compliant.
Yes, it's more related with customer usage, or cost down, anyway, it's
better to support cases as many as possible.

> 
> Rob

^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch
@ 2019-04-30  6:57           ` Chunfeng Yun
  0 siblings, 0 replies; 69+ messages in thread
From: Chunfeng Yun @ 2019-04-30  6:57 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Rutland, devicetree, Heikki Krogerus, Hans de Goede,
	Greg Kroah-Hartman, Linus Walleij, Linux USB List, linux-kernel,
	Biju Das, Badhri Jagan Sridharan, Andy Shevchenko,
	moderated list:ARM/Mediatek SoC support, Min Guo,
	Matthias Brugger, Adam Thomson,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE, Li Jun

On Mon, 2019-04-29 at 11:25 -0500, Rob Herring wrote:
> On Sun, Apr 28, 2019 at 7:16 AM Chunfeng Yun <chunfeng.yun@mediatek.com> wrote:
> >
> > On Fri, 2019-04-26 at 15:49 -0500, Rob Herring wrote:
> > > On Fri, Apr 26, 2019 at 02:47:14PM +0800, Chunfeng Yun wrote:
> > > > Now the USB Role Switch is supported, so add properties about it
> > > >
> > > > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > > > ---
> > > > 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, 8 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
> > > > index 3382b5cb471d..6e004c4a89af 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 switch, but
> > > > +   not extcon
> > >
> > > Coordinate with the Renesas and HiSilicon folks implementing the same
> > > thing and put this in a common spot.
> > I'll prepare a patch for it, and CC Biju and Yu
> >
> > > However, I think this should not
> > > even be needed as knowing the controller capabilities (based on the
> > > compatible) and knowing the type of connector should be enough
> > > information to tell you if dual role is supported or not.
> > Some Dual-Role controller drivers already used extcon framework to
> > handle role switch, if try to support the new USB Role Switch framework,
> > the driver may want to know which way will be used.
> 
> Wouldn't it know by presence of 'extcon' property or not?

non-presence of 'extcon' doesn't mean the driver need USB Role Switch,
e.g. support manual role switch decided by user, of course, we can check
some cases and then decide whether need USB Role Switch or not, maybe
provide a property will make it easier.

> 
> > Sometimes users also want to use dual-role even use the type-A, such as
> > use sys interface to handle role switch, so only knowing the connector
> > type can't tell driver which way to use
> 
> That use case doesn't sound like something that should be in DT
> though. That would be possible for any controller that supports
> dual-role. 
I give manual role switch by sysfs interface a higher priority than
other ways, if manual switch is enabled, e.g. 'extcon' will be ignored.
this may be different from other USB dual-role controller drivers.

> Though perhaps that requires some specific Vbus wiring? Or
> a cable with Vbus disconnected. 
Yes, some projects use PMIC or Charger to detect Vbus, but some don't
have Vbus detection circuit, and some even don't provide vbus pin

> Either way, doesn't sound USB compliant.
Yes, it's more related with customer usage, or cost down, anyway, it's
better to support cases as many as possible.

> 
> Rob



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 69+ messages in thread

end of thread, other threads:[~2019-04-30  6:58 UTC | newest]

Thread overview: 69+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-26  6:47 [v4 PATCH 0/6] add USB Type-B GPIO connector driver Chunfeng Yun
2019-04-26  6:47 ` Chunfeng Yun
2019-04-26  6:47 ` Chunfeng Yun
2019-04-26  6:47 ` [PATCH v4 1/6] dt-bindings: connector: add optional properties for Type-B Chunfeng Yun
2019-04-26  6:47   ` Chunfeng Yun
2019-04-26  6:47   ` [v4,1/6] " Chunfeng Yun
2019-04-26  6:47   ` [PATCH v4 1/6] " Chunfeng Yun
2019-04-26 13:19   ` Rob Herring
2019-04-26 13:19     ` Rob Herring
2019-04-26 13:19     ` [v4,1/6] " Rob Herring
2019-04-26 13:19     ` [PATCH v4 1/6] " Rob Herring
2019-04-26  6:47 ` [PATCH v4 2/6] dt-bindings: usb: add binding for Type-B GPIO connector driver Chunfeng Yun
2019-04-26  6:47   ` Chunfeng Yun
2019-04-26  6:47   ` [v4,2/6] " Chunfeng Yun
2019-04-26  6:47   ` [PATCH v4 2/6] " Chunfeng Yun
2019-04-26 20:45   ` Rob Herring
2019-04-26 20:45     ` Rob Herring
2019-04-26 20:45     ` [v4,2/6] " Rob Herring
2019-04-28  1:50     ` [PATCH v4 2/6] " Chunfeng Yun
2019-04-28  1:50       ` Chunfeng Yun
2019-04-28  1:50       ` [v4,2/6] " Chunfeng Yun
2019-04-28  1:50       ` [PATCH v4 2/6] " Chunfeng Yun
2019-04-26  6:47 ` [PATCH v4 3/6] dt-bindings: usb: mtu3: add properties about USB Role Switch Chunfeng Yun
2019-04-26  6:47   ` Chunfeng Yun
2019-04-26  6:47   ` [v4,3/6] " Chunfeng Yun
2019-04-26  6:47   ` [PATCH v4 3/6] " Chunfeng Yun
2019-04-26 20:49   ` Rob Herring
2019-04-26 20:49     ` Rob Herring
2019-04-26 20:49     ` [v4,3/6] " Rob Herring
2019-04-28 12:16     ` [PATCH v4 3/6] " Chunfeng Yun
2019-04-28 12:16       ` Chunfeng Yun
2019-04-28 12:16       ` [v4,3/6] " Chunfeng Yun
2019-04-28 12:16       ` [PATCH v4 3/6] " Chunfeng Yun
2019-04-29 16:25       ` Rob Herring
2019-04-29 16:25         ` Rob Herring
2019-04-29 16:25         ` [v4,3/6] " Rob Herring
2019-04-29 16:25         ` [PATCH v4 3/6] " Rob Herring
2019-04-30  6:57         ` Chunfeng Yun
2019-04-30  6:57           ` Chunfeng Yun
2019-04-30  6:57           ` [v4,3/6] " Chunfeng Yun
2019-04-30  6:57           ` [PATCH v4 3/6] " Chunfeng Yun
2019-04-26  6:47 ` [PATCH v4 4/6] usb: roles: add API to get usb_role_switch by node Chunfeng Yun
2019-04-26  6:47   ` Chunfeng Yun
2019-04-26  6:47   ` [v4,4/6] " Chunfeng Yun
2019-04-26  6:47   ` [PATCH v4 4/6] " Chunfeng Yun
2019-04-26  7:02   ` Biju Das
2019-04-26  7:02     ` Biju Das
2019-04-26  7:02     ` [v4,4/6] " Biju Das
2019-04-26  7:02     ` [PATCH v4 4/6] " Biju Das
2019-04-26  7:16     ` Chunfeng Yun
2019-04-26  7:16       ` Chunfeng Yun
2019-04-26  7:16       ` [v4,4/6] " Chunfeng Yun
2019-04-26  7:16       ` [PATCH v4 4/6] " Chunfeng Yun
2019-04-26  6:47 ` [PATCH v4 5/6] usb: roles: add USB Type-B GPIO connector driver Chunfeng Yun
2019-04-26  6:47   ` Chunfeng Yun
2019-04-26  6:47   ` [v4,5/6] " Chunfeng Yun
2019-04-26  6:47   ` [PATCH v4 5/6] " Chunfeng Yun
2019-04-26  9:22   ` Biju Das
2019-04-26  9:22     ` Biju Das
2019-04-26  9:22     ` [v4,5/6] " Biju Das
2019-04-26  9:22     ` [PATCH v4 5/6] " Biju Das
2019-04-28  9:26     ` Chunfeng Yun
2019-04-28  9:26       ` Chunfeng Yun
2019-04-28  9:26       ` [v4,5/6] " Chunfeng Yun
2019-04-28  9:26       ` [PATCH v4 5/6] " Chunfeng Yun
2019-04-26  6:47 ` [PATCH v4 6/6] usb: mtu3: register a USB Role Switch for dual role mode Chunfeng Yun
2019-04-26  6:47   ` Chunfeng Yun
2019-04-26  6:47   ` [v4,6/6] " Chunfeng Yun
2019-04-26  6:47   ` [PATCH v4 6/6] " Chunfeng Yun

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.