diff options
author | Denis Brockus <dbrockus@google.com> | 2020-03-17 12:21:05 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-20 04:39:57 +0000 |
commit | 03f5a8686a6a2274c176ead7fb928571a3e7c1f5 (patch) | |
tree | 09f467e642ce635a4e135534dbbd2ce9c0edab5f /driver/tcpm/tcpci.c | |
parent | 024e5e7811ee09801b55b08f274cb95e63c741d2 (diff) | |
download | chrome-ec-03f5a8686a6a2274c176ead7fb928571a3e7c1f5.tar.gz |
tcpmv2: cleanup auto discharge disconnect
This CL is based on the inability to boot trembyle when a
battery is not connected. The failure looks like it is always
right after AutoDischargeDisconnect has been set. I asked
Nuvoton if we could go back to using ForcedDischarge and
veer away from AutoDischargeDisconnect and I was told no
that it is now required.
My first step was to determine how close the existing
AutoDischargeDisconnect was to the spec and found enough
difference that I wanted to get that in line before
trying to pinpoint the issues causing this problem.
BUG=none
BRANCH=none
TEST=get tcpmv2 to work without a battery attached
Signed-off-by: Denis Brockus <dbrockus@google.com>
Change-Id: I44b86ae5dfcf6b547c742c1af0228a0ed8e3520d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2105935
Tested-by: Denis Brockus <dbrockus@chromium.org>
Reviewed-by: Edward Hill <ecgh@chromium.org>
Reviewed-by: Keith Short <keithshort@chromium.org>
Commit-Queue: Denis Brockus <dbrockus@chromium.org>
Auto-Submit: Denis Brockus <dbrockus@chromium.org>
Diffstat (limited to 'driver/tcpm/tcpci.c')
-rw-r--r-- | driver/tcpm/tcpci.c | 149 |
1 files changed, 142 insertions, 7 deletions
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index dd64ebb157..95c8d9bb3e 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -16,6 +16,7 @@ #include "tcpm.h" #include "timer.h" #include "usb_charge.h" +#include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpc.h" @@ -379,13 +380,147 @@ int tcpci_tcpc_drp_toggle(int port) { int rv; - /* Set auto drp toggle */ + /* + * Set auto drp toggle + * NOTE: This should be done according to the last connection + * that we are disconnecting from. TCPCI Rev 2 spec figures + * 4-21 and 4-22 show: + * SNK => DRP should set CC lines to Rd/Rd + * SRC => DRP should set CC lines to Rp/Rp + * The function tcpci_tcpc_set_connection performs this action + * and it may be wise as chips can use this to make this the + * standard and remove this set_role_ctrl call. + */ rv = tcpci_set_role_ctrl(port, 1, TYPEC_RP_USB, TYPEC_CC_RD); + if (rv) + return rv; + + /* Set up to catch LOOK4CONNECTION alerts */ + rv = tcpc_update8(port, + TCPC_REG_TCPC_CTRL, + TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT, + MASK_SET); + if (rv) + return rv; /* Set Look4Connection command */ - rv |= tcpc_write(port, TCPC_REG_COMMAND, - TCPC_REG_COMMAND_LOOK4CONNECTION); + rv = tcpc_write(port, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_LOOK4CONNECTION); + + return rv; +} + +int tcpci_tcpc_set_connection(int port, + enum tcpc_cc_pull pull, + int connect) +{ + int rv; + int role; + + /* + * Disconnecting will set the following and then return + * Set RC.DRP=1b (DRP) + * Set RC.RpValue=00b (smallest Rp to save power) + * Set RC.CC1=pull (Rd or Rp) + * Set RC.CC2=pull (Rd or Rp) + */ + if (!connect) { + tcpci_set_role_ctrl(port, 1, TYPEC_RP_USB, pull); + return EC_SUCCESS; + } + + /* Get the ROLE CONTROL value */ + rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &role); + if (rv) + return rv; + + if (role & TCPC_REG_ROLE_CTRL_DRP_MASK) { + enum tcpc_cc_pull cc1_pull, cc2_pull; + enum tcpc_cc_voltage_status cc1, cc2; + + enum tcpc_cc_polarity polarity; + /* + * If DRP is set, the CC pins shall stay in + * Potential_Connect_as_Src or Potential_Connect_as_Sink + * until directed otherwise. + * + * Set RC.CC1 & RC.CC2 per potential decision + * Set RC.DRP=0 + */ + rv = tcpm_get_cc(port, &cc1, &cc2); + if (rv) + return rv; + + 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_RP; + break; + case TYPEC_CC_VOLT_RP_DEF: + case TYPEC_CC_VOLT_RP_1_5: + case TYPEC_CC_VOLT_RP_3_0: + cc1_pull = TYPEC_CC_RD; + break; + default: + return EC_ERROR_UNKNOWN; + } + + 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_RP; + break; + case TYPEC_CC_VOLT_RP_DEF: + case TYPEC_CC_VOLT_RP_1_5: + case TYPEC_CC_VOLT_RP_3_0: + cc2_pull = TYPEC_CC_RD; + break; + default: + return EC_ERROR_UNKNOWN; + } + + /* Set the CC lines */ + rv = tcpc_write(port, TCPC_REG_ROLE_CTRL, + TCPC_REG_ROLE_CTRL_SET(0, + CONFIG_USB_PD_PULLUP, + cc1_pull, cc2_pull)); + if (rv) + return rv; + + /* Set TCPC_CONTROl.PlugOrientation */ + if (pull == TYPEC_CC_RD) + polarity = polarity_rm_dts( + get_snk_polarity(cc1, cc2)); + else + polarity = get_src_polarity(cc1, cc2); + + rv = tcpc_update8(port, TCPC_REG_TCPC_CTRL, + TCPC_REG_TCPC_CTRL_SET(1), + (polarity == POLARITY_CC1) ? MASK_CLR + : MASK_SET); + } else { + /* + * DRP is not set. This would happen if DRP is not enabled or + * was turned off and we did not have a connection. We have + * to manually turn off that we are looking for a connection + * and set both CC lines to the pull value. + */ + rv = tcpc_update8(port, + TCPC_REG_TCPC_CTRL, + TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT, + MASK_CLR); + } return rv; } #endif @@ -852,6 +987,7 @@ void tcpci_tcpc_alert(int port) int fault; if (tcpci_get_fault(port, &fault) == EC_SUCCESS && + fault != 0 && tcpci_handle_fault(port, fault) == EC_SUCCESS && tcpci_clear_fault(port, fault) == EC_SUCCESS) CPRINTS("C%d FAULT 0x%02X handled", port, fault); @@ -1030,7 +1166,6 @@ int tcpci_tcpm_init(int port) int error; int power_status; int tries = TCPM_INIT_TRIES; - int regval; /* Start with an unknown connection */ tcpci_set_cached_pull(port, TYPEC_CC_OPEN); @@ -1058,9 +1193,9 @@ int tcpci_tcpm_init(int port) * Alert assertion when CC_STATUS.Looking4Connection changes state. */ if (tcpc_config[port].flags & TCPC_FLAGS_TCPCI_REV2_0) { - error = tcpc_read(port, TCPC_REG_TCPC_CTRL, ®val); - regval |= TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT; - error |= tcpc_write(port, TCPC_REG_TCPC_CTRL, regval); + error = tcpc_update8(port, TCPC_REG_TCPC_CTRL, + TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT, + MASK_SET); if (error) CPRINTS("C%d: Failed to init TCPC_CTRL!", port); } |