diff options
author | Jameson Thies <jthies@google.com> | 2022-04-26 00:31:30 +0000 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-05-04 22:27:27 +0000 |
commit | cb74b8ed9fdc852bc5b4d79424a5b4434a939742 (patch) | |
tree | d321af60342f68aa0f8b2cb08b0e22e2e9c0027c /common | |
parent | 94b53640add6248bd7f6847a1c0096e07db04188 (diff) | |
download | chrome-ec-cb74b8ed9fdc852bc5b4d79424a5b4434a939742.tar.gz |
TCPMv2: Request partner's revision information in src/snk startup
Adding features from the USB PD 3.1 revision of the specification
requires us to know the difference between USB PD Rev 3.0 and USB PD Rev
3.1 devices. But, the message header only has 2 bits for revision and
only provides the major revision. To determine a devices minor
revision, TCPMv2 will need to send a Get_Revision command and store the
Revision response which has major/minor revision/version information.
This CL adds support for sending Get_Revision, and receiving Revision.
BUG=b:214087135
TEST=Checked that the PE state was correctly holding the Revision
response from a USB PD Rev 3.1 partner, and also checked that the stored
RMDO value was 0 for a USB PD Rev 3.0 partner.
BRANCH=none
Signed-off-by: Jameson Thies <jthies@google.com>
Change-Id: I99f10c15750c3a1fee1d8bad89b0c4a0b0a6b2ba
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3607054
Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
Diffstat (limited to 'common')
-rw-r--r-- | common/mock/tcpci_i2c_mock.c | 12 | ||||
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 114 |
2 files changed, 126 insertions, 0 deletions
diff --git a/common/mock/tcpci_i2c_mock.c b/common/mock/tcpci_i2c_mock.c index 8ec7556fca..c9b9f71738 100644 --- a/common/mock/tcpci_i2c_mock.c +++ b/common/mock/tcpci_i2c_mock.c @@ -99,6 +99,9 @@ static const char * const ctrl_msg_name[] = { [PD_CTRL_FR_SWAP] = "C-FR_SWAP", [PD_CTRL_GET_PPS_STATUS] = "C-GET_PPS_STATUS", [PD_CTRL_GET_COUNTRY_CODES] = "C-GET_COUNTRY_CODES", + [PD_CTRL_GET_SINK_CAP_EXT] = "C-GET_SINK_CAP_EXT", + [PD_CTRL_GET_SOURCE_INFO] = "C-GET_SOURCE_INFO", + [PD_CTRL_GET_REVISION] = "C-GET_REVISION", }; static const char * const data_msg_name[] = { @@ -113,6 +116,11 @@ static const char * const data_msg_name[] = { [PD_DATA_GET_COUNTRY_INFO] = "D-GET_COUNTRY_CODES", /* 8-14 Reserved for REV 3.0 */ [PD_DATA_ENTER_USB] = "D-ENTER_USB", + [PD_DATA_EPR_REQUEST] = "D-EPR_REQUEST", + [PD_DATA_EPR_MODE] = "D-EPR_MODE", + [PD_DATA_SOURCE_INFO] = "D-EPR_SOURCE_INFO", + [PD_DATA_REVISION] = "D-REVISION", + /* 13-14 Reserved for REV 3.0 */ [PD_DATA_VENDOR_DEF] = "D-VDM", }; @@ -132,6 +140,10 @@ static const char * const ext_msg_name[] = { [PD_EXT_PPS_STATUS] = "X-PPS_STATUS", [PD_EXT_COUNTRY_INFO] = "X-COUNTRY_INFO", [PD_EXT_COUNTRY_CODES] = "X-COUNTRY_CODES", + [PD_EXT_SINK_CAP] = "X-SNK_CAP", + [PD_EXT_CONTROL] = "X-CONTROL", + [PD_EXT_EPR_SOURCE_CAP] = "X-EPR_SRC_CAP", + [PD_EXT_EPR_SINK_CAP] = "X-EPR_SNK_CAP", }; static const char * const rev_name[] = { diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index bc3dcf48e7..352e2b4fe3 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -275,6 +275,7 @@ enum usb_pe_state { PE_SRC_CHUNK_RECEIVED, PE_SNK_CHUNK_RECEIVED, PE_VCS_FORCE_VCONN, + PE_GET_REVISION, }; /* @@ -390,6 +391,7 @@ __maybe_unused static __const_data const char * const pe_state_names[] = { /* PD3.0 only states below here*/ #ifdef CONFIG_USB_PD_REV30 [PE_FRS_SNK_SRC_START_AMS] = "PE_FRS_SNK_SRC_Start_Ams", + [PE_GET_REVISION] = "PE_Get_Revision", #ifdef CONFIG_USB_PD_EXTENDED_MESSAGES [PE_GIVE_BATTERY_CAP] = "PE_Give_Battery_Cap", [PE_GIVE_BATTERY_STATUS] = "PE_Give_Battery_Status", @@ -435,6 +437,8 @@ GEN_NOT_SUPPORTED(PE_SRC_CHUNK_RECEIVED); #define PE_SRC_CHUNK_RECEIVED PE_SRC_CHUNK_RECEIVED_NOT_SUPPORTED GEN_NOT_SUPPORTED(PE_SNK_CHUNK_RECEIVED); #define PE_SNK_CHUNK_RECEIVED PE_SNK_CHUNK_RECEIVED_NOT_SUPPORTED +GEN_NOT_SUPPORTED(PE_GET_REVISION); +#define PE_GET_REVISION PE_GET_REVISION_NOT_SUPPORTED #endif /* CONFIG_USB_PD_REV30 */ #if !defined(CONFIG_USBC_VCONN) || !defined(CONFIG_USB_PD_REV30) @@ -622,6 +626,9 @@ static struct policy_engine { uint32_t snk_caps[PDO_MAX_OBJECTS]; int snk_cap_cnt; + /* Last received Revision Message Data Object (RMDO) from the partner */ + struct rmdo partner_rmdo; + /* Attached ChromeOS device id, RW hash, and current RO / RW image */ uint16_t dev_id; uint32_t dev_rw_hash[PD_RW_HASH_SIZE/4]; @@ -1353,6 +1360,15 @@ static void pe_clear_port_data(int port) pd_set_src_caps(port, 0, NULL); pe_set_snk_caps(port, 0, NULL); + /* + * Saved Revision responses are no longer valid on disconnect + */ + pe[port].partner_rmdo.reserved = 0; + pe[port].partner_rmdo.minor_ver = 0; + pe[port].partner_rmdo.major_ver = 0; + pe[port].partner_rmdo.minor_rev = 0; + pe[port].partner_rmdo.major_rev = 0; + /* Clear any stored discovery data, but leave modes for alt mode exit */ pd_dfp_discovery_init(port); @@ -1558,6 +1574,11 @@ static bool common_src_snk_dpm_requests(int port) else return false; return true; + } else if (IS_ENABLED(CONFIG_USB_PD_REV30) && + PE_CHK_DPM_REQUEST(port, DPM_REQUEST_GET_REVISION)) { + pe_set_dpm_curr_request(port, DPM_REQUEST_GET_REVISION); + set_state_pe(port, PE_GET_REVISION); + return true; } return false; @@ -2190,6 +2211,14 @@ static void pe_src_startup_entry(int port) CONFIG_USB_PD_3A_PORTS > 0 || IS_ENABLED(CONFIG_USB_PD_FRS)) pd_dpm_request(port, DPM_REQUEST_GET_SNK_CAPS); + + /* + * Request partner's revision information. The PE_Get_Revision + * state will only send Get_Revision to partners with major + * revision 3.0 + */ + pd_dpm_request(port, DPM_REQUEST_GET_REVISION); + } } @@ -3080,6 +3109,13 @@ static void pe_snk_startup_entry(int port) IS_ENABLED(CONFIG_USB_PD_FRS)) pd_dpm_request(port, DPM_REQUEST_GET_SNK_CAPS); + /* + * Request partner's revision information. The PE_Get_Revision + * state will only send Get_Revision to partners with major + * revision 3.0 + */ + pd_dpm_request(port, DPM_REQUEST_GET_REVISION); + } static void pe_snk_startup_run(int port) @@ -7072,6 +7108,79 @@ static void pe_dr_src_get_source_cap_exit(int port) pe_sender_response_msg_exit(port); } +/* + * PE_Get_Revision + */ +__maybe_unused static void pe_get_revision_entry(int port) +{ + print_current_state(port); + + /* + * Only USB PD partners with major revision 3.0 could potentially + * respond to Get_Revision. + */ + if (prl_get_rev(port, TCPCI_MSG_SOP) != PD_REV30) + return; + + /* Send a Get_Revision message */ + send_ctrl_msg(port, TCPCI_MSG_SOP, PD_CTRL_GET_REVISION); + pe_sender_response_msg_entry(port); +} + +__maybe_unused static void pe_get_revision_run(int port) +{ + int type; + int cnt; + int ext; + enum pe_msg_check msg_check; + + if (prl_get_rev(port, TCPCI_MSG_SOP) != PD_REV30) { + pe_set_ready_state(port); + return; + } + + /* Check the state of the message sent */ + msg_check = pe_sender_response_msg_run(port); + + if ((msg_check & PE_MSG_SENT) && + PE_CHK_FLAG(port, PE_FLAGS_MSG_RECEIVED)) { + PE_CLR_FLAG(port, PE_FLAGS_MSG_RECEIVED); + + type = PD_HEADER_TYPE(rx_emsg[port].header); + cnt = PD_HEADER_CNT(rx_emsg[port].header); + ext = PD_HEADER_EXT(rx_emsg[port].header); + + if (ext == 0 && cnt == 1 && type == PD_DATA_REVISION) { + /* Revision returned by partner */ + pe[port].partner_rmdo = + *((struct rmdo *) rx_emsg[port].buf); + } + + /* + * Get_Revision is an interruptible AMS. Return to ready state + * after response whether or not there was a protocol error. + */ + pe_set_ready_state(port); + return; + } + + /* + * Return to ready state if the message was discarded or timer expires + */ + if ((msg_check & PE_MSG_DISCARDED) || + pd_timer_is_expired(port, PE_TIMER_SENDER_RESPONSE)) + pe_set_ready_state(port); + +} + +__maybe_unused static void pe_get_revision_exit(int port) +{ + if (prl_get_rev(port, TCPCI_MSG_SOP) != PD_REV30) + return; + + pe_sender_response_msg_exit(port); +} + #ifdef CONFIG_USB_PD_DATA_RESET_MSG /* * PE_DDR_Send_Data_Reset @@ -7797,6 +7906,11 @@ static __const_data const struct usb_state pe_states[] = { .entry = pe_frs_snk_src_start_ams_entry, .parent = &pe_states[PE_PRS_FRS_SHARED], }, + [PE_GET_REVISION] = { + .entry = pe_get_revision_entry, + .run = pe_get_revision_run, + .exit = pe_get_revision_exit, + }, #ifdef CONFIG_USB_PD_EXTENDED_MESSAGES [PE_GIVE_BATTERY_CAP] = { .entry = pe_give_battery_cap_entry, |