[PATCH v6 5/6] usb: typec: mux: add typec switch via general mux control
From: Li Jun <hidden>
Date: 2020-11-23 14:09:16
Also in:
linux-usb
Subsystem:
the rest, usb subsystem, usb typec class · Maintainers:
Linus Torvalds, Greg Kroah-Hartman, Heikki Krogerus
The general mux controller can be easily extended to support various mux selection, this especially fits typec orientation switch block with a dedicated driver. Signed-off-by: Li Jun <redacted> --- New patch for v6. drivers/usb/typec/bus.h | 1 + drivers/usb/typec/mux.c | 44 ++++++++++++++++++++++++++++++++++++++++--- include/linux/usb/typec_mux.h | 7 +------ 3 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/typec/bus.h b/drivers/usb/typec/bus.h
index 8ba8112..235ee82 100644
--- a/drivers/usb/typec/bus.h
+++ b/drivers/usb/typec/bus.h@@ -38,6 +38,7 @@ extern struct class typec_mux_class; struct typec_switch { struct device dev; typec_switch_set_fn_t set; + struct mux_control *mux_ctrl; }; struct typec_mux {
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index 0219aa4..afc4537 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c@@ -14,6 +14,7 @@ #include <linux/property.h> #include <linux/slab.h> #include <linux/usb/typec_mux.h> +#include <linux/mux/consumer.h> #include "bus.h"
@@ -42,10 +43,8 @@ static void *typec_switch_match(struct device_connection *con, int ep, if (con->id && !fwnode_is_compatible(con->fwnode, con->id) && !fwnode_property_present(con->fwnode, con->id)) return NULL; - dev = class_find_device(&typec_mux_class, NULL, con->fwnode, switch_fwnode_match); - return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER); }
@@ -71,6 +70,19 @@ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode) } EXPORT_SYMBOL_GPL(fwnode_typec_switch_get); +struct typec_switch *typec_switch_get(struct device *dev) +{ + struct mux_control *typec_mc = mux_control_get(dev->parent, + "mux-typec-switch"); + struct typec_switch *sw = fwnode_typec_switch_get(dev_fwnode(dev)); + + if (!IS_ERR_OR_NULL(sw) && !IS_ERR_OR_NULL(typec_mc)) + sw->mux_ctrl = typec_mc; + + return sw; +} +EXPORT_SYMBOL_GPL(typec_switch_get); + /** * typec_put_switch - Release USB Type-C orientation switch * @sw: USB Type-C orientation switch
@@ -142,13 +154,39 @@ typec_switch_register(struct device *parent, } EXPORT_SYMBOL_GPL(typec_switch_register); +static int typec_switch_mux_ctrl(struct mux_control *sw_mux, + enum typec_orientation orientation) +{ + int ret = 0; + + if (!sw_mux) + return -EINVAL; + + switch (orientation) { + case TYPEC_ORIENTATION_NORMAL: + ret = mux_control_select(sw_mux, 1); + break; + case TYPEC_ORIENTATION_REVERSE: + ret = mux_control_select(sw_mux, 0); + break; + case TYPEC_ORIENTATION_NONE: + ret = mux_control_deselect(sw_mux); + break; + } + + return ret; +} + int typec_switch_set(struct typec_switch *sw, enum typec_orientation orientation) { if (IS_ERR_OR_NULL(sw)) return 0; - return sw->set(sw, orientation); + if (sw->mux_ctrl) + return typec_switch_mux_ctrl(sw->mux_ctrl, orientation); + else + return sw->set(sw, orientation); } EXPORT_SYMBOL_GPL(typec_switch_set);
diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
index a9d9957..e2ea141 100644
--- a/include/linux/usb/typec_mux.h
+++ b/include/linux/usb/typec_mux.h@@ -26,15 +26,10 @@ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode); void typec_switch_put(struct typec_switch *sw); int typec_switch_set(struct typec_switch *sw, enum typec_orientation orientation); - -static inline struct typec_switch *typec_switch_get(struct device *dev) -{ - return fwnode_typec_switch_get(dev_fwnode(dev)); -} - struct typec_switch * typec_switch_register(struct device *parent, const struct typec_switch_desc *desc); +struct typec_switch *typec_switch_get(struct device *dev); void typec_switch_unregister(struct typec_switch *sw); void typec_switch_set_drvdata(struct typec_switch *sw, void *data);
--
2.7.4