linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] typec switch via mux controller
@ 2021-05-19  7:14 Li Jun
  2021-05-19  7:14 ` [PATCH 1/4] dt-bindings: connector: Add typec orientation switch properties Li Jun
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Li Jun @ 2021-05-19  7:14 UTC (permalink / raw)
  To: heikki.krogerus, robh+dt, shawnguo
  Cc: gregkh, linux, linux-usb, linux-imx, jun.li, devicetree,
	linux-arm-kernel

This is a follow up patch set to enable typec orientation swtich
via a simple HW block(e.g. controlled by GPIOs), the implementation
is based on Rob's commment to use existing mux controller bindings,
typec port directly use mux controller consumer API, typec_switch
struct is not used.

Last discussion is here:
https://www.spinics.net/lists/linux-usb/msg205492.html

Li Jun (4):
  dt-bindings: connector: Add typec orientation switch properties
  usb: typec: use typec cap fwnode's of_node for typec port
  usb: typec: add typec orientation switch support via mux controller
  arm64: dts: imx8mp-evk: enable usb0 with typec connector

 .../bindings/connector/usb-connector.yaml     |  21 ++++
 arch/arm64/boot/dts/freescale/imx8mp-evk.dts  | 110 ++++++++++++++++++
 drivers/usb/typec/class.c                     |  28 ++++-
 drivers/usb/typec/class.h                     |   2 +
 drivers/usb/typec/mux.c                       |  34 ++++++
 include/linux/usb/typec_mux.h                 |   4 +
 6 files changed, 198 insertions(+), 1 deletion(-)

-- 
2.25.1


_______________________________________________
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] 14+ messages in thread

* [PATCH 1/4] dt-bindings: connector: Add typec orientation switch properties
  2021-05-19  7:14 [PATCH 0/4] typec switch via mux controller Li Jun
@ 2021-05-19  7:14 ` Li Jun
  2021-05-21  1:30   ` Rob Herring
  2021-05-19  7:14 ` [PATCH 2/4] usb: typec: use typec cap fwnode's of_node for typec port Li Jun
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: Li Jun @ 2021-05-19  7:14 UTC (permalink / raw)
  To: heikki.krogerus, robh+dt, shawnguo
  Cc: gregkh, linux, linux-usb, linux-imx, jun.li, devicetree,
	linux-arm-kernel

Typec orientation switch can be implementaed as a consumer of mux
controller, with this way, mux-control-name must be provided with
name "typec-orientation-switch", along with its 3 states value array
for none(high impedance), cc1, cc2.

Signed-off-by: Li Jun <jun.li@nxp.com>
---
 .../bindings/connector/usb-connector.yaml     | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml
index 32509b98142e..567183e199a3 100644
--- a/Documentation/devicetree/bindings/connector/usb-connector.yaml
+++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml
@@ -111,6 +111,24 @@ properties:
       - 1.5A
       - 3.0A
 
+  mux-controls:
+    description:
+      mux controller node to use for orientation switch selection.
+    maxItems: 1
+
+  mux-control-name:
+    items:
+      - const: typec-orientation-switch
+
+  mux-control-switch-states:
+    description: |
+      An ordered u32 array describing the mux state value for each typec
+      orientations: NONE(high impedance), CC1, CC2, if there is no HW mux
+      state for NONE, use value of CC1 or CC2 for it,
+    minItems: 3
+    maxItems: 3
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+
   # The following are optional properties for "usb-c-connector" with power
   # delivery support.
   source-pdos:
@@ -301,6 +319,9 @@ examples:
         sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
                      PDO_VAR(5000, 12000, 2000)>;
         op-sink-microwatt = <10000000>;
+        mux-controls = <&mux>;
+        mux-control-names = "typec-orientation-switch";
+        mux-control-switch-states = <2>, <0>, <1>;
       };
     };
 
-- 
2.25.1


_______________________________________________
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] 14+ messages in thread

* [PATCH 2/4] usb: typec: use typec cap fwnode's of_node for typec port
  2021-05-19  7:14 [PATCH 0/4] typec switch via mux controller Li Jun
  2021-05-19  7:14 ` [PATCH 1/4] dt-bindings: connector: Add typec orientation switch properties Li Jun
@ 2021-05-19  7:14 ` Li Jun
  2021-05-20 12:38   ` Heikki Krogerus
  2021-05-19  7:14 ` [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller Li Jun
  2021-05-19  7:14 ` [PATCH 4/4] arm64: dts: imx8mp-evk: enable usb0 with typec connector Li Jun
  3 siblings, 1 reply; 14+ messages in thread
From: Li Jun @ 2021-05-19  7:14 UTC (permalink / raw)
  To: heikki.krogerus, robh+dt, shawnguo
  Cc: gregkh, linux, linux-usb, linux-imx, jun.li, devicetree,
	linux-arm-kernel

Asssign typec cap fwnode's of_node to typec port, then we can use
typec port device to get properties from its OF.

Signed-off-by: Li Jun <jun.li@nxp.com>
---
 drivers/usb/typec/class.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index b9429c9f65f6..a29bf2c32233 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -8,6 +8,7 @@
 
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/property.h>
 #include <linux/slab.h>
 #include <linux/usb/pd_vdo.h>
@@ -2049,6 +2050,7 @@ struct typec_port *typec_register_port(struct device *parent,
 	port->dev.class = &typec_class;
 	port->dev.parent = parent;
 	port->dev.fwnode = cap->fwnode;
+	port->dev.of_node = to_of_node(cap->fwnode);
 	port->dev.type = &typec_port_dev_type;
 	dev_set_name(&port->dev, "port%d", id);
 	dev_set_drvdata(&port->dev, cap->driver_data);
-- 
2.25.1


_______________________________________________
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] 14+ messages in thread

* [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller
  2021-05-19  7:14 [PATCH 0/4] typec switch via mux controller Li Jun
  2021-05-19  7:14 ` [PATCH 1/4] dt-bindings: connector: Add typec orientation switch properties Li Jun
  2021-05-19  7:14 ` [PATCH 2/4] usb: typec: use typec cap fwnode's of_node for typec port Li Jun
@ 2021-05-19  7:14 ` Li Jun
  2021-05-20 12:33   ` Heikki Krogerus
  2021-05-19  7:14 ` [PATCH 4/4] arm64: dts: imx8mp-evk: enable usb0 with typec connector Li Jun
  3 siblings, 1 reply; 14+ messages in thread
From: Li Jun @ 2021-05-19  7:14 UTC (permalink / raw)
  To: heikki.krogerus, robh+dt, shawnguo
  Cc: gregkh, linux, linux-usb, linux-imx, jun.li, devicetree,
	linux-arm-kernel

Some dedicated mux block can use existing mux controller as a
mux provider, typec port as a consumer to select channel for
orientation switch, this can be an alternate way to current
typec_switch interface.

Signed-off-by: Li Jun <jun.li@nxp.com>
---
 drivers/usb/typec/class.c     | 26 +++++++++++++++++++++++++-
 drivers/usb/typec/class.h     |  2 ++
 drivers/usb/typec/mux.c       | 34 ++++++++++++++++++++++++++++++++++
 include/linux/usb/typec_mux.h |  4 ++++
 4 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index a29bf2c32233..1bb0275e6204 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -1601,6 +1601,7 @@ static void typec_release(struct device *dev)
 	ida_simple_remove(&typec_index_ida, port->id);
 	ida_destroy(&port->mode_ids);
 	typec_switch_put(port->sw);
+	typec_mux_control_switch_put(port->mux_control_switch);
 	typec_mux_put(port->mux);
 	kfree(port->cap);
 	kfree(port);
@@ -1816,6 +1817,13 @@ int typec_set_orientation(struct typec_port *port,
 	if (ret)
 		return ret;
 
+	if (!port->sw) {
+		ret = typec_mux_control_switch_set(port->mux_control_switch,
+				port->mux_control_switch_states[orientation]);
+		if (ret)
+			return ret;
+	}
+
 	port->orientation = orientation;
 	sysfs_notify(&port->dev.kobj, NULL, "orientation");
 	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
@@ -1991,7 +1999,7 @@ struct typec_port *typec_register_port(struct device *parent,
 				       const struct typec_capability *cap)
 {
 	struct typec_port *port;
-	int ret;
+	int ret = 0;
 	int id;
 
 	port = kzalloc(sizeof(*port), GFP_KERNEL);
@@ -2068,6 +2076,22 @@ struct typec_port *typec_register_port(struct device *parent,
 		return ERR_PTR(ret);
 	}
 
+	if (!port->sw) {
+		/* Try to get typec switch via general mux controller */
+		port->mux_control_switch = typec_mux_control_switch_get(&port->dev);
+		if (IS_ERR(port->mux_control_switch))
+			ret = PTR_ERR(port->mux_control_switch);
+		else if (port->mux_control_switch)
+			ret = device_property_read_u32_array(&port->dev,
+					"mux-control-switch-states",
+					port->mux_control_switch_states,
+					3);
+		if (ret) {
+			put_device(&port->dev);
+			return ERR_PTR(ret);
+		}
+	}
+
 	port->mux = typec_mux_get(&port->dev, NULL);
 	if (IS_ERR(port->mux)) {
 		ret = PTR_ERR(port->mux);
diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h
index aef03eb7e152..15dad2621c83 100644
--- a/drivers/usb/typec/class.h
+++ b/drivers/usb/typec/class.h
@@ -50,6 +50,8 @@ struct typec_port {
 
 	enum typec_orientation		orientation;
 	struct typec_switch		*sw;
+	struct mux_control		*mux_control_switch;
+	int				mux_control_switch_states[3];
 	struct typec_mux		*mux;
 
 	const struct typec_capability	*cap;
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index 9da22ae3006c..6c5c4f07286d 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -11,6 +11,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/mux/consumer.h>
 #include <linux/property.h>
 #include <linux/slab.h>
 
@@ -176,6 +177,39 @@ void *typec_switch_get_drvdata(struct typec_switch *sw)
 }
 EXPORT_SYMBOL_GPL(typec_switch_get_drvdata);
 
+struct mux_control *typec_mux_control_switch_get(struct device *dev)
+{
+	if (!device_property_present(dev, "mux-control-names"))
+		return NULL;
+
+	return mux_control_get(dev, "typec-orientation-switch");
+}
+EXPORT_SYMBOL_GPL(typec_mux_control_switch_get);
+
+int typec_mux_control_switch_set(struct mux_control *mc_sw, int state)
+{
+	int ret;
+
+	if (!mc_sw)
+		return 0;
+
+	ret = mux_control_deselect(mc_sw);
+	if (ret)
+		return ret;
+
+	return mux_control_select(mc_sw, state);
+}
+EXPORT_SYMBOL_GPL(typec_mux_control_switch_set);
+
+void typec_mux_control_switch_put(struct mux_control *mc_sw)
+{
+	if (!mc_sw)
+		return;
+
+	return mux_control_put(mc_sw);
+}
+EXPORT_SYMBOL_GPL(typec_mux_control_switch_put);
+
 /* ------------------------------------------------------------------------- */
 
 static int mux_fwnode_match(struct device *dev, const void *fwnode)
diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
index a9d9957933dc..e0933e205b80 100644
--- a/include/linux/usb/typec_mux.h
+++ b/include/linux/usb/typec_mux.h
@@ -27,6 +27,10 @@ void typec_switch_put(struct typec_switch *sw);
 int typec_switch_set(struct typec_switch *sw,
 		     enum typec_orientation orientation);
 
+struct mux_control *typec_mux_control_switch_get(struct device *dev);
+int typec_mux_control_switch_set(struct mux_control *mc_sw, int state);
+void typec_mux_control_switch_put(struct mux_control *mc_sw);
+
 static inline struct typec_switch *typec_switch_get(struct device *dev)
 {
 	return fwnode_typec_switch_get(dev_fwnode(dev));
-- 
2.25.1


_______________________________________________
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] 14+ messages in thread

* [PATCH 4/4] arm64: dts: imx8mp-evk: enable usb0 with typec connector
  2021-05-19  7:14 [PATCH 0/4] typec switch via mux controller Li Jun
                   ` (2 preceding siblings ...)
  2021-05-19  7:14 ` [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller Li Jun
@ 2021-05-19  7:14 ` Li Jun
  3 siblings, 0 replies; 14+ messages in thread
From: Li Jun @ 2021-05-19  7:14 UTC (permalink / raw)
  To: heikki.krogerus, robh+dt, shawnguo
  Cc: gregkh, linux, linux-usb, linux-imx, jun.li, devicetree,
	linux-arm-kernel

The first usb port on imx8mp evk board has typec connector,
it has dual data role and dual power role with power delivery
support.

Signed-off-by: Li Jun <jun.li@nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 110 +++++++++++++++++++
 1 file changed, 110 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
index 2c28e589677e..c69514910eb9 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 
+#include <dt-bindings/usb/pd.h>
 #include "imx8mp.dtsi"
 
 / {
@@ -65,6 +66,22 @@ reg_usdhc2_vmmc: regulator-usdhc2 {
 		gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	mux: mux-controller {
+		compatible = "gpio-mux";
+		#mux-control-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_typec_mux>;
+		mux-gpios = <&gpio4 20 GPIO_ACTIVE_HIGH>,
+			    <&gpio2 20 GPIO_ACTIVE_HIGH>;
+		idle-state = <2>;
+
+		port {
+			usb3_data_ss: endpoint {
+				remote-endpoint = <&typec_con_ss>;
+			};
+		};
+	};
 };
 
 &flexcan1 {
@@ -104,6 +121,56 @@ ethphy1: ethernet-phy@1 {
 	};
 };
 
+&i2c2 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	ptn5110: tcpc@50 {
+		compatible = "nxp,ptn5110";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_typec>;
+		reg = <0x50>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <19 8>;
+
+		port {
+			typec_dr_sw: endpoint {
+				remote-endpoint = <&usb3_drd_sw>;
+			};
+		};
+
+		usb_con: connector {
+			compatible = "usb-c-connector";
+			label = "USB-C";
+			power-role = "dual";
+			data-role = "dual";
+			try-power-role = "sink";
+			source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+			sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
+				     PDO_VAR(5000, 20000, 3000)>;
+			op-sink-microwatt = <15000000>;
+			self-powered;
+			mux-controls = <&mux>;
+			mux-control-names = "typec-orientation-switch";
+			mux-control-switch-states = <2>, <0>, <1>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@1 {
+					reg = <1>;
+					typec_con_ss: endpoint {
+						remote-endpoint = <&usb3_data_ss>;
+					};
+				};
+			};
+		};
+	};
+};
+
 &i2c3 {
 	clock-frequency = <400000>;
 	pinctrl-names = "default";
@@ -137,6 +204,29 @@ &usb3_1 {
 	status = "okay";
 };
 
+&usb3_phy0 {
+	status = "okay";
+};
+
+&usb3_0 {
+	status = "okay";
+};
+
+&usb_dwc3_0 {
+	dr_mode = "otg";
+	hnp-disable;
+	srp-disable;
+	adp-disable;
+	usb-role-switch;
+	status = "okay";
+
+	port {
+		usb3_drd_sw: endpoint {
+			remote-endpoint = <&typec_dr_sw>;
+		};
+	};
+};
+
 &usb_dwc3_1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usb1_vbus>;
@@ -229,6 +319,13 @@ MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16	0x19
 		>;
 	};
 
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL		0x400001c3
+			MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA		0x400001c3
+		>;
+	};
+
 	pinctrl_i2c3: i2c3grp {
 		fsl,pins = <
 			MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL		0x400001c3
@@ -242,6 +339,19 @@ MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19	0x41
 		>;
 	};
 
+	pinctrl_typec: typec1grp {
+		fsl,pins = <
+			MX8MP_IOMUXC_SAI1_TXD7__GPIO4_IO19	0x1c4
+		>;
+	};
+
+	pinctrl_typec_mux: typec1muxgrp {
+		fsl,pins = <
+			MX8MP_IOMUXC_SAI1_MCLK__GPIO4_IO20	0x16
+			MX8MP_IOMUXC_SD2_WP__GPIO2_IO20		0x16
+		>;
+	};
+
 	pinctrl_uart2: uart2grp {
 		fsl,pins = <
 			MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX	0x49
-- 
2.25.1


_______________________________________________
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] 14+ messages in thread

* Re: [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller
  2021-05-19  7:14 ` [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller Li Jun
@ 2021-05-20 12:33   ` Heikki Krogerus
  2021-05-21  8:37     ` Heikki Krogerus
  2021-05-21 13:02     ` Jun Li
  0 siblings, 2 replies; 14+ messages in thread
From: Heikki Krogerus @ 2021-05-20 12:33 UTC (permalink / raw)
  To: Li Jun
  Cc: robh+dt, shawnguo, gregkh, linux, linux-usb, linux-imx,
	devicetree, linux-arm-kernel

On Wed, May 19, 2021 at 03:14:49PM +0800, Li Jun wrote:
> Some dedicated mux block can use existing mux controller as a
> mux provider, typec port as a consumer to select channel for
> orientation switch, this can be an alternate way to current
> typec_switch interface.
> 
> Signed-off-by: Li Jun <jun.li@nxp.com>
> ---
>  drivers/usb/typec/class.c     | 26 +++++++++++++++++++++++++-
>  drivers/usb/typec/class.h     |  2 ++
>  drivers/usb/typec/mux.c       | 34 ++++++++++++++++++++++++++++++++++
>  include/linux/usb/typec_mux.h |  4 ++++
>  4 files changed, 65 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
> index a29bf2c32233..1bb0275e6204 100644
> --- a/drivers/usb/typec/class.c
> +++ b/drivers/usb/typec/class.c
> @@ -1601,6 +1601,7 @@ static void typec_release(struct device *dev)
>  	ida_simple_remove(&typec_index_ida, port->id);
>  	ida_destroy(&port->mode_ids);
>  	typec_switch_put(port->sw);
> +	typec_mux_control_switch_put(port->mux_control_switch);
>  	typec_mux_put(port->mux);
>  	kfree(port->cap);
>  	kfree(port);
> @@ -1816,6 +1817,13 @@ int typec_set_orientation(struct typec_port *port,
>  	if (ret)
>  		return ret;
>  
> +	if (!port->sw) {
> +		ret = typec_mux_control_switch_set(port->mux_control_switch,
> +				port->mux_control_switch_states[orientation]);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	port->orientation = orientation;
>  	sysfs_notify(&port->dev.kobj, NULL, "orientation");
>  	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE);
> @@ -1991,7 +1999,7 @@ struct typec_port *typec_register_port(struct device *parent,
>  				       const struct typec_capability *cap)
>  {
>  	struct typec_port *port;
> -	int ret;
> +	int ret = 0;
>  	int id;
>  
>  	port = kzalloc(sizeof(*port), GFP_KERNEL);
> @@ -2068,6 +2076,22 @@ struct typec_port *typec_register_port(struct device *parent,
>  		return ERR_PTR(ret);
>  	}
>  
> +	if (!port->sw) {
> +		/* Try to get typec switch via general mux controller */
> +		port->mux_control_switch = typec_mux_control_switch_get(&port->dev);
> +		if (IS_ERR(port->mux_control_switch))
> +			ret = PTR_ERR(port->mux_control_switch);
> +		else if (port->mux_control_switch)
> +			ret = device_property_read_u32_array(&port->dev,
> +					"mux-control-switch-states",
> +					port->mux_control_switch_states,
> +					3);
> +		if (ret) {
> +			put_device(&port->dev);
> +			return ERR_PTR(ret);
> +		}
> +	}

Why not just do that inside fwnode_typec_switch_get() and handle the
whole thing in drivers/usb/typec/mux.c (or in its own file if you
prefer)?

You'll just need to register a "wrapper" Type-C switch object for the
OF mux controller, but that should not be a problem. That way you
don't need to export any new functions, touch this file or anything
else.


thanks,

-- 
heikki

_______________________________________________
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] 14+ messages in thread

* Re: [PATCH 2/4] usb: typec: use typec cap fwnode's of_node for typec port
  2021-05-19  7:14 ` [PATCH 2/4] usb: typec: use typec cap fwnode's of_node for typec port Li Jun
@ 2021-05-20 12:38   ` Heikki Krogerus
  0 siblings, 0 replies; 14+ messages in thread
From: Heikki Krogerus @ 2021-05-20 12:38 UTC (permalink / raw)
  To: Li Jun
  Cc: robh+dt, shawnguo, gregkh, linux, linux-usb, linux-imx,
	devicetree, linux-arm-kernel

On Wed, May 19, 2021 at 03:14:48PM +0800, Li Jun wrote:
> Asssign typec cap fwnode's of_node to typec port, then we can use
> typec port device to get properties from its OF.
> 
> Signed-off-by: Li Jun <jun.li@nxp.com>
> ---
>  drivers/usb/typec/class.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
> index b9429c9f65f6..a29bf2c32233 100644
> --- a/drivers/usb/typec/class.c
> +++ b/drivers/usb/typec/class.c
> @@ -8,6 +8,7 @@
>  
>  #include <linux/module.h>
>  #include <linux/mutex.h>
> +#include <linux/of.h>
>  #include <linux/property.h>
>  #include <linux/slab.h>
>  #include <linux/usb/pd_vdo.h>
> @@ -2049,6 +2050,7 @@ struct typec_port *typec_register_port(struct device *parent,
>  	port->dev.class = &typec_class;
>  	port->dev.parent = parent;
>  	port->dev.fwnode = cap->fwnode;
> +	port->dev.of_node = to_of_node(cap->fwnode);
>  	port->dev.type = &typec_port_dev_type;
>  	dev_set_name(&port->dev, "port%d", id);
>  	dev_set_drvdata(&port->dev, cap->driver_data);

No. I think this is what you want to do:

diff --git a/drivers/mux/core.c b/drivers/mux/core.c
index 1fb22388e7e07..e30e8504c1d6d 100644
--- a/drivers/mux/core.c
+++ b/drivers/mux/core.c
@@ -424,7 +424,7 @@ static struct mux_chip *of_find_mux_chip_by_node(struct device_node *np)
  */
 struct mux_control *mux_control_get(struct device *dev, const char *mux_name)
 {
-       struct device_node *np = dev->of_node;
+       struct device_node *np = to_of_node(dev_fwnode(dev));
        struct of_phandle_args args;
        struct mux_chip *mux_chip;
        unsigned int controller;

thanks,

-- 
heikki

_______________________________________________
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] 14+ messages in thread

* Re: [PATCH 1/4] dt-bindings: connector: Add typec orientation switch properties
  2021-05-19  7:14 ` [PATCH 1/4] dt-bindings: connector: Add typec orientation switch properties Li Jun
@ 2021-05-21  1:30   ` Rob Herring
  2021-05-25 11:48     ` Jun Li
  0 siblings, 1 reply; 14+ messages in thread
From: Rob Herring @ 2021-05-21  1:30 UTC (permalink / raw)
  To: Li Jun
  Cc: heikki.krogerus, shawnguo, gregkh, linux, linux-usb, linux-imx,
	devicetree, linux-arm-kernel

On Wed, May 19, 2021 at 03:14:47PM +0800, Li Jun wrote:
> Typec orientation switch can be implementaed as a consumer of mux
> controller, with this way, mux-control-name must be provided with
> name "typec-orientation-switch", along with its 3 states value array
> for none(high impedance), cc1, cc2.
> 
> Signed-off-by: Li Jun <jun.li@nxp.com>
> ---
>  .../bindings/connector/usb-connector.yaml     | 21 +++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml
> index 32509b98142e..567183e199a3 100644
> --- a/Documentation/devicetree/bindings/connector/usb-connector.yaml
> +++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml
> @@ -111,6 +111,24 @@ properties:
>        - 1.5A
>        - 3.0A
>  
> +  mux-controls:
> +    description:
> +      mux controller node to use for orientation switch selection.
> +    maxItems: 1
> +
> +  mux-control-name:
> +    items:
> +      - const: typec-orientation-switch

Don't really need a name with only 1 entry.

> +
> +  mux-control-switch-states:

Not really part of the 'mux-control' binding, but part of the connector. 
So 'typec-orientation-switch-states' or something.

> +    description: |
> +      An ordered u32 array describing the mux state value for each typec
> +      orientations: NONE(high impedance), CC1, CC2, if there is no HW mux
> +      state for NONE, use value of CC1 or CC2 for it,
> +    minItems: 3
> +    maxItems: 3
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +
>    # The following are optional properties for "usb-c-connector" with power
>    # delivery support.
>    source-pdos:
> @@ -301,6 +319,9 @@ examples:
>          sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
>                       PDO_VAR(5000, 12000, 2000)>;
>          op-sink-microwatt = <10000000>;
> +        mux-controls = <&mux>;
> +        mux-control-names = "typec-orientation-switch";
> +        mux-control-switch-states = <2>, <0>, <1>;
>        };
>      };
>  
> -- 
> 2.25.1
> 

_______________________________________________
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] 14+ messages in thread

* Re: [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller
  2021-05-20 12:33   ` Heikki Krogerus
@ 2021-05-21  8:37     ` Heikki Krogerus
  2021-05-25 11:46       ` Jun Li
  2021-05-21 13:02     ` Jun Li
  1 sibling, 1 reply; 14+ messages in thread
From: Heikki Krogerus @ 2021-05-21  8:37 UTC (permalink / raw)
  To: Li Jun
  Cc: robh+dt, shawnguo, gregkh, linux, linux-usb, linux-imx,
	devicetree, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 764 bytes --]

Hi,

On Thu, May 20, 2021 at 03:33:36PM +0300, Heikki Krogerus wrote:
> Why not just do that inside fwnode_typec_switch_get() and handle the
> whole thing in drivers/usb/typec/mux.c (or in its own file if you
> prefer)?
> 
> You'll just need to register a "wrapper" Type-C switch object for the
> OF mux controller, but that should not be a problem. That way you
> don't need to export any new functions, touch this file or anything
> else.

I wrote a bit of code just to see how that would look. I'm attaching
you the hack I made. I guess something like that would not be too bad.
A wrapper is probable always a bit clumsy, but I'm not sure that in
this case it's a huge problem. Of course if there are any better
ideas, let's here them :-)


thanks,

-- 
heikki

[-- Attachment #2: 0001-usb-typec-mux-Add-wrapper-for-OF-mux-controllers-tha.patch --]
[-- Type: text/plain, Size: 5213 bytes --]

From bdd63f82788fe95e056ed85ece939e41cfb862ad Mon Sep 17 00:00:00 2001
From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Date: Fri, 21 May 2021 10:42:23 +0300
Subject: [PATCH] usb: typec: mux: Add wrapper for OF mux controllers that
 handle orientation

Interim. Experiment only.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
 drivers/usb/typec/Makefile |  1 +
 drivers/usb/typec/mux.c    | 13 +++--
 drivers/usb/typec/mux.h    | 15 ++++++
 drivers/usb/typec/of_mux.c | 97 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 122 insertions(+), 4 deletions(-)
 create mode 100644 drivers/usb/typec/of_mux.c

diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index a0adb8947a301..d85231b2fe10b 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_TYPEC)		+= typec.o
 typec-y				:= class.o mux.o bus.o port-mapper.o
+typec-$(MULTIPLEXER)		+= of_mux.o
 obj-$(CONFIG_TYPEC)		+= altmodes/
 obj-$(CONFIG_TYPEC_TCPM)	+= tcpm/
 obj-$(CONFIG_TYPEC_UCSI)	+= ucsi/
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index 9da22ae3006c9..282622276d97b 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -63,6 +63,9 @@ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode)
 
 	sw = fwnode_connection_find_match(fwnode, "orientation-switch", NULL,
 					  typec_switch_match);
+	if (!sw)
+		sw = of_switch_register(fwnode);
+
 	if (!IS_ERR_OR_NULL(sw))
 		WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
 
@@ -78,10 +81,12 @@ EXPORT_SYMBOL_GPL(fwnode_typec_switch_get);
  */
 void typec_switch_put(struct typec_switch *sw)
 {
-	if (!IS_ERR_OR_NULL(sw)) {
-		module_put(sw->dev.parent->driver->owner);
-		put_device(&sw->dev);
-	}
+	if (IS_ERR_OR_NULL(sw))
+		return;
+
+	module_put(sw->dev.parent->driver->owner);
+	of_switch_unregister(sw);
+	put_device(&sw->dev);
 }
 EXPORT_SYMBOL_GPL(typec_switch_put);
 
diff --git a/drivers/usb/typec/mux.h b/drivers/usb/typec/mux.h
index 4fd9426ee44f6..c99caab766313 100644
--- a/drivers/usb/typec/mux.h
+++ b/drivers/usb/typec/mux.h
@@ -5,8 +5,11 @@
 
 #include <linux/usb/typec_mux.h>
 
+struct of_switch;
+
 struct typec_switch {
 	struct device dev;
+	struct of_switch *osw;
 	typec_switch_set_fn_t set;
 };
 
@@ -18,4 +21,16 @@ struct typec_mux {
 #define to_typec_switch(_dev_) container_of(_dev_, struct typec_switch, dev)
 #define to_typec_mux(_dev_) container_of(_dev_, struct typec_mux, dev)
 
+#ifdef CONFIG_MULTIPLEXER
+struct typec_switch *of_switch_register(struct fwnode_handle *fwnode);
+void of_switch_unregister(struct typec_switch *sw);
+#else
+static inline struct typec_switch *of_switch_register(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+static inline void of_switch_unregister(struct typec_switch *sw) { }
+#endif /* MULTIPLEXER */
+
 #endif /* __USB_TYPEC_MUX__ */
diff --git a/drivers/usb/typec/of_mux.c b/drivers/usb/typec/of_mux.c
new file mode 100644
index 0000000000000..48686a92331d7
--- /dev/null
+++ b/drivers/usb/typec/of_mux.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Wrapper for mux controllers handling orientation
+ *
+ * Copyright (C) 2021 Intel Corporation
+ */
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/mux/consumer.h>
+#include <linux/usb/typec_mux.h>
+
+#include "mux.h"
+
+struct of_switch {
+	struct mux_control *mc;
+	unsigned int state[3];
+};
+
+static int of_switch_set(struct typec_switch *sw, enum typec_orientation orientation)
+{
+	int ret;
+
+	/* Checking has the switch been unregistered - just not released yet */
+	if (!sw->osw)
+		return -ENODEV;
+
+	ret = mux_control_deselect(sw->osw->mc);
+	if (ret)
+		return ret;
+
+	return mux_control_select(sw->osw->mc, sw->osw->state[orientation]);
+}
+
+struct typec_switch *of_switch_register(struct fwnode_handle *fwnode)
+{
+	struct typec_switch_desc desc;
+	struct typec_switch *sw;
+	struct mux_control *mc;
+	unsigned int state[3];
+	struct of_switch *osw;
+	int ret;
+
+	if (!fwnode_property_present(fwnode, "mux-control-names"))
+		return NULL;
+
+	ret = fwnode_property_read_u32_array(fwnode, "mux-control-switch-states",
+					     state, 3);
+	if (ret)
+		return ERR_PTR(ret);
+
+	desc.fwnode = fwnode;
+	desc.set = of_switch_set;
+	desc.name = fwnode_get_name(fwnode);
+	desc.drvdata = NULL;
+
+	sw = typec_switch_register(NULL, &desc);
+	if (IS_ERR(sw))
+		return sw;
+
+	sw->dev.of_node = to_of_node(fwnode);
+
+	mc = mux_control_get(&sw->dev, "typec-orientation-switch");
+	if (IS_ERR_OR_NULL(mc)) {
+		typec_switch_unregister(sw);
+		if (IS_ERR(mc))
+			return ERR_CAST(mc);
+		return ERR_PTR(-ENODEV);
+	}
+
+	osw = kzalloc(sizeof(osw), GFP_KERNEL);
+	if (!osw) {
+		typec_switch_unregister(sw);
+		mux_control_put(mc);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	memcpy(osw->state, state, sizeof(unsigned int) * 3);
+	osw->mc = mc;
+	sw->osw = osw;
+
+	return sw;
+}
+
+void of_switch_unregister(struct typec_switch *sw)
+{
+	struct of_switch *osw = sw->osw;
+
+	if (!osw)
+		return;
+
+	sw->osw = NULL;
+	typec_switch_unregister(sw);
+	mux_control_put(osw->mc);
+	kfree(osw);
+}
-- 
2.30.2


[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

_______________________________________________
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] 14+ messages in thread

* RE: [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller
  2021-05-20 12:33   ` Heikki Krogerus
  2021-05-21  8:37     ` Heikki Krogerus
@ 2021-05-21 13:02     ` Jun Li
  1 sibling, 0 replies; 14+ messages in thread
From: Jun Li @ 2021-05-21 13:02 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: robh+dt, shawnguo, gregkh, linux, linux-usb, dl-linux-imx,
	devicetree, linux-arm-kernel



> -----Original Message-----
> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Sent: Thursday, May 20, 2021 8:34 PM
> To: Jun Li <jun.li@nxp.com>
> Cc: robh+dt@kernel.org; shawnguo@kernel.org; gregkh@linuxfoundation.org;
> linux@roeck-us.net; linux-usb@vger.kernel.org; dl-linux-imx
> <linux-imx@nxp.com>; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH 3/4] usb: typec: add typec orientation switch support
> via mux controller
> 
> On Wed, May 19, 2021 at 03:14:49PM +0800, Li Jun wrote:
> > Some dedicated mux block can use existing mux controller as a mux
> > provider, typec port as a consumer to select channel for orientation
> > switch, this can be an alternate way to current typec_switch
> > interface.
> >
> > Signed-off-by: Li Jun <jun.li@nxp.com>
> > ---
> >  drivers/usb/typec/class.c     | 26 +++++++++++++++++++++++++-
> >  drivers/usb/typec/class.h     |  2 ++
> >  drivers/usb/typec/mux.c       | 34 ++++++++++++++++++++++++++++++++++
> >  include/linux/usb/typec_mux.h |  4 ++++
> >  4 files changed, 65 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
> > index a29bf2c32233..1bb0275e6204 100644
> > --- a/drivers/usb/typec/class.c
> > +++ b/drivers/usb/typec/class.c
> > @@ -1601,6 +1601,7 @@ static void typec_release(struct device *dev)
> >  	ida_simple_remove(&typec_index_ida, port->id);
> >  	ida_destroy(&port->mode_ids);
> >  	typec_switch_put(port->sw);
> > +	typec_mux_control_switch_put(port->mux_control_switch);
> >  	typec_mux_put(port->mux);
> >  	kfree(port->cap);
> >  	kfree(port);
> > @@ -1816,6 +1817,13 @@ int typec_set_orientation(struct typec_port *port,
> >  	if (ret)
> >  		return ret;
> >
> > +	if (!port->sw) {
> > +		ret = typec_mux_control_switch_set(port->mux_control_switch,
> > +				port->mux_control_switch_states[orientation]);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> >  	port->orientation = orientation;
> >  	sysfs_notify(&port->dev.kobj, NULL, "orientation");
> >  	kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); @@ -1991,7 +1999,7 @@
> > struct typec_port *typec_register_port(struct device *parent,
> >  				       const struct typec_capability *cap)  {
> >  	struct typec_port *port;
> > -	int ret;
> > +	int ret = 0;
> >  	int id;
> >
> >  	port = kzalloc(sizeof(*port), GFP_KERNEL); @@ -2068,6 +2076,22 @@
> > struct typec_port *typec_register_port(struct device *parent,
> >  		return ERR_PTR(ret);
> >  	}
> >
> > +	if (!port->sw) {
> > +		/* Try to get typec switch via general mux controller */
> > +		port->mux_control_switch =
> typec_mux_control_switch_get(&port->dev);
> > +		if (IS_ERR(port->mux_control_switch))
> > +			ret = PTR_ERR(port->mux_control_switch);
> > +		else if (port->mux_control_switch)
> > +			ret = device_property_read_u32_array(&port->dev,
> > +					"mux-control-switch-states",
> > +					port->mux_control_switch_states,
> > +					3);
> > +		if (ret) {
> > +			put_device(&port->dev);
> > +			return ERR_PTR(ret);
> > +		}
> > +	}
> 
> Why not just do that inside fwnode_typec_switch_get() and handle the whole
> thing in drivers/usb/typec/mux.c (or in its own file if you prefer)?
> 
> You'll just need to register a "wrapper" Type-C switch object for the OF
> mux controller, but that should not be a problem. That way you don't need
> to export any new functions, touch this file or anything else.
> 

Okay, so stick to current typec_switch is preferred, actually I hesitated
on this, I know that approach will have a unified interface, but with
the cost of creating it only for wrap.

My v2 will go with the direction you suggested.

Thanks
Li Jun

> 
> thanks,
> 
> --
> heikki

_______________________________________________
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] 14+ messages in thread

* RE: [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller
  2021-05-21  8:37     ` Heikki Krogerus
@ 2021-05-25 11:46       ` Jun Li
  2021-05-26  9:16         ` Heikki Krogerus
  0 siblings, 1 reply; 14+ messages in thread
From: Jun Li @ 2021-05-25 11:46 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: robh+dt, shawnguo, gregkh, linux, linux-usb, dl-linux-imx,
	devicetree, linux-arm-kernel

Hi Heikki,

> -----Original Message-----
> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Sent: Friday, May 21, 2021 4:38 PM
> To: Jun Li <jun.li@nxp.com>
> Cc: robh+dt@kernel.org; shawnguo@kernel.org; gregkh@linuxfoundation.org;
> linux@roeck-us.net; linux-usb@vger.kernel.org; dl-linux-imx
> <linux-imx@nxp.com>; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH 3/4] usb: typec: add typec orientation switch support
> via mux controller
> 
> Hi,
> 
> On Thu, May 20, 2021 at 03:33:36PM +0300, Heikki Krogerus wrote:
> > Why not just do that inside fwnode_typec_switch_get() and handle the
> > whole thing in drivers/usb/typec/mux.c (or in its own file if you
> > prefer)?
> >
> > You'll just need to register a "wrapper" Type-C switch object for the
> > OF mux controller, but that should not be a problem. That way you
> > don't need to export any new functions, touch this file or anything
> > else.
> 
> I wrote a bit of code just to see how that would look. I'm attaching you
> the hack I made. I guess something like that would not be too bad.
> A wrapper is probable always a bit clumsy, but I'm not sure that in this
> case it's a huge problem. Of course if there are any better ideas, let's
> here them :-)

Thanks for your patch, I am pasting the patch as below.

seems we need consider more than that.

diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index a0adb8947a301..d85231b2fe10b 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_TYPEC)		+= typec.o
 typec-y				:= class.o mux.o bus.o port-mapper.o
+typec-$(MULTIPLEXER)		+= of_mux.o
 obj-$(CONFIG_TYPEC)		+= altmodes/
 obj-$(CONFIG_TYPEC_TCPM)	+= tcpm/
 obj-$(CONFIG_TYPEC_UCSI)	+= ucsi/
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index 9da22ae3006c9..282622276d97b 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -63,6 +63,9 @@ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode)
 
 	sw = fwnode_connection_find_match(fwnode, "orientation-switch", NULL,
 					  typec_switch_match);
+	if (!sw)
+		sw = of_switch_register(fwnode);
+

How to support multiple typec_switch_get() for of_mux case?
the second call to fwnode_typec_switch_get() will get the switch
via fwnode_connection_find_match()? This means we still need
a property "orientation-switch" for mux controller node, this
seems not the expected way for a mux consumer, even with this
property, we will get a EPROBE_DEFER for the first call.

If we use mux_control_get() for multiple caller/consumer, then
we need some other device as input.
  
typec_switch object looks to me is a provider, if we create
and maintain it in consumer side, I have not come out a better
way:-).

Thanks
Li Jun


 	if (!IS_ERR_OR_NULL(sw))
 		WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
 
@@ -78,10 +81,12 @@ EXPORT_SYMBOL_GPL(fwnode_typec_switch_get);
  */
 void typec_switch_put(struct typec_switch *sw)
 {
-	if (!IS_ERR_OR_NULL(sw)) {
-		module_put(sw->dev.parent->driver->owner);
-		put_device(&sw->dev);
-	}
+	if (IS_ERR_OR_NULL(sw))
+		return;
+
+	module_put(sw->dev.parent->driver->owner);
+	of_switch_unregister(sw);
+	put_device(&sw->dev);
 }
 EXPORT_SYMBOL_GPL(typec_switch_put);
 
diff --git a/drivers/usb/typec/mux.h b/drivers/usb/typec/mux.h
index 4fd9426ee44f6..c99caab766313 100644
--- a/drivers/usb/typec/mux.h
+++ b/drivers/usb/typec/mux.h
@@ -5,8 +5,11 @@
 
 #include <linux/usb/typec_mux.h>
 
+struct of_switch;
+
 struct typec_switch {
 	struct device dev;
+	struct of_switch *osw;
 	typec_switch_set_fn_t set;
 };
 
@@ -18,4 +21,16 @@ struct typec_mux {
 #define to_typec_switch(_dev_) container_of(_dev_, struct typec_switch, dev)
 #define to_typec_mux(_dev_) container_of(_dev_, struct typec_mux, dev)
 
+#ifdef CONFIG_MULTIPLEXER
+struct typec_switch *of_switch_register(struct fwnode_handle *fwnode);
+void of_switch_unregister(struct typec_switch *sw);
+#else
+static inline struct typec_switch *of_switch_register(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+static inline void of_switch_unregister(struct typec_switch *sw) { }
+#endif /* MULTIPLEXER */
+
 #endif /* __USB_TYPEC_MUX__ */
diff --git a/drivers/usb/typec/of_mux.c b/drivers/usb/typec/of_mux.c
new file mode 100644
index 0000000000000..48686a92331d7
--- /dev/null
+++ b/drivers/usb/typec/of_mux.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Wrapper for mux controllers handling orientation
+ *
+ * Copyright (C) 2021 Intel Corporation
+ */
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/mux/consumer.h>
+#include <linux/usb/typec_mux.h>
+
+#include "mux.h"
+
+struct of_switch {
+	struct mux_control *mc;
+	unsigned int state[3];
+};
+
+static int of_switch_set(struct typec_switch *sw, enum typec_orientation orientation)
+{
+	int ret;
+
+	/* Checking has the switch been unregistered - just not released yet */
+	if (!sw->osw)
+		return -ENODEV;
+
+	ret = mux_control_deselect(sw->osw->mc);
+	if (ret)
+		return ret;
+
+	return mux_control_select(sw->osw->mc, sw->osw->state[orientation]);
+}
+
+struct typec_switch *of_switch_register(struct fwnode_handle *fwnode)
+{
+	struct typec_switch_desc desc;
+	struct typec_switch *sw;
+	struct mux_control *mc;
+	unsigned int state[3];
+	struct of_switch *osw;
+	int ret;
+
+	if (!fwnode_property_present(fwnode, "mux-control-names"))
+		return NULL;
+
+	ret = fwnode_property_read_u32_array(fwnode, "mux-control-switch-states",
+					     state, 3);
+	if (ret)
+		return ERR_PTR(ret);
+
+	desc.fwnode = fwnode;
+	desc.set = of_switch_set;
+	desc.name = fwnode_get_name(fwnode);
+	desc.drvdata = NULL;
+
+	sw = typec_switch_register(NULL, &desc);
+	if (IS_ERR(sw))
+		return sw;
+
+	sw->dev.of_node = to_of_node(fwnode);
+
+	mc = mux_control_get(&sw->dev, "typec-orientation-switch");
+	if (IS_ERR_OR_NULL(mc)) {
+		typec_switch_unregister(sw);
+		if (IS_ERR(mc))
+			return ERR_CAST(mc);
+		return ERR_PTR(-ENODEV);
+	}
+
+	osw = kzalloc(sizeof(osw), GFP_KERNEL);
+	if (!osw) {
+		typec_switch_unregister(sw);
+		mux_control_put(mc);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	memcpy(osw->state, state, sizeof(unsigned int) * 3);
+	osw->mc = mc;
+	sw->osw = osw;
+
+	return sw;
+}
+
+void of_switch_unregister(struct typec_switch *sw)
+{
+	struct of_switch *osw = sw->osw;
+
+	if (!osw)
+		return;
+
+	sw->osw = NULL;
+	typec_switch_unregister(sw);
+	mux_control_put(osw->mc);
+	kfree(osw);
+}
-- 
2.30.2
> 
> 
> thanks,
> 
> --
> heikki

_______________________________________________
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] 14+ messages in thread

* RE: [PATCH 1/4] dt-bindings: connector: Add typec orientation switch properties
  2021-05-21  1:30   ` Rob Herring
@ 2021-05-25 11:48     ` Jun Li
  0 siblings, 0 replies; 14+ messages in thread
From: Jun Li @ 2021-05-25 11:48 UTC (permalink / raw)
  To: Rob Herring
  Cc: heikki.krogerus, shawnguo, gregkh, linux, linux-usb,
	dl-linux-imx, devicetree, linux-arm-kernel

Hi

> -----Original Message-----
> From: Rob Herring <robh@kernel.org>
> Sent: Friday, May 21, 2021 9:31 AM
> To: Jun Li <jun.li@nxp.com>
> Cc: heikki.krogerus@linux.intel.com; shawnguo@kernel.org;
> gregkh@linuxfoundation.org; linux@roeck-us.net;
> linux-usb@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>;
> devicetree@vger.kernel.org; linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH 1/4] dt-bindings: connector: Add typec orientation
> switch properties
> 
> On Wed, May 19, 2021 at 03:14:47PM +0800, Li Jun wrote:
> > Typec orientation switch can be implementaed as a consumer of mux
> > controller, with this way, mux-control-name must be provided with name
> > "typec-orientation-switch", along with its 3 states value array for
> > none(high impedance), cc1, cc2.
> >
> > Signed-off-by: Li Jun <jun.li@nxp.com>
> > ---
> >  .../bindings/connector/usb-connector.yaml     | 21 +++++++++++++++++++
> >  1 file changed, 21 insertions(+)
> >
> > diff --git
> > a/Documentation/devicetree/bindings/connector/usb-connector.yaml
> > b/Documentation/devicetree/bindings/connector/usb-connector.yaml
> > index 32509b98142e..567183e199a3 100644
> > --- a/Documentation/devicetree/bindings/connector/usb-connector.yaml
> > +++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml
> > @@ -111,6 +111,24 @@ properties:
> >        - 1.5A
> >        - 3.0A
> >
> > +  mux-controls:
> > +    description:
> > +      mux controller node to use for orientation switch selection.
> > +    maxItems: 1
> > +
> > +  mux-control-name:
> > +    items:
> > +      - const: typec-orientation-switch
> 
> Don't really need a name with only 1 entry.

Okay, will remove it.

> 
> > +
> > +  mux-control-switch-states:
> 
> Not really part of the 'mux-control' binding, but part of the connector.

Yes, agree.

> So 'typec-orientation-switch-states' or something.

will use typec-orientation-switch-states.

Thanks
Li Jun
> 
> > +    description: |
> > +      An ordered u32 array describing the mux state value for each typec
> > +      orientations: NONE(high impedance), CC1, CC2, if there is no HW mux
> > +      state for NONE, use value of CC1 or CC2 for it,
> > +    minItems: 3
> > +    maxItems: 3
> > +    $ref: /schemas/types.yaml#/definitions/uint32-array
> > +
> >    # The following are optional properties for "usb-c-connector" with power
> >    # delivery support.
> >    source-pdos:
> > @@ -301,6 +319,9 @@ examples:
> >          sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
> >                       PDO_VAR(5000, 12000, 2000)>;
> >          op-sink-microwatt = <10000000>;
> > +        mux-controls = <&mux>;
> > +        mux-control-names = "typec-orientation-switch";
> > +        mux-control-switch-states = <2>, <0>, <1>;
> >        };
> >      };
> >
> > --
> > 2.25.1
> >

_______________________________________________
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] 14+ messages in thread

* Re: [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller
  2021-05-25 11:46       ` Jun Li
@ 2021-05-26  9:16         ` Heikki Krogerus
  2021-05-31 11:58           ` Jun Li
  0 siblings, 1 reply; 14+ messages in thread
From: Heikki Krogerus @ 2021-05-26  9:16 UTC (permalink / raw)
  To: Jun Li
  Cc: robh+dt, shawnguo, gregkh, linux, linux-usb, dl-linux-imx,
	devicetree, linux-arm-kernel

On Tue, May 25, 2021 at 11:46:18AM +0000, Jun Li wrote:
> Hi Heikki,
> 
> > -----Original Message-----
> > From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > Sent: Friday, May 21, 2021 4:38 PM
> > To: Jun Li <jun.li@nxp.com>
> > Cc: robh+dt@kernel.org; shawnguo@kernel.org; gregkh@linuxfoundation.org;
> > linux@roeck-us.net; linux-usb@vger.kernel.org; dl-linux-imx
> > <linux-imx@nxp.com>; devicetree@vger.kernel.org;
> > linux-arm-kernel@lists.infradead.org
> > Subject: Re: [PATCH 3/4] usb: typec: add typec orientation switch support
> > via mux controller
> > 
> > Hi,
> > 
> > On Thu, May 20, 2021 at 03:33:36PM +0300, Heikki Krogerus wrote:
> > > Why not just do that inside fwnode_typec_switch_get() and handle the
> > > whole thing in drivers/usb/typec/mux.c (or in its own file if you
> > > prefer)?
> > >
> > > You'll just need to register a "wrapper" Type-C switch object for the
> > > OF mux controller, but that should not be a problem. That way you
> > > don't need to export any new functions, touch this file or anything
> > > else.
> > 
> > I wrote a bit of code just to see how that would look. I'm attaching you
> > the hack I made. I guess something like that would not be too bad.
> > A wrapper is probable always a bit clumsy, but I'm not sure that in this
> > case it's a huge problem. Of course if there are any better ideas, let's
> > here them :-)
> 
> Thanks for your patch, I am pasting the patch as below.
> 
> seems we need consider more than that.
> 
> diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
> index a0adb8947a301..d85231b2fe10b 100644
> --- a/drivers/usb/typec/Makefile
> +++ b/drivers/usb/typec/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0
>  obj-$(CONFIG_TYPEC)		+= typec.o
>  typec-y				:= class.o mux.o bus.o port-mapper.o
> +typec-$(MULTIPLEXER)		+= of_mux.o
>  obj-$(CONFIG_TYPEC)		+= altmodes/
>  obj-$(CONFIG_TYPEC_TCPM)	+= tcpm/
>  obj-$(CONFIG_TYPEC_UCSI)	+= ucsi/
> diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
> index 9da22ae3006c9..282622276d97b 100644
> --- a/drivers/usb/typec/mux.c
> +++ b/drivers/usb/typec/mux.c
> @@ -63,6 +63,9 @@ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode)
>  
>  	sw = fwnode_connection_find_match(fwnode, "orientation-switch", NULL,
>  					  typec_switch_match);
> +	if (!sw)
> +		sw = of_switch_register(fwnode);
> +
> 
> How to support multiple typec_switch_get() for of_mux case?
> the second call to fwnode_typec_switch_get() will get the switch
> via fwnode_connection_find_match()? This means we still need
> a property "orientation-switch" for mux controller node, this
> seems not the expected way for a mux consumer, even with this
> property, we will get a EPROBE_DEFER for the first call.
> 
> If we use mux_control_get() for multiple caller/consumer, then
> we need some other device as input.
>   
> typec_switch object looks to me is a provider, if we create
> and maintain it in consumer side, I have not come out a better
> way:-).

Sorry, but can we rewind a bit: Why can't you just register the
orientation switch from your mux driver and be done with it? You
should then be able to use OF graph, and no special bindings should
be needed, no?

If you want to reuse a mux-controller driver, then you do need to
modify it (but only a little), and what ever mux-controller specific
bindings there are, you will not use those when the mux supplies the
orientation switching function, instead you'll use the OF graph for
that. But surely that is not a problem?

The mux-controller framework expects the "consumers" of the muxes to
understand the final function that the mux is used for. The Type-C
"mux" framework (I should not even talk about muxes with those) works
the other way around. The driver for the component that supplies the
orientation switch function must understand that it is handling that
function, and there is a good reason for doing it that way with the
USB Type-C switches. The orientation switch for example quite simply
is _not_ always a mux. In fact, it's seems to be rarely a mux these
days. With USB4 for example the orientation is handled almost always
by the first on-board retimer.

There are actually also some technical reasons why Hans failed to get
the mux-controller thing to work, which is the original reason why we
introduced the dedicated framework for the Type-C "muxes" (I really
should stop talking about muxes), but I don't remember what was the
reason.

In any case, to summarise: the orientation switch is a function. A mux
is a device that can supply that function, and if it does, then the
driver for it really needs to register the dedicated orientation
switch.

thanks,

-- 
heikki

_______________________________________________
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] 14+ messages in thread

* RE: [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller
  2021-05-26  9:16         ` Heikki Krogerus
@ 2021-05-31 11:58           ` Jun Li
  0 siblings, 0 replies; 14+ messages in thread
From: Jun Li @ 2021-05-31 11:58 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: robh+dt, shawnguo, gregkh, linux, linux-usb, dl-linux-imx,
	devicetree, linux-arm-kernel, peda, Hans de Goede



> -----Original Message-----
> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Sent: Wednesday, May 26, 2021 5:16 PM
> To: Jun Li <jun.li@nxp.com>
> Cc: robh+dt@kernel.org; shawnguo@kernel.org; gregkh@linuxfoundation.org;
> linux@roeck-us.net; linux-usb@vger.kernel.org; dl-linux-imx
> <linux-imx@nxp.com>; devicetree@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH 3/4] usb: typec: add typec orientation switch support
> via mux controller
> 
> On Tue, May 25, 2021 at 11:46:18AM +0000, Jun Li wrote:
> > Hi Heikki,
> >
> > > -----Original Message-----
> > > From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> > > Sent: Friday, May 21, 2021 4:38 PM
> > > To: Jun Li <jun.li@nxp.com>
> > > Cc: robh+dt@kernel.org; shawnguo@kernel.org;
> > > gregkh@linuxfoundation.org; linux@roeck-us.net;
> > > linux-usb@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>;
> > > devicetree@vger.kernel.org; linux-arm-kernel@lists.infradead.org
> > > Subject: Re: [PATCH 3/4] usb: typec: add typec orientation switch
> > > support via mux controller
> > >
> > > Hi,
> > >
> > > On Thu, May 20, 2021 at 03:33:36PM +0300, Heikki Krogerus wrote:
> > > > Why not just do that inside fwnode_typec_switch_get() and handle
> > > > the whole thing in drivers/usb/typec/mux.c (or in its own file if
> > > > you prefer)?
> > > >
> > > > You'll just need to register a "wrapper" Type-C switch object for
> > > > the OF mux controller, but that should not be a problem. That way
> > > > you don't need to export any new functions, touch this file or
> > > > anything else.
> > >
> > > I wrote a bit of code just to see how that would look. I'm attaching
> > > you the hack I made. I guess something like that would not be too bad.
> > > A wrapper is probable always a bit clumsy, but I'm not sure that in
> > > this case it's a huge problem. Of course if there are any better
> > > ideas, let's here them :-)
> >
> > Thanks for your patch, I am pasting the patch as below.
> >
> > seems we need consider more than that.
> >
> > diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
> > index a0adb8947a301..d85231b2fe10b 100644
> > --- a/drivers/usb/typec/Makefile
> > +++ b/drivers/usb/typec/Makefile
> > @@ -1,6 +1,7 @@
> >  # SPDX-License-Identifier: GPL-2.0
> >  obj-$(CONFIG_TYPEC)		+= typec.o
> >  typec-y				:= class.o mux.o bus.o port-mapper.o
> > +typec-$(MULTIPLEXER)		+= of_mux.o
> >  obj-$(CONFIG_TYPEC)		+= altmodes/
> >  obj-$(CONFIG_TYPEC_TCPM)	+= tcpm/
> >  obj-$(CONFIG_TYPEC_UCSI)	+= ucsi/
> > diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index
> > 9da22ae3006c9..282622276d97b 100644
> > --- a/drivers/usb/typec/mux.c
> > +++ b/drivers/usb/typec/mux.c
> > @@ -63,6 +63,9 @@ struct typec_switch *fwnode_typec_switch_get(struct
> > fwnode_handle *fwnode)
> >
> >  	sw = fwnode_connection_find_match(fwnode, "orientation-switch", NULL,
> >  					  typec_switch_match);
> > +	if (!sw)
> > +		sw = of_switch_register(fwnode);
> > +
> >
> > How to support multiple typec_switch_get() for of_mux case?
> > the second call to fwnode_typec_switch_get() will get the switch via
> > fwnode_connection_find_match()? This means we still need a property
> > "orientation-switch" for mux controller node, this seems not the
> > expected way for a mux consumer, even with this property, we will get
> > a EPROBE_DEFER for the first call.
> >
> > If we use mux_control_get() for multiple caller/consumer, then we need
> > some other device as input.
> >
> > typec_switch object looks to me is a provider, if we create and
> > maintain it in consumer side, I have not come out a better way:-).
> 
> Sorry, but can we rewind a bit: Why can't you just register the orientation
> switch from your mux driver and be done with it? You should then be able
> to use OF graph, and no special bindings should be needed, no?

So we still need a special property for OF graph per discussion on another
thread(use device type other than device name for match), and this has
to be a mux controller core binding for possible different mux chips
(GPIO/MMIO...), register a typec switch if this property exist, but this
is the user specific thing from mux controller point view, I feed this
is again against DT binding's expectation.

> 
> If you want to reuse a mux-controller driver, then you do need to modify
> it (but only a little), and what ever mux-controller specific bindings there
> are, you will not use those when the mux supplies the orientation switching
> function, instead you'll use the OF graph for that. But surely that is not
> a problem?
> 
> The mux-controller framework expects the "consumers" of the muxes to
> understand the final function that the mux is used for. The Type-C "mux"
> framework (I should not even talk about muxes with those) works the other
> way around. 

Fully agree.

> The driver for the component that supplies the orientation switch
> function must understand that it is handling that function, and there is
> a good reason for doing it that way with the USB Type-C switches. 

I understand yes if the switch is only part function of the driver.
  
> The
> orientation switch for example quite simply is _not_ always a mux. In fact,
> it's seems to be rarely a mux these days. With USB4 for example the orientation
> is handled almost always by the first on-board retimer.

If the mux is only part function of a new driver, use the tyepc
"mux" framework and create new binding for the new driver is fine.

But if the typec switch control need a dedicated driver to handle,
on DT platforms, now mux-controller is the only proposed way to go
from binding point view. I am not sure if my case is a normal HW
design, but I guess I should not the only user of this kind of
situation.

> 
> There are actually also some technical reasons why Hans failed to get the
> mux-controller thing to work, which is the original reason why we introduced
> the dedicated framework for the Type-C "muxes" (I really should stop talking
> about muxes), but I don't remember what was the reason.

I checked the patches Hans did, that was mainly to address non-DT
platform, I don't see a clear reason why it can't fit DT platform,
maybe I missed something.

+Hans, It would be great if you can comment on this, thanks.

> 
> In any case, to summarise: the orientation switch is a function. A mux is
> a device that can supply that function, and if it does, then the driver for
> it really needs to register the dedicated orientation switch.

Understand your point, if register the dedicated orientation switch is a must,
I feel using general mux control can't make much sense.

Thanks
Li Jun 
> 
> thanks,
> 
> --
> heikki

_______________________________________________
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] 14+ messages in thread

end of thread, other threads:[~2021-05-31 12:00 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-19  7:14 [PATCH 0/4] typec switch via mux controller Li Jun
2021-05-19  7:14 ` [PATCH 1/4] dt-bindings: connector: Add typec orientation switch properties Li Jun
2021-05-21  1:30   ` Rob Herring
2021-05-25 11:48     ` Jun Li
2021-05-19  7:14 ` [PATCH 2/4] usb: typec: use typec cap fwnode's of_node for typec port Li Jun
2021-05-20 12:38   ` Heikki Krogerus
2021-05-19  7:14 ` [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller Li Jun
2021-05-20 12:33   ` Heikki Krogerus
2021-05-21  8:37     ` Heikki Krogerus
2021-05-25 11:46       ` Jun Li
2021-05-26  9:16         ` Heikki Krogerus
2021-05-31 11:58           ` Jun Li
2021-05-21 13:02     ` Jun Li
2021-05-19  7:14 ` [PATCH 4/4] arm64: dts: imx8mp-evk: enable usb0 with typec connector Li Jun

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).