All of lore.kernel.org
 help / color / mirror / Atom feed
From: Li Jun <jun.li@nxp.com>
To: heikki.krogerus@linux.intel.com, robh+dt@kernel.org, shawnguo@kernel.org
Cc: gregkh@linuxfoundation.org, linux@roeck-us.net,
	linux-usb@vger.kernel.org, linux-imx@nxp.com, jun.li@nxp.com,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Subject: [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller
Date: Wed, 19 May 2021 15:14:49 +0800	[thread overview]
Message-ID: <1621408490-23811-4-git-send-email-jun.li@nxp.com> (raw)
In-Reply-To: <1621408490-23811-1-git-send-email-jun.li@nxp.com>

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


WARNING: multiple messages have this Message-ID (diff)
From: Li Jun <jun.li@nxp.com>
To: heikki.krogerus@linux.intel.com, robh+dt@kernel.org, shawnguo@kernel.org
Cc: gregkh@linuxfoundation.org, linux@roeck-us.net,
	linux-usb@vger.kernel.org, linux-imx@nxp.com, jun.li@nxp.com,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Subject: [PATCH 3/4] usb: typec: add typec orientation switch support via mux controller
Date: Wed, 19 May 2021 15:14:49 +0800	[thread overview]
Message-ID: <1621408490-23811-4-git-send-email-jun.li@nxp.com> (raw)
In-Reply-To: <1621408490-23811-1-git-send-email-jun.li@nxp.com>

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

  parent reply	other threads:[~2021-05-19  7:32 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-19  7:14 [PATCH 0/4] typec switch via mux controller Li Jun
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
2021-05-19  7:14   ` Li Jun
2021-05-21  1:30   ` Rob Herring
2021-05-21  1:30     ` Rob Herring
2021-05-25 11:48     ` Jun Li
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-19  7:14   ` Li Jun
2021-05-20 12:38   ` Heikki Krogerus
2021-05-20 12:38     ` Heikki Krogerus
2021-05-19  7:14 ` Li Jun [this message]
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-20 12:33     ` Heikki Krogerus
2021-05-21  8:37     ` Heikki Krogerus
2021-05-21  8:37       ` Heikki Krogerus
2021-05-25 11:46       ` Jun Li
2021-05-25 11:46         ` Jun Li
2021-05-26  9:16         ` Heikki Krogerus
2021-05-26  9:16           ` Heikki Krogerus
2021-05-31 11:58           ` Jun Li
2021-05-31 11:58             ` Jun Li
2021-05-21 13:02     ` 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
2021-05-19  7:14   ` Li Jun

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1621408490-23811-4-git-send-email-jun.li@nxp.com \
    --to=jun.li@nxp.com \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-imx@nxp.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=robh+dt@kernel.org \
    --cc=shawnguo@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.