From: Li Jun Date: Wed, 26 Jul 2017 23:33:42 +0000 (+0800) Subject: MLK-16013-17 staging: typec: tcpm: optimise cc toggling for drp port X-Git-Tag: C0P2-H0.0--20200415~1916 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=84c2173687ce68bc80963fd95c96d9c5be3cc311;p=linux.git MLK-16013-17 staging: typec: tcpm: optimise cc toggling for drp port We should only enable drp auto toggling when unattached, so add one more parameter; when attached, we set the cc line state according to the other end cc status. Reviewed-by: Peter Chen Signed-off-by: Li Jun --- diff --git a/drivers/staging/typec/tcpci.c b/drivers/staging/typec/tcpci.c index 7294b30c5639..5e1778aabb07 100644 --- a/drivers/staging/typec/tcpci.c +++ b/drivers/staging/typec/tcpci.c @@ -131,28 +131,79 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) } static int tcpci_start_drp_toggling(struct tcpc_dev *tcpc, - enum typec_cc_status cc) + enum typec_cc_status cc, int attach) { struct tcpci *tcpci = tcpc_to_tcpci(tcpc); - unsigned int reg = TCPC_ROLE_CTRL_DRP; + unsigned int reg = 0; - switch (cc) { - default: - case TYPEC_CC_RP_DEF: - reg |= (TCPC_ROLE_CTRL_RP_VAL_DEF << - TCPC_ROLE_CTRL_RP_VAL_SHIFT); - break; - case TYPEC_CC_RP_1_5: - reg |= (TCPC_ROLE_CTRL_RP_VAL_1_5 << - TCPC_ROLE_CTRL_RP_VAL_SHIFT); - break; - case TYPEC_CC_RP_3_0: - reg |= (TCPC_ROLE_CTRL_RP_VAL_3_0 << - TCPC_ROLE_CTRL_RP_VAL_SHIFT); - break; + /* Only set DRP bit for auto toggle when unattached */ + if (attach) { + switch (cc) { + case TYPEC_CC_RP_DEF: + if (attach >> TYPEC_POLARITY_CC2) + reg |= TCPC_ROLE_CTRL_CC_RP << + TCPC_ROLE_CTRL_CC2_SHIFT; + else if (attach >> TYPEC_POLARITY_CC1) + reg |= TCPC_ROLE_CTRL_CC_RP << + TCPC_ROLE_CTRL_CC1_SHIFT; + + reg |= (TCPC_ROLE_CTRL_RP_VAL_DEF << + TCPC_ROLE_CTRL_RP_VAL_SHIFT); + break; + case TYPEC_CC_RP_1_5: + if (attach >> TYPEC_POLARITY_CC2) + reg |= TCPC_ROLE_CTRL_CC_RP << + TCPC_ROLE_CTRL_CC2_SHIFT; + else if (attach >> TYPEC_POLARITY_CC1) + reg |= TCPC_ROLE_CTRL_CC_RP << + TCPC_ROLE_CTRL_CC1_SHIFT; + + reg |= (TCPC_ROLE_CTRL_RP_VAL_1_5 << + TCPC_ROLE_CTRL_RP_VAL_SHIFT); + break; + case TYPEC_CC_RP_3_0: + if (attach >> TYPEC_POLARITY_CC2) + reg |= TCPC_ROLE_CTRL_CC_RP << + TCPC_ROLE_CTRL_CC2_SHIFT; + else if (attach >> TYPEC_POLARITY_CC1) + reg |= TCPC_ROLE_CTRL_CC_RP << + TCPC_ROLE_CTRL_CC1_SHIFT; + + reg |= (TCPC_ROLE_CTRL_RP_VAL_3_0 << + TCPC_ROLE_CTRL_RP_VAL_SHIFT); + break; + case TYPEC_CC_RD: + if (attach >> TYPEC_POLARITY_CC2) + reg |= TCPC_ROLE_CTRL_CC_RD << + TCPC_ROLE_CTRL_CC2_SHIFT; + else if (attach >> TYPEC_POLARITY_CC1) + reg |= TCPC_ROLE_CTRL_CC_RD << + TCPC_ROLE_CTRL_CC1_SHIFT; + break; + default: + break; + } + + /* keep the un-touched cc line to be open */ + if (attach >> TYPEC_POLARITY_CC2) + reg |= TCPC_ROLE_CTRL_CC_OPEN << + TCPC_ROLE_CTRL_CC1_SHIFT; + else if (attach >> TYPEC_POLARITY_CC1) + reg |= TCPC_ROLE_CTRL_CC_OPEN << + TCPC_ROLE_CTRL_CC2_SHIFT; + } else { /* Not attached */ + if (cc == TYPEC_CC_RD) + reg = TCPC_ROLE_CTRL_DRP | 0xa; /* Rd */ + else + reg = TCPC_ROLE_CTRL_DRP | 0x5; /* Rp */ } - return regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg); + regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg); + + if (!attach) + regmap_write(tcpci->regmap, TCPC_COMMAND, + TCPC_CMD_LOOK4CONNECTION); + return 0; } static enum typec_cc_status tcpci_to_typec_cc(unsigned int cc, bool sink) diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c index 1dde877d6a41..82993f1090a3 100644 --- a/drivers/staging/typec/tcpm.c +++ b/drivers/staging/typec/tcpm.c @@ -1814,13 +1814,25 @@ static int tcpm_set_charge(struct tcpm_port *port, bool charge) static bool tcpm_start_drp_toggling(struct tcpm_port *port) { - int ret; + int ret = 0; + + tcpm_log(port, "Start DRP toggling"); + /* First toggle Rp if current state is SNK_UNATTACHED */ if (port->tcpc->start_drp_toggling && - port->typec_caps.type == TYPEC_PORT_DRP) { - tcpm_log_force(port, "Start DRP toggling"); - ret = port->tcpc->start_drp_toggling(port->tcpc, - tcpm_rp_cc(port)); + port->typec_caps.type == TYPEC_PORT_DRP) { + if (port->state == SRC_UNATTACHED) + ret = port->tcpc->start_drp_toggling(port->tcpc, + tcpm_rp_cc(port), 0); + else if (port->state == SNK_UNATTACHED) + ret = port->tcpc->start_drp_toggling(port->tcpc, + TYPEC_CC_RD, 0); + else if (port->state == SRC_ATTACHED) + ret = port->tcpc->start_drp_toggling(port->tcpc, + tcpm_rp_cc(port), 0x1 << port->polarity); + else if (port->state == SNK_ATTACHED) + ret = port->tcpc->start_drp_toggling(port->tcpc, + TYPEC_CC_RD, 0x1 << port->polarity); if (!ret) return true; } @@ -1886,6 +1898,8 @@ static int tcpm_src_attach(struct tcpm_port *port) if (ret < 0) return ret; + tcpm_start_drp_toggling(port); + ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST); if (ret < 0) return ret; @@ -1995,6 +2009,8 @@ static int tcpm_snk_attach(struct tcpm_port *port) if (ret < 0) return ret; + tcpm_start_drp_toggling(port); + ret = tcpm_set_roles(port, true, TYPEC_SINK, TYPEC_DEVICE); if (ret < 0) return ret; diff --git a/drivers/staging/typec/tcpm.h b/drivers/staging/typec/tcpm.h index a231e7c62457..358631f8737a 100644 --- a/drivers/staging/typec/tcpm.h +++ b/drivers/staging/typec/tcpm.h @@ -117,7 +117,7 @@ struct tcpc_dev { int (*set_roles)(struct tcpc_dev *dev, bool attached, enum typec_role role, enum typec_data_role data); int (*start_drp_toggling)(struct tcpc_dev *dev, - enum typec_cc_status cc); + enum typec_cc_status cc, int attach); int (*try_role)(struct tcpc_dev *dev, int role); int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type, const struct pd_message *msg);