MLK-16013-17 staging: typec: tcpm: optimise cc toggling for drp port
authorLi Jun <jun.li@nxp.com>
Wed, 26 Jul 2017 23:33:42 +0000 (07:33 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:36:19 +0000 (15:36 -0500)
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 <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 7294b30..5e1778a 100644 (file)
@@ -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)
index 1dde877..82993f1 100644 (file)
@@ -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;
index a231e7c..358631f 100644 (file)
@@ -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);