summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Brockus <dbrockus@google.com>2020-05-06 14:54:46 -0600
committerCommit Bot <commit-bot@chromium.org>2020-05-08 23:23:53 +0000
commitbed715eea6e2d64a2de64793d9521e0d4e6fa7ee (patch)
treeedb9d7d2817b33e4f482c9cfa51a30ae35a926b3
parent726ca5624f1de3aed6e5e89d8bc18c8ae49bf373 (diff)
downloadchrome-ec-bed715eea6e2d64a2de64793d9521e0d4e6fa7ee.tar.gz
tcpmv2: get USB CCD working on servo_v4 with trembyle
Change AutoDischargeDisconnects to handle Debug Accessory CCD devices. Repair Try.SRC on an initial SNK connection path. Repair power swap path. Auto Discharge was still in the wrong places and faults pointed that there was a problem but finding the correct location is not quite as simple. This at least is working better than before. BUG=b:154590730 BRANCH=none TEST=servo_v4 charge through TEST=servo_v4 connected to USB stick when SNK and SRC Signed-off-by: Denis Brockus <dbrockus@google.com> Change-Id: I9638b873a7243028a230d6d997c060d0bf2616e3 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2185871 Tested-by: Denis Brockus <dbrockus@chromium.org> Tested-by: Edward Hill <ecgh@chromium.org> Reviewed-by: Edward Hill <ecgh@chromium.org> Commit-Queue: Edward Hill <ecgh@chromium.org> Commit-Queue: Denis Brockus <dbrockus@chromium.org> Auto-Submit: Denis Brockus <dbrockus@chromium.org>
-rw-r--r--common/usbc/usb_pe_drp_sm.c10
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c61
-rw-r--r--driver/tcpm/nct38xx.c22
-rw-r--r--driver/tcpm/tcpci.c17
-rw-r--r--driver/tcpm/tcpci.h2
-rw-r--r--driver/tcpm/tcpm.h8
-rw-r--r--include/usb_pd_tcpm.h4
7 files changed, 86 insertions, 38 deletions
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index 67c3d06b66..1f3528788f 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -2238,11 +2238,6 @@ static void pe_snk_wait_for_capabilities_entry(int port)
{
print_current_state(port);
- /* USB TCPCI Spec R2V1p1 4.4.5.4.4
- * Enable AutoDischargeDisconnect since vbus is present
- */
- tcpm_enable_auto_discharge_disconnect(port, 1);
-
/* Initialize and start the SinkWaitCapTimer */
pe[port].timeout = get_time().val + PD_T_SINK_WAIT_CAP;
}
@@ -2810,11 +2805,6 @@ static void pe_snk_transition_to_default_entry(int port)
{
print_current_state(port);
- /* USB TCPCI Spec R2V1p1 4.4.5.4.4
- * Disable AutoDischargeDisconnect as vbus will drop in HardReset
- */
- tcpm_enable_auto_discharge_disconnect(port, 0);
-
/* Inform the TC Layer of Hard Reset */
tc_hard_reset_request(port);
}
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
index ab387ab48a..88b42e0343 100644
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
@@ -659,6 +659,9 @@ int tc_check_vconn_swap(int port)
void tc_pr_swap_complete(int port)
{
TC_CLR_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS);
+
+ /* Enable auto discharge disconnect */
+ tcpm_enable_auto_discharge_disconnect(port, 1);
}
void tc_prs_src_snk_assert_rd(int port)
@@ -708,8 +711,10 @@ void tc_hard_reset_request(int port)
void tc_hard_reset_allow_unattach(int port)
{
TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH);
+
+ /* Enable AutoDischargeDisconnect */
+ tcpm_enable_auto_discharge_disconnect(port, 1);
}
-/****************************************************************************/
void tc_disc_ident_in_progress(int port)
{
@@ -745,7 +750,7 @@ enum try_src_override_t tc_get_try_src_override(void)
void tc_snk_power_off(int port)
{
if (get_state_tc(port) == TC_ATTACHED_SNK ||
- get_state_tc(port) == TC_DBG_ACC_SNK) {
+ get_state_tc(port) == TC_DBG_ACC_SNK) {
TC_SET_FLAG(port, TC_FLAGS_POWER_OFF_SNK);
sink_stop_drawing_current(port);
}
@@ -769,6 +774,9 @@ void tc_src_power_off(int port)
if (IS_ENABLED(CONFIG_CHARGE_MANAGER))
charge_manager_set_ceil(port, CEIL_REQUESTOR_PD,
CHARGE_CEIL_NONE);
+
+ /* Disable AutoDischargeDisconnect */
+ tcpm_enable_auto_discharge_disconnect(port, 0);
}
}
@@ -1264,6 +1272,9 @@ static void sink_stop_drawing_current(int port)
charge_manager_set_ceil(port,
CEIL_REQUESTOR_PD, CHARGE_CEIL_NONE);
}
+
+ /* Disable AutoDischargeDisconnect */
+ tcpm_enable_auto_discharge_disconnect(port, 0);
}
#ifdef CONFIG_USB_PD_TRY_SRC
@@ -1663,9 +1674,6 @@ static void tc_unattached_snk_entry(const int port)
CLR_ALL_BUT_LPM_FLAGS(port);
tc_enable_pd(port, 0);
}
-
- /* Turn on auto discharge disconnect */
- tcpm_enable_auto_discharge_disconnect(port, 1);
}
static void tc_unattached_snk_run(const int port)
@@ -1705,7 +1713,7 @@ static void tc_unattached_snk_run(const int port)
* Set RC.CC2=10b (Rd)
*/
tcpm_enable_auto_discharge_disconnect(port, 0);
- tcpm_set_connection(port, TYPEC_CC_RD, 0);
+ tcpm_set_connection(port, TYPEC_CC_RD, 0, NULL);
set_state_tc(port, TC_DRP_AUTO_TOGGLE);
return;
}
@@ -1907,6 +1915,10 @@ static void tc_attached_snk_entry(const int port)
/* Enable PD */
if (IS_ENABLED(CONFIG_USB_PE_SM))
tc_enable_pd(port, 1);
+
+ /* Enable auto discharge disconnect, if not PR Swapping */
+ if (!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS))
+ tcpm_enable_auto_discharge_disconnect(port, 1);
}
static void tc_attached_snk_run(const int port)
@@ -2090,6 +2102,10 @@ static void tc_unoriented_dbg_acc_src_entry(const int port)
/* Inform PPC that a sink is connected. */
if (IS_ENABLED(CONFIG_USBC_PPC))
ppc_sink_is_connected(port, 1);
+
+ /* Enable auto discharge disconnect, if not PR Swapping */
+ if (!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS))
+ tcpm_enable_auto_discharge_disconnect(port, 1);
}
static void tc_unoriented_dbg_acc_src_run(const int port)
@@ -2150,6 +2166,7 @@ static void tc_unoriented_dbg_acc_src_run(const int port)
!TC_CHK_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS)) {
set_state_tc(port, TC_UNATTACHED_SNK);
+ return;
}
#ifdef CONFIG_USB_PE_SM
@@ -2250,6 +2267,10 @@ static void tc_dbg_acc_snk_entry(const int port)
/* Enable PD */
tc_enable_pd(port, 1);
+
+ /* Enable auto discharge disconnect, if not PR Swapping */
+ if (!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS))
+ tcpm_enable_auto_discharge_disconnect(port, 1);
}
static void tc_dbg_acc_snk_run(const int port)
@@ -2371,9 +2392,6 @@ static void tc_unattached_src_entry(const int port)
}
tc[port].next_role_swap = get_time().val + PD_T_DRP_SRC;
-
- /* Turn on auto discharge disconnect */
- tcpm_enable_auto_discharge_disconnect(port, 1);
}
static void tc_unattached_src_run(const int port)
@@ -2431,7 +2449,7 @@ static void tc_unattached_src_run(const int port)
* Set RC.CC2=01b (Rp)
*/
tcpm_enable_auto_discharge_disconnect(port, 0);
- tcpm_set_connection(port, TYPEC_CC_RP, 0);
+ tcpm_set_connection(port, TYPEC_CC_RP, 0, NULL);
set_state_tc(port, TC_DRP_AUTO_TOGGLE);
}
#endif
@@ -2623,9 +2641,12 @@ static void tc_attached_src_entry(const int port)
/*
* Only notify if we're not performing a power role swap. During a
* power role swap, the port partner is not disconnecting/connecting.
+ * Enable auto discharge disconnect, if not PR Swapping.
*/
- if (!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS))
+ if (!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
hook_notify(HOOK_USB_PD_CONNECT);
+ tcpm_enable_auto_discharge_disconnect(port, 1);
+ }
}
static void tc_attached_src_run(const int port)
@@ -2701,6 +2722,7 @@ static void tc_attached_src_run(const int port)
set_state_tc(port, IS_ENABLED(CONFIG_USB_PD_TRY_SRC) ?
TC_TRY_WAIT_SNK : TC_UNATTACHED_SNK);
+ return;
}
#ifdef CONFIG_USB_PE_SM
@@ -2796,6 +2818,7 @@ static __maybe_unused void check_drp_connection(const int port)
{
enum pd_drp_next_states next_state;
enum tcpc_cc_voltage_status cc1, cc2;
+ int prev_drp;
TC_CLR_FLAG(port, TC_FLAGS_CHECK_CONNECTION);
@@ -2819,7 +2842,9 @@ static __maybe_unused void check_drp_connection(const int port)
* Set RC.DRP=0
* Set TCPC_CONTROl.PlugOrientation
*/
- tcpm_set_connection(port, TYPEC_CC_RD, 1);
+ tcpm_set_connection(port, TYPEC_CC_RD, 1, &prev_drp);
+ if (prev_drp)
+ tcpm_enable_auto_discharge_disconnect(port, 1);
set_state_tc(port, TC_UNATTACHED_SNK);
break;
case DRP_TC_UNATTACHED_SRC:
@@ -2829,7 +2854,9 @@ static __maybe_unused void check_drp_connection(const int port)
* Set RC.DRP=0
* Set TCPC_CONTROl.PlugOrientation
*/
- tcpm_set_connection(port, TYPEC_CC_RP, 1);
+ tcpm_set_connection(port, TYPEC_CC_RP, 1, &prev_drp);
+ if (prev_drp)
+ tcpm_enable_auto_discharge_disconnect(port, 1);
set_state_tc(port, TC_UNATTACHED_SRC);
break;
@@ -2846,7 +2873,7 @@ static __maybe_unused void check_drp_connection(const int port)
(PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE)
? TYPEC_CC_RP
: TYPEC_CC_RD,
- 0);
+ 0, NULL);
set_state_tc(port, TC_DRP_AUTO_TOGGLE);
break;
#endif
@@ -2923,6 +2950,9 @@ static void tc_try_src_entry(const int port)
tc[port].cc_state = PD_CC_UNSET;
tc[port].try_wait_debounce = get_time().val + PD_T_DRP_TRY;
tc[port].timeout = get_time().val + PD_T_TRY_TIMEOUT;
+
+ /* Disable AutoDischargeDisconnect */
+ tcpm_enable_auto_discharge_disconnect(port, 0);
}
static void tc_try_src_run(const int port)
@@ -2984,6 +3014,9 @@ static void tc_try_wait_snk_entry(const int port)
tc_enable_pd(port, 0);
tc[port].cc_state = PD_CC_UNSET;
tc[port].try_wait_debounce = get_time().val + PD_T_CC_DEBOUNCE;
+
+ /* Disable AutoDischargeDisconnect */
+ tcpm_enable_auto_discharge_disconnect(port, 0);
}
static void tc_try_wait_snk_run(const int port)
diff --git a/driver/tcpm/nct38xx.c b/driver/tcpm/nct38xx.c
index d6ec0f198e..4f9aa6efd7 100644
--- a/driver/tcpm/nct38xx.c
+++ b/driver/tcpm/nct38xx.c
@@ -77,15 +77,24 @@ static int nct38xx_init(int port)
if (rv)
return rv;
+ /**
+ * Set driver specific ALERT mask bits
+ *
+ * Wake up on faults
+ */
+ reg = TCPC_REG_ALERT_FAULT;
+
/*
* Enable the Vendor Define alert event only when the IO expander
* feature is defined
*/
if (IS_ENABLED(CONFIG_IO_EXPANDER_NCT38XX))
- rv = tcpc_update16(port,
- TCPC_REG_ALERT_MASK,
- TCPC_REG_ALERT_VENDOR_DEF,
- MASK_SET);
+ reg |= TCPC_REG_ALERT_VENDOR_DEF;
+
+ rv = tcpc_update16(port,
+ TCPC_REG_ALERT_MASK,
+ reg,
+ MASK_SET);
return rv;
}
@@ -150,9 +159,11 @@ static int nct3807_handle_fault(int port, int fault)
{
int rv = EC_SUCCESS;
+ /* Registers are set to default, initialize for our use */
if (fault & TCPC_REG_FAULT_STATUS_ALL_REGS_RESET) {
rv = nct38xx_init(port);
} else {
+ /* We don't use TCPC OVP, so just disable it */
if (fault & TCPC_REG_FAULT_STATUS_VBUS_OVER_VOLTAGE) {
/* Disable OVP */
rv = tcpc_update8(port,
@@ -162,6 +173,9 @@ static int nct3807_handle_fault(int port, int fault)
if (rv)
return rv;
}
+ /* Failing AutoDischargeDisconnect should disable it */
+ if (fault & TCPC_REG_FAULT_STATUS_AUTO_DISCHARGE_FAIL)
+ tcpm_enable_auto_discharge_disconnect(port, 0);
}
return rv;
}
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 1896de81ed..97840516a7 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -397,11 +397,21 @@ int tcpci_tcpc_drp_toggle(int port)
int tcpci_tcpc_set_connection(int port,
enum tcpc_cc_pull pull,
- int connect)
+ int connect,
+ int *prev_drp)
{
int rv;
int role;
+ /* Get the ROLE CONTROL value */
+ rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &role);
+ if (rv)
+ return rv;
+
+ /* if optional prev_drp is present then save the current DRP state */
+ if (prev_drp)
+ *prev_drp = !!(role & TCPC_REG_ROLE_CTRL_DRP_MASK);
+
/*
* Disconnecting will set the following and then return
* Set RC.DRP=1b (DRP)
@@ -414,11 +424,6 @@ int tcpci_tcpc_set_connection(int port,
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;
diff --git a/driver/tcpm/tcpci.h b/driver/tcpm/tcpci.h
index 813c3026d4..c3ee70e982 100644
--- a/driver/tcpm/tcpci.h
+++ b/driver/tcpm/tcpci.h
@@ -223,7 +223,7 @@ int tcpci_tcpm_release(int port);
int tcpci_set_role_ctrl(int port, int toggle, int rp, int pull);
int tcpci_tcpc_drp_toggle(int port);
int tcpci_tcpc_set_connection(int port, enum tcpc_cc_pull pull,
- int connect);
+ int connect, int *prev_drp);
#endif
#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
int tcpci_enter_low_power_mode(int port);
diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h
index f9453d418c..e360811155 100644
--- a/driver/tcpm/tcpm.h
+++ b/driver/tcpm/tcpm.h
@@ -180,13 +180,17 @@ static inline int tcpm_set_cc(int port, int pull)
static inline int tcpm_set_connection(int port,
enum tcpc_cc_pull pull,
- int connect)
+ int connect,
+ int *prev_drp)
{
const struct tcpm_drv *tcpc = tcpc_config[port].drv;
if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) &&
tcpc->set_connection)
- return tcpc->set_connection(port, pull, connect);
+ return tcpc->set_connection(port, pull, connect, prev_drp);
+ else if (prev_drp)
+ *prev_drp = 0;
+
return EC_SUCCESS;
}
diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h
index 6cc53209a1..a98d8e3000 100644
--- a/include/usb_pd_tcpm.h
+++ b/include/usb_pd_tcpm.h
@@ -333,12 +333,14 @@ struct tcpm_drv {
* @param port Type-C port number
* @param pull enum tcpc_cc_pull of CC lines
* @param connect Connect(1) or Disconnect(0)
+ * @param prev_drp optional output of previous DRP value
*
* @return EC_SUCCESS or error
*/
int (*set_connection)(int port,
enum tcpc_cc_pull pull,
- int connect);
+ int connect,
+ int *prev_drp);
#ifdef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
/**