diff options
-rw-r--r-- | common/usb_common.c | 20 | ||||
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 46 | ||||
-rw-r--r-- | include/usb_common.h | 10 | ||||
-rw-r--r-- | include/usb_pd.h | 10 | ||||
-rw-r--r-- | include/usb_pe_sm.h | 1 |
5 files changed, 86 insertions, 1 deletions
diff --git a/common/usb_common.c b/common/usb_common.c index 9c1c980a8c..7b7f392e32 100644 --- a/common/usb_common.c +++ b/common/usb_common.c @@ -792,3 +792,23 @@ static int command_tcpc_dump(int argc, char **argv) DECLARE_CONSOLE_COMMAND(tcpci_dump, command_tcpc_dump, "<Type-C port>", "dump the TCPC regs"); #endif /* defined(CONFIG_CMD_TCPC_DUMP) */ + +int pd_build_alert_msg(uint32_t *msg, uint32_t *len, enum pd_power_role pr) +{ + if (msg == NULL || len == NULL) + return EC_ERROR_INVAL; + + /* + * SOURCE: currently only supports OCP + * SINK: currently only supports OVP + */ + if (pr == PD_ROLE_SOURCE) + *msg = ADO_OCP_EVENT; + else + *msg = ADO_OVP_EVENT; + + /* Alert data is 4 bytes */ + *len = 4; + + return EC_SUCCESS; +} diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index 276f498777..1088d1ede8 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -250,6 +250,7 @@ enum usb_pe_state { PE_FRS_SNK_SRC_START_AMS, PE_GIVE_BATTERY_CAP, PE_GIVE_BATTERY_STATUS, + PE_SEND_ALERT, #ifdef CONFIG_USB_PD_REV30 /* Super States */ @@ -342,6 +343,7 @@ static const char * const pe_state_names[] = { [PE_FRS_SNK_SRC_START_AMS] = "PE_FRS_SNK_SRC_Start_Ams", [PE_GIVE_BATTERY_CAP] = "PE_Give_Battery_Cap", [PE_GIVE_BATTERY_STATUS] = "PE_Give_Battery_Status", + [PE_SEND_ALERT] = "PE_Send_Alert", /* Super States */ [PE_PRS_FRS_SHARED] = "SS:PE_PRS_FRS_SHARED", @@ -1093,7 +1095,12 @@ test_export_static enum usb_pe_state get_state_pe(const int port) static bool common_src_snk_dpm_requests(int port) { - if (IS_ENABLED(CONFIG_USBC_VCONN) && + if (IS_ENABLED(CONFIG_USB_PD_REV30) && + PE_CHK_DPM_REQUEST(port, DPM_REQUEST_SEND_ALERT)) { + PE_CLR_DPM_REQUEST(port, DPM_REQUEST_SEND_ALERT); + set_state_pe(port, PE_SEND_ALERT); + return true; + } else if (IS_ENABLED(CONFIG_USBC_VCONN) && PE_CHK_DPM_REQUEST(port, DPM_REQUEST_VCONN_SWAP)) { PE_CLR_DPM_REQUEST(port, DPM_REQUEST_VCONN_SWAP); set_state_pe(port, PE_VCS_SEND_SWAP); @@ -3276,6 +3283,39 @@ static void pe_give_battery_status_run(int port) set_state_pe(port, PE_SRC_READY); } } + +/** + * PE_SRC_Send_Source_Alert and + * PE_SNK_Send_Sink_Alert + */ +static void pe_send_alert_entry(int port) +{ + uint32_t *msg = (uint32_t *)tx_emsg[port].buf; + uint32_t *len = &tx_emsg[port].len; + + print_current_state(port); + + if (pd_build_alert_msg(msg, len, pe[port].power_role) != EC_SUCCESS) { + if (pe[port].power_role == PD_ROLE_SOURCE) + set_state_pe(port, PE_SRC_READY); + else + set_state_pe(port, PE_SNK_READY); + } + + /* Request the Protocol Layer to send Alert Message. */ + send_data_msg(port, TCPC_TX_SOP, PD_DATA_ALERT); +} + +static void pe_send_alert_run(int port) +{ + if (PE_CHK_FLAG(port, PE_FLAGS_TX_COMPLETE)) { + PE_CLR_FLAG(port, PE_FLAGS_TX_COMPLETE); + if (pe[port].power_role == PD_ROLE_SOURCE) + set_state_pe(port, PE_SRC_READY); + else + set_state_pe(port, PE_SNK_READY); + } +} #endif /* CONFIG_USB_PD_REV30 */ /** @@ -5579,6 +5619,10 @@ static const struct usb_state pe_states[] = { .entry = pe_give_battery_status_entry, .run = pe_give_battery_status_run, }, + [PE_SEND_ALERT] = { + .entry = pe_send_alert_entry, + .run = pe_send_alert_run, + }, #endif /* CONFIG_USB_PD_REV30 */ [PE_DRS_EVALUATE_SWAP] = { .entry = pe_drs_evaluate_swap_entry, diff --git a/include/usb_common.h b/include/usb_common.h index 078f4b0029..180ebbcc95 100644 --- a/include/usb_common.h +++ b/include/usb_common.h @@ -179,4 +179,14 @@ int pd_get_saved_port_flags(int port, uint8_t *flags); * @param do_set value written to the BB Ram flag */ void pd_update_saved_port_flags(int port, uint8_t flag, uint8_t do_set); + +/** + * Build PD alert message + * + * @param msg pointer where message is stored + * @param len pointer where length of message is stored in bytes + * @param pr current PD power role + * @return EC_SUCCESS on success else EC_ERROR_INVAL + */ +int pd_build_alert_msg(uint32_t *msg, uint32_t *len, enum pd_power_role pr); #endif /* __CROS_EC_USB_COMMON_H */ diff --git a/include/usb_pd.h b/include/usb_pd.h index 90d8a1392a..09468911bf 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -1096,6 +1096,16 @@ enum pd_ext_msg_type { /* 15-31 Reserved */ }; +/* Alert Data Object fields for REV 3.0 */ +#define ADO_OVP_EVENT BIT(30) +#define ADO_SOURCE_INPUT_CHANGE BIT(29) +#define ADO_OPERATING_CONDITION_CHANGE BIT(28) +#define ADO_OTP_EVENT BIT(27) +#define ADO_OCP_EVENT BIT(26) +#define ADO_BATTERY_STATUS_CHANGE BIT(25) +#define ADO_FIXED_BATTERIES(n) ((n & 0xf) << 20) +#define ADO_HOT_SWAPPABLE_BATTERIES(n) ((n & 0xf) << 16) + /* Data message type */ enum pd_data_msg_type { /* 0 Reserved */ diff --git a/include/usb_pe_sm.h b/include/usb_pe_sm.h index e69eff572f..8089fddb55 100644 --- a/include/usb_pe_sm.h +++ b/include/usb_pe_sm.h @@ -42,6 +42,7 @@ enum pe_dpm_request { DPM_REQUEST_HARD_RESET_SEND = BIT(15), DPM_REQUEST_SOFT_RESET_SEND = BIT(16), DPM_REQUEST_PORT_DISCOVERY = BIT(17), + DPM_REQUEST_SEND_ALERT = BIT(18), }; /** |