From 9fa7c906c2322413d5f8ee132ffcdf3654715b2f Mon Sep 17 00:00:00 2001 From: Wai-Hong Tam Date: Fri, 8 Jan 2021 18:43:35 -0800 Subject: TCPMv2: Defer initializing type-C supplier current limit Initializing all of the suppliers seeds the charge manger and a supplier is then selected (a corresponding charger input current is configured). Originally, both PD and type-C suppliers are unconditionally initialized in the restart_tc_sm() that seeds the charge manger. A lower current supplier (the default VBUS supplier) is selected first before the type-C current detection. A issue happens on the first boot from battery cutoff, the EC RO detects 5V 3A and boots AP. When sysjump to RW, the default VBUS supplier (5V 0.5A) is used first and limits the charger input current to some lower value. It makes AP out of power. This change defers the type-C supplier initialization to either Unattached.SNK (new) or Attached.SNK. In Unattached.SNK, we debounce the CC open status to make sure CC open and then initialize the type-C supplier. As some TCPC needs time to get the CC status valid. Before that, CC open is reported by default. It misleads the decision. We reuse the existing role toggle timer to debounce. And also align the transitions to DRPAutoToggle and LowPowerState to simplify the logic. BRANCH=Trogdor BUG=b:174105232, b:175663604 TEST=Verified the first boot from cutoff, AP still ON after sysjump to RW. TEST=Verified type-C detection, PD detection, and BC 1.2 detection still work correctly. Change-Id: Ia5d714a15d3f556463cf38e11130151e1f1477cb Signed-off-by: Wai-Hong Tam Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2619338 Reviewed-by: Aseda Aboagye --- common/usbc/usb_tc_drp_acc_trysrc_sm.c | 49 +++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c index 1df7710301..d9b3b1cd20 100644 --- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c +++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c @@ -1392,9 +1392,12 @@ static void restart_tc_sm(int port, enum usb_tc_state start_state) } if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { - /* Initialize PD and type-C supplier current limits to 0 */ + /* + * Only initialize PD supplier current limit to 0. + * Defer initializing type-C supplier current limit + * to Unattached.SNK or Attached.SNK. + */ pd_set_input_current_limit(port, 0, 0); - typec_set_input_current_limit(port, 0, 0); charge_manager_update_dualrole(port, CAP_UNKNOWN); } @@ -2094,17 +2097,6 @@ static void tc_unattached_snk_run(const int port) /* Check for connection */ tcpm_get_cc(port, &cc1, &cc2); - /* - * Attempt TCPC auto DRP toggle if it is - * not already auto toggling. - */ - if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && - drp_state[port] == PD_DRP_TOGGLE_ON && - tcpm_auto_toggle_supported(port) && cc_is_open(cc1, cc2)) { - set_state_tc(port, TC_DRP_AUTO_TOGGLE); - return; - } - /* * The port shall transition to AttachWait.SNK when a Source * connection is detected, as indicated by the SNK.Rp state @@ -2117,9 +2109,34 @@ static void tc_unattached_snk_run(const int port) if (cc_is_rp(cc1) || cc_is_rp(cc2)) { /* Connection Detected */ set_state_tc(port, TC_ATTACH_WAIT_SNK); - } else if (get_time().val > tc[port].next_role_swap && - drp_state[port] == PD_DRP_TOGGLE_ON) { - /* DRP Toggle */ + return; + } + + /* + * Debounce the CC open status. Some TCPC needs time to get the CC + * status valid. Before that, CC open is reported by default. Wait + * to make sure the CC is really open. Reuse the role toggle timer. + */ + if (get_time().val < tc[port].next_role_swap) + return; + + /* + * Initialize type-C supplier current limits to 0. The charge + * manage is now seeded if it was not. + */ + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) + typec_set_input_current_limit(port, 0, 0); + + /* + * Attempt TCPC auto DRP toggle if it is + * not already auto toggling. + */ + if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && + drp_state[port] == PD_DRP_TOGGLE_ON && + tcpm_auto_toggle_supported(port)) { + set_state_tc(port, TC_DRP_AUTO_TOGGLE); + } else if (drp_state[port] == PD_DRP_TOGGLE_ON) { + /* DRP Toggle. The timer was checked above. */ set_state_tc(port, TC_UNATTACHED_SRC); } else if (IS_ENABLED(CONFIG_USB_PD_TCPC_LOW_POWER) && (drp_state[port] == PD_DRP_FORCE_SINK || -- cgit v1.2.1