summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJameson Thies <jthies@google.com>2022-05-19 00:29:09 +0000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-05-21 23:48:59 +0000
commitd20ada6dab1ded4b3866232976a3ee9b73696d5e (patch)
treecf6d466014786dc3d6bb9fa3b935b3a6d97adfc0
parentadfd6d52b0792cd119319f88b9c2a9789c7c9105 (diff)
downloadchrome-ec-d20ada6dab1ded4b3866232976a3ee9b73696d5e.tar.gz
TCPMV2: Add power state change to status
The Status Data Block (SDB) was updated in USB PD Revision 3.1 to include a Power State Change field which includes New Power State and New Power State Indicator fields. This CL updates dpm_get_status_msg to include the Power State Change field. BUG=b:227236917 TEST=make try_build_boards and make runhosttests BRANCH=None Signed-off-by: Jameson Thies <jthies@google.com> Change-Id: I05ffaa0a66f19bea781b16ab381930700c7f8e47 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3632817 Reviewed-by: Diana Z <dzigterman@chromium.org> Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
-rw-r--r--common/usbc/usb_pd_dpm.c81
-rw-r--r--common/usbc/usb_pe_drp_sm.c5
-rw-r--r--include/usb_pd.h31
-rw-r--r--include/usb_pe_sm.h8
4 files changed, 122 insertions, 3 deletions
diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c
index 45d41b6b1f..734fe53926 100644
--- a/common/usbc/usb_pd_dpm.c
+++ b/common/usbc/usb_pd_dpm.c
@@ -13,6 +13,7 @@
#include "console.h"
#include "ec_commands.h"
#include "hooks.h"
+#include "power.h"
#include "system.h"
#include "task.h"
#include "tcpm/tcpm.h"
@@ -24,6 +25,7 @@
#include "usb_pd_dpm.h"
#include "usb_pd_tcpm.h"
#include "usb_pd_pdo.h"
+#include "usb_pe_sm.h"
#include "usb_tbt_alt_mode.h"
#ifdef CONFIG_ZEPHYR
@@ -818,6 +820,24 @@ int dpm_get_source_current(const int port)
return 500;
}
+__overridable enum pd_sdb_power_indicator board_get_pd_sdb_power_indicator(
+enum pd_sdb_power_state power_state)
+{
+ /*
+ * LED on for S0 and blinking for S0ix/S3.
+ * LED off for all other power states (S4, S5, G3, NOT_SUPPORTED)
+ */
+ switch (power_state) {
+ case PD_SDB_POWER_STATE_S0:
+ return PD_SDB_POWER_INDICATOR_ON;
+ case PD_SDB_POWER_STATE_MODERN_STANDBY:
+ case PD_SDB_POWER_STATE_S3:
+ return PD_SDB_POWER_INDICATOR_BLINKING;
+ default:
+ return PD_SDB_POWER_INDICATOR_OFF;
+ }
+}
+
static uint8_t get_status_internal_temp(void)
{
/*
@@ -863,9 +883,56 @@ static enum pd_sdb_temperature_status get_status_temp_status(void)
#endif
}
+static uint8_t get_status_power_state_change(void)
+{
+ enum pd_sdb_power_state ret = PD_SDB_POWER_STATE_NOT_SUPPORTED;
+
+#ifdef HAS_TASK_CHIPSET
+ switch (power_get_state()) {
+ case POWER_G3:
+ case POWER_S5G3:
+ ret = PD_SDB_POWER_STATE_G3;
+ break;
+ case POWER_S5:
+ case POWER_G3S5:
+ case POWER_S3S5:
+ case POWER_S4S5:
+ ret = PD_SDB_POWER_STATE_S5;
+ break;
+ case POWER_S4:
+ case POWER_S3S4:
+ case POWER_S5S4:
+ ret = PD_SDB_POWER_STATE_S4;
+ break;
+ case POWER_S3:
+ case POWER_S5S3:
+ case POWER_S0S3:
+ case POWER_S4S3:
+ ret = PD_SDB_POWER_STATE_S3;
+ break;
+ case POWER_S0:
+ case POWER_S3S0:
+#ifdef CONFIG_POWER_S0IX
+ case POWER_S0ixS0:
+#endif /* CONFIG_POWER_S0IX */
+ ret = PD_SDB_POWER_STATE_S0;
+ break;
+#ifdef CONFIG_POWER_S0IX
+ case POWER_S0ix:
+ case POWER_S0S0ix:
+ ret = PD_SDB_POWER_STATE_MODERN_STANDBY;
+ break;
+#endif /* CONFIG_POWER_S0IX */
+ }
+#endif /* HAS_TASK_CHIPSET */
+
+ return ret | board_get_pd_sdb_power_indicator(ret);
+}
+
int dpm_get_status_msg(int port, uint8_t *msg, uint32_t *len)
{
struct pd_sdb sdb;
+ struct rmdo partner_rmdo;
/* TODO(b/227236917): Fill in fields of Status message */
@@ -887,10 +954,18 @@ int dpm_get_status_msg(int port, uint8_t *msg, uint32_t *len)
/* Power Status */
sdb.power_status = 0x0;
- /* USB PD Rev 3.0: 6.5.2 Status Message */
- *len = 6;
+ partner_rmdo = pe_get_partner_rmdo(port);
+ if ((partner_rmdo.major_rev == 3 && partner_rmdo.minor_rev >= 1) ||
+ partner_rmdo.major_rev > 3) {
+ /* USB PD Rev 3.1: 6.5.2 Status Message */
+ sdb.power_state_change = get_status_power_state_change();
+ *len = 7;
+ } else {
+ /* USB PD Rev 3.0: 6.5.2 Status Message */
+ sdb.power_state_change = 0;
+ *len = 6;
+ }
memcpy(msg, &sdb, *len);
-
return EC_SUCCESS;
}
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index 6906c4c6f8..654748a8bd 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -1433,6 +1433,11 @@ void pe_clear_ado(int port)
mutex_unlock(&pe[port].ado_lock);
}
+struct rmdo pe_get_partner_rmdo(int port)
+{
+ return pe[port].partner_rmdo;
+}
+
static void pe_handle_detach(void)
{
const int port = TASK_ID_TO_PD_PORT(task_get_current());
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 12e34520bc..62a8330c54 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -1217,12 +1217,32 @@ enum pd_sdb_temperature_status {
BUILD_ASSERT(sizeof(enum pd_sdb_temperature_status) == 1);
struct pd_sdb {
+ /* SDB Fields for PD REV 3.0 */
uint8_t internal_temp;
uint8_t present_input;
uint8_t present_battery_input;
uint8_t event_flags;
enum pd_sdb_temperature_status temperature_status;
uint8_t power_status;
+ /* SDB Fields for PD REV 3.1 */
+ uint8_t power_state_change;
+};
+
+enum pd_sdb_power_state {
+ PD_SDB_POWER_STATE_NOT_SUPPORTED = 0,
+ PD_SDB_POWER_STATE_S0 = 1,
+ PD_SDB_POWER_STATE_MODERN_STANDBY = 2,
+ PD_SDB_POWER_STATE_S3 = 3,
+ PD_SDB_POWER_STATE_S4 = 4,
+ PD_SDB_POWER_STATE_S5 = 5,
+ PD_SDB_POWER_STATE_G3 = 6,
+};
+
+enum pd_sdb_power_indicator {
+ PD_SDB_POWER_INDICATOR_OFF = (0 << 3),
+ PD_SDB_POWER_INDICATOR_ON = (1 << 3),
+ PD_SDB_POWER_INDICATOR_BLINKING = (2 << 3),
+ PD_SDB_POWER_INDICATOR_BREATHING = (3 << 3),
};
/* Extended message type for REV 3.0 */
@@ -3515,6 +3535,17 @@ void typec_select_src_collision_rp(int port, enum tcpc_rp_value rp);
* @return 0 on success else failure
*/
int typec_update_cc(int port);
+
+/**
+ * Defines the New power state indicator bits in the Power State Change
+ * field of the Status Data Block (SDB) in USB PD Revision 3.1 and above.
+ *
+ * @param pd_sdb_power_state enum defining the New Power State field of the SDB
+ * @return pd_sdb_power_indicator enum for the SDB
+ */
+__override_proto enum pd_sdb_power_indicator board_get_pd_sdb_power_indicator(
+enum pd_sdb_power_state power_state);
+
/****************************************************************************/
#endif /* __CROS_EC_USB_PD_H */
diff --git a/include/usb_pe_sm.h b/include/usb_pe_sm.h
index aef262ef49..4018f16322 100644
--- a/include/usb_pe_sm.h
+++ b/include/usb_pe_sm.h
@@ -192,6 +192,14 @@ int pe_set_ado(int port, uint32_t data);
*/
void pe_clear_ado(int port);
+/**
+ * Gets port partner's RMDO from the PE state.
+ *
+ * @param port USB-C port number
+ * @return port partner's Revision Message Data Object (RMDO).
+ */
+struct rmdo pe_get_partner_rmdo(int port);
+
#ifdef TEST_BUILD
/**
* Clears all internal port data, as we would on a detach event