From: Li Jun Date: Thu, 27 Jul 2017 17:09:12 +0000 (+0800) Subject: MLK-16013-27 staging: typec: add super speed signal mux selection X-Git-Tag: C0P2-H0.0--20200415~1906 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=925b1acd31d534b8ade1796808f1613f32025d0a;p=linux.git MLK-16013-27 staging: typec: add super speed signal mux selection 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 Signed-off-by: Li Jun --- diff --git a/drivers/staging/typec/tcpci.c b/drivers/staging/typec/tcpci.c index a047b3376eec..7f947a4de2fb 100644 --- a/drivers/staging/typec/tcpci.c +++ b/drivers/staging/typec/tcpci.c @@ -21,6 +21,7 @@ #include #include #include +#include #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); } diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c index c78453ce5ab2..07241e529828 100644 --- a/drivers/staging/typec/tcpm.c +++ b/drivers/staging/typec/tcpm.c @@ -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); diff --git a/drivers/staging/typec/tcpm.h b/drivers/staging/typec/tcpm.h index b8a57425914a..e0502093cb6e 100644 --- a/drivers/staging/typec/tcpm.h +++ b/drivers/staging/typec/tcpm.h @@ -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; };