summaryrefslogtreecommitdiff
path: root/driver/tcpm/nct38xx.c
diff options
context:
space:
mode:
authorDenis Brockus <dbrockus@chromium.org>2020-02-13 08:05:34 -0700
committerCommit Bot <commit-bot@chromium.org>2020-02-15 02:12:57 +0000
commit139e94729bc55c6dbf838d1136c04b7ce711c48f (patch)
tree705c73cdeac1a4106a32e1243c30dc92ffb79902 /driver/tcpm/nct38xx.c
parent58bd6e33611249d3e40260aa7aecc29900a69cea (diff)
downloadchrome-ec-139e94729bc55c6dbf838d1136c04b7ce711c48f.tar.gz
nct38xx: auto-toggle exit cleanup
Don't set the polarity behind the back of the PD stack. Just clear the DRP and leave the CC lines so they look just as we found them. This will allow TRY to work and we will no go OPEN because we set the CC lines to something that was not expected. BUG=b:149415919 BRANCH=none TEST=verify USB-C connections are working Change-Id: I766514bd46922000ea8916d61d00265e7e5e4fd4 Signed-off-by: Denis Brockus <dbrockus@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2053461 Reviewed-by: Jett Rink <jettrink@chromium.org> Commit-Queue: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'driver/tcpm/nct38xx.c')
-rw-r--r--driver/tcpm/nct38xx.c150
1 files changed, 130 insertions, 20 deletions
diff --git a/driver/tcpm/nct38xx.c b/driver/tcpm/nct38xx.c
index 9c874f5e87..0f27661371 100644
--- a/driver/tcpm/nct38xx.c
+++ b/driver/tcpm/nct38xx.c
@@ -14,7 +14,6 @@
#include "task.h"
#include "tcpci.h"
#include "usb_common.h"
-#include "usb_pd.h"
#if !defined(CONFIG_USB_PD_TCPM_TCPCI)
#error "NCT38XX is using part of standard TCPCI control"
@@ -120,29 +119,140 @@ static void nct38xx_tcpc_alert(int port)
}
#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
-static void nct38xx_auto_toggle_connection(int port,
+static void nct38xx_drp_toggle_connection(int port,
enum tcpc_cc_voltage_status cc1,
enum tcpc_cc_voltage_status cc2)
{
- int polarity;
+ int rv;
+ int role;
- /*
- * Get the current polarity so we can make sure the
- * PD stack will set the CC lines as we expect and
- * not to setting both CC lines the same due to
- * NO-POLARITY still being set in the cache. This
- * will cause this chip to go back to searching
- * auto toggle with an open on both CC lines.
- *
- * TODO(b/149415919): Consider trying to clear the DRP
- * mode instead of changing the polarity
- */
- if (cc_is_rp(cc1) || cc_is_rp(cc2))
- polarity = get_snk_polarity(cc1, cc2);
- else
- polarity = get_src_polarity(cc1, cc2);
+ /* Get the ROLE CONTROL value */
+ rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &role);
+ if (rv) {
+ CPRINTS("C%d: %s failed to read ROLE",
+ port, __func__);
+ return;
+ }
+
+ if (role & TCPC_REG_ROLE_CTRL_DRP_MASK) {
+ /* TODO(b/149593609) get an understanding from Nuvoton
+ * why this is the way it works.
+ *
+ * If DRP is set, the CC pins shall stay in
+ * Potential_Connect_as_Src or Potential_Connect_as_Sink
+ * until directed otherwise.
+ *
+ * From TCPCIr2 figure 4-20 DRP Connection Detection
+ * Determine CC & VCONN:
+ * Set RC.CC1 & RC.CC2 per potential connect decision
+ * Set RC.DRP=0
+ * Set TCPC_CONTROl.PlugOrientation
+ * Set PC.AutoDischargeDisconnect=1 & PC.EnableVconn
+ */
+ int ctrl;
+ enum tcpc_cc_polarity polarity;
+ enum tcpc_cc_voltage_status cc1_pull, cc2_pull;
+ enum tcpc_rp_value rp = TYPEC_RP_USB;
+
+ switch (cc1) {
+ case TYPEC_CC_VOLT_OPEN:
+ cc1_pull = TYPEC_CC_OPEN;
+ break;
+ case TYPEC_CC_VOLT_RA:
+ cc1_pull = TYPEC_CC_RA;
+ break;
+ case TYPEC_CC_VOLT_RD:
+ cc1_pull = TYPEC_CC_RD;
+ break;
+ case TYPEC_CC_VOLT_RP_DEF:
+ case TYPEC_CC_VOLT_RP_1_5:
+ case TYPEC_CC_VOLT_RP_3_0:
+ rp = cc1 - TYPEC_CC_VOLT_RP_DEF;
+ cc1_pull = TYPEC_CC_RP;
+ break;
+ default:
+ CPRINTS("C%d: %s Invalid CC1 Voltage presented",
+ port, __func__);
+ return;
+ }
+
+ switch (cc2) {
+ case TYPEC_CC_VOLT_OPEN:
+ cc2_pull = TYPEC_CC_OPEN;
+ break;
+ case TYPEC_CC_VOLT_RA:
+ cc2_pull = TYPEC_CC_RA;
+ break;
+ case TYPEC_CC_VOLT_RD:
+ cc2_pull = TYPEC_CC_RD;
+ break;
+ case TYPEC_CC_VOLT_RP_DEF:
+ case TYPEC_CC_VOLT_RP_1_5:
+ case TYPEC_CC_VOLT_RP_3_0:
+ rp = cc2 - TYPEC_CC_VOLT_RP_DEF;
+ cc2_pull = TYPEC_CC_RP;
+ break;
+ default:
+ CPRINTS("C%d: %s Invalid CC2 Voltage presented",
+ port, __func__);
+ return;
+ }
- pd_set_polarity(port, polarity);
+ /* Set the CC lines */
+ rv = tcpc_write(port, TCPC_REG_ROLE_CTRL,
+ TCPC_REG_ROLE_CTRL_SET(0,
+ rp, cc1_pull, cc2_pull));
+ if (rv) {
+ CPRINTS("C%d: %s failed to write ROLE",
+ port, __func__);
+ return;
+ }
+
+ /* Set the polarity */
+ if (cc_is_rp(cc1) || cc_is_rp(cc2))
+ polarity = get_snk_polarity(cc1, cc2);
+ else
+ polarity = get_src_polarity(cc1, cc2);
+ nct38xx_tcpm_drv.set_polarity(port, polarity);
+
+ /* Set/Clear auto discharge disconnect */
+ rv = tcpc_read(port, TCPC_REG_POWER_CTRL, &ctrl);
+ if (rv) {
+ CPRINTS("C%d: %s failed to read POWER_CTRL",
+ port, __func__);
+ return;
+ }
+
+ if (TCPC_REG_POWER_CTRL_VCONN(ctrl))
+ ctrl |= TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT;
+ else
+ ctrl &= ~TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT;
+
+ rv = tcpc_write(port,
+ TCPC_REG_POWER_CTRL,
+ ctrl);
+ if (rv) {
+ CPRINTS("C%d: %s failed to write POWER_CTRL",
+ port, __func__);
+ return;
+ }
+ } else {
+ /*
+ * We left auto-toggle and no longer have DRP set. This
+ * would happen if DRP was turned off and we did not have
+ * a connection. We have to manually turn off that we
+ * are looking for a connection.
+ */
+ rv = tcpc_update8(port,
+ TCPC_REG_TCPC_CTRL,
+ TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT,
+ MASK_CLR);
+ if (rv) {
+ CPRINTS("C%d: %s failed to clear Look4Connection",
+ port, __func__);
+ return;
+ }
+ }
}
#endif
@@ -169,7 +279,7 @@ const struct tcpm_drv nct38xx_tcpm_drv = {
&tcpci_tcpc_enable_auto_discharge_disconnect,
#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
.drp_toggle = &tcpci_tcpc_drp_toggle,
- .tcpc_auto_toggle_connection = &nct38xx_auto_toggle_connection,
+ .drp_toggle_connection = &nct38xx_drp_toggle_connection,
#endif
#ifdef CONFIG_USBC_PPC
.set_snk_ctrl = &tcpci_tcpm_set_snk_ctrl,