MLK-16013-27 staging: typec: add super speed signal mux selection
authorLi Jun <jun.li@nxp.com>
Thu, 27 Jul 2017 17:09:12 +0000 (01:09 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:36:20 +0000 (15:36 -0500)
According to the polarity of cc line, we need to do USB3 signal mux
selection if it's controlled by software.

Reviewed-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
drivers/staging/typec/tcpci.c
drivers/staging/typec/tcpm.c
drivers/staging/typec/tcpm.h

index a047b33..7f947a4 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/regmap.h>
 #include <linux/usb/typec.h>
+#include <linux/of_gpio.h>
 
 #include "pd.h"
 #include "tcpci.h"
@@ -37,6 +38,7 @@ struct tcpci {
        struct regmap *regmap;
 
        bool controls_vbus;
+       int ss_sel_gpio;
 
        struct tcpc_dev tcpc;
        unsigned int irq_mask;
@@ -258,6 +260,19 @@ static int tcpci_set_polarity(struct tcpc_dev *tcpc,
        return 0;
 }
 
+static int tcpci_set_ss_mux(struct tcpc_dev *tcpc,
+                               enum typec_cc_polarity polarity)
+{
+       struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
+
+       if (polarity == TYPEC_POLARITY_CC1)
+               gpio_set_value(tcpci->ss_sel_gpio, 1);
+       else
+               gpio_set_value(tcpci->ss_sel_gpio, 0);
+
+       return 0;
+}
+
 static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable)
 {
        struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
@@ -583,6 +598,27 @@ static int tcpci_parse_config(struct tcpci *tcpci)
        return 0;
 }
 
+static int tcpci_ss_mux_control_init(struct tcpci *tcpci)
+{
+       struct device *dev = tcpci->dev;
+       int retval = 0;
+
+       tcpci->ss_sel_gpio = of_get_named_gpio(dev->of_node,
+                                               "ss-sel-gpios", 0);
+       if (!gpio_is_valid(tcpci->ss_sel_gpio)) {
+               /* Super speed signal mux conrol gpio is optional */
+               dev_dbg(dev, "no Super Speed mux gpio pin available");
+       } else {
+               retval = devm_gpio_request_one(dev, tcpci->ss_sel_gpio,
+                               GPIOF_OUT_INIT_LOW, "typec_ss_sel");
+               if (retval < 0)
+                       dev_err(dev, "Unable to request super speed mux gpio %d\n",
+                                                                       retval);
+       }
+
+       return retval;
+}
+
 static int tcpci_probe(struct i2c_client *client,
                       const struct i2c_device_id *i2c_id)
 {
@@ -612,6 +648,7 @@ static int tcpci_probe(struct i2c_client *client,
        tcpci->tcpc.vbus_discharge = tcpci_vbus_force_discharge;
        tcpci->tcpc.get_vbus_vol = tcpci_get_vbus_vol;
        tcpci->tcpc.bist_mode = tcpci_bist_mode;
+       tcpci->tcpc.ss_mux_sel = tcpci_set_ss_mux;
 
        tcpci->tcpc.set_pd_rx = tcpci_set_pd_rx;
        tcpci->tcpc.set_roles = tcpci_set_roles;
@@ -632,6 +669,10 @@ static int tcpci_probe(struct i2c_client *client,
        if (err < 0)
                return err;
 
+       err = tcpci_ss_mux_control_init(tcpci);
+       if (err)
+               return err;
+
        tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc);
        return PTR_ERR_OR_ZERO(tcpci->port);
 }
index c78453c..07241e5 100644 (file)
@@ -1930,6 +1930,9 @@ static int tcpm_src_attach(struct tcpm_port *port)
        if (ret < 0)
                return ret;
 
+       if (port->tcpc->ss_mux_sel)
+               port->tcpc->ss_mux_sel(port->tcpc, polarity);
+
        tcpm_start_drp_toggling(port);
 
        ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST);
@@ -2032,16 +2035,20 @@ static void tcpm_src_detach(struct tcpm_port *port)
 
 static int tcpm_snk_attach(struct tcpm_port *port)
 {
+       enum typec_cc_polarity polarity = port->cc2 != TYPEC_CC_OPEN ?
+                               TYPEC_POLARITY_CC2 : TYPEC_POLARITY_CC1;
        int ret;
 
        if (port->attached)
                return 0;
 
-       ret = tcpm_set_polarity(port, port->cc2 != TYPEC_CC_OPEN ?
-                               TYPEC_POLARITY_CC2 : TYPEC_POLARITY_CC1);
+       ret = tcpm_set_polarity(port, polarity);
        if (ret < 0)
                return ret;
 
+       if (port->tcpc->ss_mux_sel)
+               port->tcpc->ss_mux_sel(port->tcpc, polarity);
+
        tcpm_start_drp_toggling(port);
 
        ret = tcpm_set_roles(port, true, TYPEC_SINK, TYPEC_DEVICE);
index b8a5742..e050209 100644 (file)
@@ -129,6 +129,8 @@ struct tcpc_dev {
        int (*vbus_detect)(struct tcpc_dev *dev, bool enable);
        int (*vbus_discharge)(struct tcpc_dev *tcpc, bool enable);
        void (*bist_mode)(struct tcpc_dev *tcpc, bool enable);
+       int (*ss_mux_sel)(struct tcpc_dev *dev,
+                               enum typec_cc_polarity polarity);
 
        struct tcpc_mux_dev *mux;
 };