summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2022-12-12 17:27:50 -0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-04-13 01:20:27 +0000
commit57ed659cb9abdb659ee472cdd1c1f1069a3e2b6d (patch)
tree8bed2b115aaddf554fed8a8e816c6979ef62e9bf
parentd1a831463f7f8aab5efb7b46c4e4ba508ee323ec (diff)
downloadchrome-ec-57ed659cb9abdb659ee472cdd1c1f1069a3e2b6d.tar.gz
USB-PD: Update EC_CMD_TYPEC_STATUS for EPR
Currently, EC_CMD_TYPEC_STATUS can carry up to 7 PDOs. With EPR, the max number of PDOs is 11. This patch adds version 1 of the command with the new response struct which has 11 slots for source caps and sink caps. BRANCH=None BUG=b:257320026 TEST=Tested v0 on Vell. v1 will be tested when time comes. Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Change-Id: I694b5897de7faee8e492c7cdc196ff94dd9c8fb4 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4294392 Reviewed-by: Keith Short <keithshort@chromium.org>
-rw-r--r--common/usbc/usb_pd_host.c100
-rw-r--r--include/ec_commands.h54
2 files changed, 123 insertions, 31 deletions
diff --git a/common/usbc/usb_pd_host.c b/common/usbc/usb_pd_host.c
index 5f57393bb2..06da8a711c 100644
--- a/common/usbc/usb_pd_host.c
+++ b/common/usbc/usb_pd_host.c
@@ -178,40 +178,67 @@ static enum ec_status hc_typec_control(struct host_cmd_handler_args *args)
}
DECLARE_HOST_COMMAND(EC_CMD_TYPEC_CONTROL, hc_typec_control, EC_VER_MASK(0));
+/*
+ * Validate ec_response_typec_status_v0's binary compatibility with
+ * ec_response_typec_status, which is being deprecated.
+ */
+BUILD_ASSERT(offsetof(struct ec_response_typec_status_v0,
+ typec_status.sop_prime_revision) ==
+ offsetof(struct ec_response_typec_status, sop_prime_revision));
+BUILD_ASSERT(offsetof(struct ec_response_typec_status_v0, source_cap_pdos) ==
+ offsetof(struct ec_response_typec_status, source_cap_pdos));
+BUILD_ASSERT(sizeof(struct ec_response_typec_status_v0) ==
+ sizeof(struct ec_response_typec_status));
+
+/*
+ * Validate ec_response_typec_status_v0's binary compatibility with
+ * ec_response_typec_status_v1 with respect to typec_status.
+ */
+BUILD_ASSERT(offsetof(struct ec_response_typec_status_v0,
+ typec_status.pd_enabled) ==
+ offsetof(struct ec_response_typec_status_v1,
+ typec_status.pd_enabled));
+BUILD_ASSERT(offsetof(struct ec_response_typec_status_v0,
+ typec_status.sop_prime_revision) ==
+ offsetof(struct ec_response_typec_status_v1,
+ typec_status.sop_prime_revision));
+
static enum ec_status hc_typec_status(struct host_cmd_handler_args *args)
{
const struct ec_params_typec_status *p = args->params;
- struct ec_response_typec_status *r = args->response;
+ struct ec_response_typec_status_v1 *r1 = args->response;
+ struct ec_response_typec_status_v0 *r0 = args->response;
+ struct cros_ec_typec_status *cs = &r1->typec_status;
const char *tc_state_name;
if (p->port >= board_get_usb_pd_port_count())
return EC_RES_INVALID_PARAM;
- if (args->response_max < sizeof(*r))
- return EC_RES_RESPONSE_TOO_BIG;
+ args->response_size = args->version == 0 ? sizeof(*r0) : sizeof(*r1);
- args->response_size = sizeof(*r);
+ if (args->response_max < args->response_size)
+ return EC_RES_RESPONSE_TOO_BIG;
- r->pd_enabled = pd_comm_is_enabled(p->port);
- r->dev_connected = pd_is_connected(p->port);
- r->sop_connected = pd_capable(p->port);
+ cs->pd_enabled = pd_comm_is_enabled(p->port);
+ cs->dev_connected = pd_is_connected(p->port);
+ cs->sop_connected = pd_capable(p->port);
- r->power_role = pd_get_power_role(p->port);
- r->data_role = pd_get_data_role(p->port);
- r->vconn_role = pd_get_vconn_state(p->port) ? PD_ROLE_VCONN_SRC :
- PD_ROLE_VCONN_OFF;
- r->polarity = pd_get_polarity(p->port);
- r->cc_state = pd_get_task_cc_state(p->port);
- r->dp_pin = get_dp_pin_mode(p->port);
- r->mux_state = usb_mux_get(p->port);
+ cs->power_role = pd_get_power_role(p->port);
+ cs->data_role = pd_get_data_role(p->port);
+ cs->vconn_role = pd_get_vconn_state(p->port) ? PD_ROLE_VCONN_SRC :
+ PD_ROLE_VCONN_OFF;
+ cs->polarity = pd_get_polarity(p->port);
+ cs->cc_state = pd_get_task_cc_state(p->port);
+ cs->dp_pin = get_dp_pin_mode(p->port);
+ cs->mux_state = usb_mux_get(p->port);
tc_state_name = pd_get_task_state_name(p->port);
- strzcpy(r->tc_state, tc_state_name, sizeof(r->tc_state));
+ strzcpy(cs->tc_state, tc_state_name, sizeof(cs->tc_state));
- r->events = pd_get_events(p->port);
+ cs->events = pd_get_events(p->port);
if (pd_get_partner_rmdo(p->port).major_rev != 0) {
- r->sop_revision =
+ cs->sop_revision =
PD_STATUS_RMDO_REV_SET_MAJOR(
pd_get_partner_rmdo(p->port).major_rev) |
PD_STATUS_RMDO_REV_SET_MINOR(
@@ -220,28 +247,41 @@ static enum ec_status hc_typec_status(struct host_cmd_handler_args *args)
pd_get_partner_rmdo(p->port).major_ver) |
PD_STATUS_RMDO_VER_SET_MINOR(
pd_get_partner_rmdo(p->port).minor_ver);
- } else if (r->sop_connected) {
- r->sop_revision = PD_STATUS_REV_SET_MAJOR(
+ } else if (cs->sop_connected) {
+ cs->sop_revision = PD_STATUS_REV_SET_MAJOR(
pd_get_rev(p->port, TCPCI_MSG_SOP));
} else {
- r->sop_revision = 0;
+ cs->sop_revision = 0;
}
- r->sop_prime_revision =
+ cs->sop_prime_revision =
pd_get_identity_discovery(p->port, TCPCI_MSG_SOP_PRIME) ==
PD_DISC_COMPLETE ?
PD_STATUS_REV_SET_MAJOR(
pd_get_rev(p->port, TCPCI_MSG_SOP_PRIME)) :
0;
- r->source_cap_count = pd_get_src_cap_cnt(p->port);
- memcpy(r->source_cap_pdos, pd_get_src_caps(p->port),
- r->source_cap_count * sizeof(uint32_t));
-
- r->sink_cap_count = pd_get_snk_cap_cnt(p->port);
- memcpy(r->sink_cap_pdos, pd_get_snk_caps(p->port),
- r->sink_cap_count * sizeof(uint32_t));
+ if (args->version == 0) {
+ cs->source_cap_count = MIN(pd_get_src_cap_cnt(p->port),
+ ARRAY_SIZE(r0->source_cap_pdos));
+ memcpy(r0->source_cap_pdos, pd_get_src_caps(p->port),
+ cs->source_cap_count * sizeof(uint32_t));
+ cs->sink_cap_count = MIN(pd_get_snk_cap_cnt(p->port),
+ ARRAY_SIZE(r0->sink_cap_pdos));
+ memcpy(r0->sink_cap_pdos, pd_get_snk_caps(p->port),
+ cs->sink_cap_count * sizeof(uint32_t));
+ } else {
+ cs->source_cap_count = MIN(pd_get_src_cap_cnt(p->port),
+ ARRAY_SIZE(r1->source_cap_pdos));
+ memcpy(r1->source_cap_pdos, pd_get_src_caps(p->port),
+ cs->source_cap_count * sizeof(uint32_t));
+ cs->sink_cap_count = MIN(pd_get_snk_cap_cnt(p->port),
+ ARRAY_SIZE(r1->sink_cap_pdos));
+ memcpy(r1->sink_cap_pdos, pd_get_snk_caps(p->port),
+ cs->sink_cap_count * sizeof(uint32_t));
+ }
return EC_RES_SUCCESS;
}
-DECLARE_HOST_COMMAND(EC_CMD_TYPEC_STATUS, hc_typec_status, EC_VER_MASK(0));
+DECLARE_HOST_COMMAND(EC_CMD_TYPEC_STATUS, hc_typec_status,
+ EC_VER_MASK(0) | EC_VER_MASK(1));
diff --git a/include/ec_commands.h b/include/ec_commands.h
index a74543bd93..ecf499eb84 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -7029,7 +7029,12 @@ struct ec_params_typec_status {
uint8_t port;
} __ec_align1;
-struct ec_response_typec_status {
+/*
+ * ec_response_typec_status is deprecated. Use ec_response_typec_status_v1.
+ * If you need to support old ECs who speak only v0, use
+ * ec_response_typec_status_v0 instead. They're binary-compatible.
+ */
+struct ec_response_typec_status /* DEPRECATED */ {
uint8_t pd_enabled; /* PD communication enabled - bool */
uint8_t dev_connected; /* Device connected - bool */
uint8_t sop_connected; /* Device is SOP PD capable - bool */
@@ -7068,6 +7073,53 @@ struct ec_response_typec_status {
uint32_t sink_cap_pdos[7]; /* Max 7 PDOs can be present */
} __ec_align1;
+struct cros_ec_typec_status {
+ uint8_t pd_enabled; /* PD communication enabled - bool */
+ uint8_t dev_connected; /* Device connected - bool */
+ uint8_t sop_connected; /* Device is SOP PD capable - bool */
+ uint8_t source_cap_count; /* Number of Source Cap PDOs */
+
+ uint8_t power_role; /* enum pd_power_role */
+ uint8_t data_role; /* enum pd_data_role */
+ uint8_t vconn_role; /* enum pd_vconn_role */
+ uint8_t sink_cap_count; /* Number of Sink Cap PDOs */
+
+ uint8_t polarity; /* enum tcpc_cc_polarity */
+ uint8_t cc_state; /* enum pd_cc_states */
+ uint8_t dp_pin; /* DP pin mode (MODE_DP_IN_[A-E]) */
+ uint8_t mux_state; /* USB_PD_MUX* - encoded mux state */
+
+ char tc_state[32]; /* TC state name */
+
+ uint32_t events; /* PD_STATUS_EVENT bitmask */
+
+ /*
+ * BCD PD revisions for partners
+ *
+ * The format has the PD major revision in the upper nibble, and the PD
+ * minor revision in the next nibble. The following two nibbles hold the
+ * major and minor specification version. If a partner does not support
+ * the Revision message, only the major revision will be given.
+ * ex. PD Revision 3.2 Version 1.9 would map to 0x3219
+ *
+ * PD revision/version will be 0 if no PD device is connected.
+ */
+ uint16_t sop_revision;
+ uint16_t sop_prime_revision;
+} __ec_align1;
+
+struct ec_response_typec_status_v0 {
+ struct cros_ec_typec_status typec_status;
+ uint32_t source_cap_pdos[7]; /* Max 7 PDOs can be present */
+ uint32_t sink_cap_pdos[7]; /* Max 7 PDOs can be present */
+} __ec_align1;
+
+struct ec_response_typec_status_v1 {
+ struct cros_ec_typec_status typec_status;
+ uint32_t source_cap_pdos[11]; /* Max 11 PDOs can be present */
+ uint32_t sink_cap_pdos[11]; /* Max 11 PDOs can be present */
+} __ec_align1;
+
/**
* Get the number of peripheral charge ports
*/