1
0
Fork 0

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 <peter.chen@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
pull/10/head
Li Jun 2017-07-28 01:09:12 +08:00 committed by Jason Liu
parent 45927e4eb2
commit 13f735b060
3 changed files with 52 additions and 2 deletions

View 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);
}

View File

@ -1988,6 +1988,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);
@ -2096,16 +2099,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);

View File

@ -140,6 +140,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;
};