summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-09-22 16:57:03 -0600
committerJustin TerAvest <teravest@chromium.org>2020-10-01 23:04:47 +0000
commit8b05bdfc38ccc2b1eb694ad4d41096e08a5116c4 (patch)
tree243ed41da6da51bed4b650049a185536f0dd5243
parent9b4f53e42e7bfcb2d045eca422b0097cc309a8d2 (diff)
downloadchrome-ec-8b05bdfc38ccc2b1eb694ad4d41096e08a5116c4.tar.gz
TCPMv2: Add VBUS_REMOVED level
For boards which use Vbus ADCs, add a VBUS_REMOVED check level. The level for VBUS_PRESENT should be used in any locations looking for "Vbus is present" on transition, but in order to correctly detect disconnection with a load on Vbus, VBUS_REMOVED (vSinkDisconnect) is required. TODO statements have been added for places where work will be needed to support vSinkDisconnectPD in the future. For boards detecting Vbus through an external chip, the levels will likely be indistinguishable due to the chips setting a lower threshold for disconnect than for connection. Unit test code has also been added to encourage new Vbus levels to be added to the mock, and remind developers to update all locations using the vbus_level enum. BRANCH=None BUG=b:168831161 TEST=make -j buildall Signed-off-by: Diana Z <dzigterman@chromium.org> Change-Id: I04014ce54ec162dd9c62f545126d921c6d880741 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2436580 Reviewed-by: Denis Brockus <dbrockus@chromium.org>
-rw-r--r--common/mock/tcpc_mock.c12
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c21
-rw-r--r--driver/tcpm/tcpci.c13
-rw-r--r--include/usb_pd.h4
-rw-r--r--include/usb_pd_tcpm.h11
5 files changed, 51 insertions, 10 deletions
diff --git a/common/mock/tcpc_mock.c b/common/mock/tcpc_mock.c
index 64a1ce01cf..457868c96a 100644
--- a/common/mock/tcpc_mock.c
+++ b/common/mock/tcpc_mock.c
@@ -8,6 +8,7 @@
#include "console.h"
#include "memory.h"
#include "mock/tcpc_mock.h"
+#include "test_util.h"
#include "tests/enum_strings.h"
#include "timer.h"
#include "usb_pd_tcpm.h"
@@ -51,8 +52,17 @@ static bool mock_check_vbus_level(int port, enum vbus_level level)
{
if (level == VBUS_PRESENT)
return mock_tcpc.vbus_level;
- else
+ else if (level == VBUS_SAFE0V || level == VBUS_REMOVED)
return !mock_tcpc.vbus_level;
+
+ /*
+ * Unknown vbus_level was added, force a failure.
+ * Note that TCPC drivers and pd_check_vbus_level() implementations
+ * should be carefully checked on new level additions in case they
+ * need updated.
+ */
+ ccprints("[TCPC] Unhandled Vbus check %d", level);
+ TEST_ASSERT(0);
}
static int mock_select_rp_value(int port, int rp)
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
index 2a5ac25944..45d28687a0 100644
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
@@ -2271,6 +2271,19 @@ static void tc_attached_snk_run(const int port)
}
/*
+ * From 4.5.2.2.5.2 Exiting from Attached.SNK State:
+ *
+ * "A port that is not a Vconn-Powered USB Device and is not in the
+ * process of a USB PD PR_Swap or a USB PD Hard Reset or a USB PD
+ * FR_Swap shall transition to Unattached.SNK within tSinkDisconnect
+ * when Vbus falls below vSinkDisconnect for Vbus operating at or
+ * below 5 V or below vSinkDisconnectPD when negotiated by USB PD
+ * to operate above 5 V."
+ *
+ * TODO(b/149530538): Use vSinkDisconnectPD when above 5V
+ */
+
+ /*
* Debounce Vbus before we drop that we are doing a PR_Swap
*/
if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) &&
@@ -2284,7 +2297,7 @@ static void tc_attached_snk_run(const int port)
* with the swap and should have Vbus, so re-enable
* AutoDischargeDisconnect.
*/
- if (pd_is_vbus_present(port))
+ if (!pd_check_vbus_level(port, VBUS_REMOVED))
tcpm_enable_auto_discharge_disconnect(port, 1);
}
@@ -2297,7 +2310,7 @@ static void tc_attached_snk_run(const int port)
/*
* Detach detection
*/
- if (!pd_is_vbus_present(port)) {
+ if (pd_check_vbus_level(port, VBUS_REMOVED)) {
if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0);
pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0);
@@ -2396,7 +2409,7 @@ static void tc_attached_snk_run(const int port)
#else /* CONFIG_USB_PE_SM */
/* Detach detection */
- if (!pd_is_vbus_present(port)) {
+ if (pd_check_vbus_level(port, VBUS_REMOVED)) {
set_state_tc(port, TC_UNATTACHED_SNK);
return;
}
@@ -3331,7 +3344,7 @@ static void tc_ct_attached_snk_run(int port)
* transition to CTUnattached.SNK within tSinkDisconnect when VBUS
* falls below vSinkDisconnect
*/
- if (!pd_is_vbus_present(port)) {
+ if (pd_check_vbus_level(port, VBUS_REMOVED)) {
set_state_tc(port, TC_CT_UNATTACHED_SNK);
return;
}
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 5af5fe0151..fd6a5906a5 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -100,7 +100,14 @@ STATIC_IF(DEBUG_GET_CC)
* Last reported VBus Level
*
* BIT(VBUS_SAFE0V) will indicate if in SAFE0V
- * BIT(VBUS_PRESENT) will indicate if in PRESENT
+ * BIT(VBUS_PRESENT) will indicate if in PRESENT in the TCPCI POWER_STATUS
+ *
+ * Note that VBUS_REMOVED cannot be distinguished from !VBUS_PRESENT with
+ * this interface, but the trigger thresholds for Vbus Present should allow the
+ * same bit to be used safely for both.
+ *
+ * TODO(b/149530538): Some TCPCs may be able to implement
+ * VBUS_SINK_DISCONNECT_THRESHOLD to support vSinkDisconnectPD
*/
static int tcpc_vbus[CONFIG_USB_PD_PORT_MAX_COUNT];
@@ -718,8 +725,10 @@ bool tcpci_tcpm_check_vbus_level(int port, enum vbus_level level)
{
if (level == VBUS_SAFE0V)
return !!(tcpc_vbus[port] & BIT(VBUS_SAFE0V));
- else
+ else if (level == VBUS_PRESENT)
return !!(tcpc_vbus[port] & BIT(VBUS_PRESENT));
+ else
+ return !(tcpc_vbus[port] & BIT(VBUS_PRESENT));
}
#endif
diff --git a/include/usb_pd.h b/include/usb_pd.h
index c42afd2b28..40b24aa79f 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -254,6 +254,10 @@ enum pd_rx_errors {
#define PD_V_SAFE0V_MAX 800
#define PD_V_SAFE5V_MIN 4750
+/* USB Type-C voltages in mV (Table 4-3, USB Type-C Release 2.0 Spec) */
+#define PD_V_SINK_DISCONNECT_MAX 3670
+/* TODO(b/149530538): Add equation for vSinkDisconnectPD */
+
/* function table for entered mode */
struct amode_fx {
int (*status)(int port, uint32_t *payload);
diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h
index d6f89553fc..9044942171 100644
--- a/include/usb_pd_tcpm.h
+++ b/include/usb_pd_tcpm.h
@@ -104,10 +104,15 @@ enum tcpc_transmit_complete {
TCPC_TX_COMPLETE_FAILED = 2,
};
-/* USB-C PD Vbus levels */
+/*
+ * USB-C PD Vbus levels
+ *
+ * Return true on Vbus check if Vbus is...
+ */
enum vbus_level {
- VBUS_SAFE0V,
- VBUS_PRESENT,
+ VBUS_SAFE0V, /* less than vSafe0V max */
+ VBUS_PRESENT, /* at least vSafe5V min */
+ VBUS_REMOVED, /* less than vSinkDisconnect max */
};
/**