MLK-16013-27 usb: typec: add super speed signal mux selection
authorLi Jun <jun.li@nxp.com>
Wed, 9 Jan 2019 06:44:00 +0000 (12:14 +0530)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
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>
Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
drivers/usb/typec/tcpci.c
drivers/usb/typec/tcpm.c
include/linux/usb/tcpm.h

index 5a788dc..b4761b5 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/usb/pd.h>
 #include <linux/usb/tcpm.h>
 #include <linux/usb/typec.h>
+#include <linux/of_gpio.h>
 
 #include "tcpci.h"
 
@@ -28,6 +29,7 @@ struct tcpci {
        struct regmap *regmap;
 
        bool controls_vbus;
+       int ss_sel_gpio;
 
        struct tcpc_dev tcpc;
        unsigned int irq_mask;
@@ -273,6 +275,19 @@ static int tcpci_set_polarity(struct tcpc_dev *tcpc,
                           TCPC_TCPC_CTRL_ORIENTATION : 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);
@@ -625,6 +640,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;
+}
+
 struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
 {
        struct tcpci *tcpci;
@@ -650,6 +686,7 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
        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;
@@ -701,6 +738,10 @@ static int tcpci_probe(struct i2c_client *client,
        if (IS_ERR(chip->tcpci))
                return PTR_ERR(chip->tcpci);
 
+       err = tcpci_ss_mux_control_init(chip->tcpci);
+       if (err)
+               goto err;
+
        err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
                                        _tcpci_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_LOW,
index 65947cd..bd4bd2c 100644 (file)
@@ -2657,6 +2657,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, tcpm_rp_cc(port));
 
        ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST);
@@ -2772,16 +2775,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, tcpm_rp_cc(port));
 
        ret = tcpm_set_roles(port, true, TYPEC_SINK, TYPEC_DEVICE);
index 194e439..cb1de58 100644 (file)
@@ -160,6 +160,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 tcpm_port;