diff options
-rw-r--r-- | common/usb_pd_alt_mode_dfp.c | 74 | ||||
-rw-r--r-- | common/usb_pd_policy.c | 70 | ||||
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 78 | ||||
-rw-r--r-- | include/usb_pd.h | 8 |
4 files changed, 82 insertions, 148 deletions
diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c index abf2ef4125..a5371f8c78 100644 --- a/common/usb_pd_alt_mode_dfp.c +++ b/common/usb_pd_alt_mode_dfp.c @@ -65,6 +65,27 @@ static int pd_allocate_mode(int port, uint16_t svid) return -1; } +static int validate_mode_request(struct svdm_amode_data *modep, + uint16_t svid, int opos) +{ + if (!modep->fx) + return 0; + + if (svid != modep->fx->svid) { + CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n", + svid, modep->fx->svid); + return 0; + } + + if (opos != modep->opos) { + CPRINTF("ERR:opos r:%d != c:%d\n", + opos, modep->opos); + return 0; + } + + return 1; +} + /* * This algorithm defaults to choosing higher pin config over lower ones in * order to prefer multi-function if desired. @@ -159,3 +180,56 @@ uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos) /* SVDM to send to UFP for mode entry */ return VDO(modep->fx->svid, 1, CMD_ENTER_MODE | VDO_OPOS(modep->opos)); } + +int pd_dfp_exit_mode(int port, uint16_t svid, int opos) +{ + struct svdm_amode_data *modep; + struct pd_policy *pe = pd_get_am_policy(port); + int idx; + + /* + * Empty svid signals we should reset DFP VDM state by exiting all + * entered modes then clearing state. This occurs when we've + * disconnected or for hard reset. + */ + if (!svid) { + for (idx = 0; idx < PD_AMODE_COUNT; idx++) + if (pe->amodes[idx].fx) + pe->amodes[idx].fx->exit(port); + + pd_dfp_pe_init(port); + return 0; + } + + /* + * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple + * mode exit. Additionally it should honor OPOS == 7 as DFP's request + * to exit all modes. We currently don't have any UFPs that support + * multiple modes on one SVID. + */ + modep = pd_get_amode_data(port, svid); + if (!modep || !validate_mode_request(modep, svid, opos)) + return 0; + + /* call DFPs exit function */ + modep->fx->exit(port); + + pd_set_dfp_enter_mode_flag(port, false); + + /* exit the mode */ + modep->opos = 0; + return 1; +} + +void dfp_consume_attention(int port, uint32_t *payload) +{ + uint16_t svid = PD_VDO_VID(payload[0]); + int opos = PD_VDO_OPOS(payload[0]); + struct svdm_amode_data *modep = pd_get_amode_data(port, svid); + + if (!modep || !validate_mode_request(modep, svid, opos)) + return; + + if (modep->fx->attention) + modep->fx->attention(port, payload); +} diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c index 968c02d1b7..10264e1f0e 100644 --- a/common/usb_pd_policy.c +++ b/common/usb_pd_policy.c @@ -845,76 +845,6 @@ static int enter_tbt_compat_mode(int port, uint32_t *payload) return 2; } -static int validate_mode_request(struct svdm_amode_data *modep, - uint16_t svid, int opos) -{ - if (!modep->fx) - return 0; - - if (svid != modep->fx->svid) { - CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n", - svid, modep->fx->svid); - return 0; - } - - if (opos != modep->opos) { - CPRINTF("ERR:opos r:%d != c:%d\n", - opos, modep->opos); - return 0; - } - - return 1; -} - -static void dfp_consume_attention(int port, uint32_t *payload) -{ - uint16_t svid = PD_VDO_VID(payload[0]); - int opos = PD_VDO_OPOS(payload[0]); - struct svdm_amode_data *modep = pd_get_amode_data(port, svid); - - if (!modep || !validate_mode_request(modep, svid, opos)) - return; - - if (modep->fx->attention) - modep->fx->attention(port, payload); -} - -int pd_dfp_exit_mode(int port, uint16_t svid, int opos) -{ - struct svdm_amode_data *modep; - int idx; - - /* - * Empty svid signals we should reset DFP VDM state by exiting all - * entered modes then clearing state. This occurs when we've - * disconnected or for hard reset. - */ - if (!svid) { - for (idx = 0; idx < PD_AMODE_COUNT; idx++) - if (pe[port].amodes[idx].fx) - pe[port].amodes[idx].fx->exit(port); - - pd_dfp_pe_init(port); - return 0; - } - - /* - * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple - * mode exit. Additionally it should honor OPOS == 7 as DFP's request - * to exit all modes. We currently don't have any UFPs that support - * multiple modes on one SVID. - */ - modep = pd_get_amode_data(port, svid); - if (!modep || !validate_mode_request(modep, svid, opos)) - return 0; - - /* call DFPs exit function */ - modep->fx->exit(port); - /* exit the mode */ - modep->opos = 0; - return 1; -} - uint16_t pd_get_identity_vid(int port) { return PD_IDH_VID(pe[port].identity[0]); diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index 2b101b8e29..1b5783a9d6 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -490,9 +490,6 @@ static unsigned int max_request_mv = PD_MAX_VOLTAGE_MV; * Private VDM utility functions */ #ifdef CONFIG_USB_PD_ALT_MODE_DFP -static int validate_mode_request(struct svdm_amode_data *modep, - uint16_t svid, int opos); -static void dfp_consume_attention(int port, uint32_t *payload); static void dfp_consume_identity(int port, int cnt, uint32_t *payload); static void dfp_consume_svids(int port, int cnt, uint32_t *payload); static int dfp_discover_modes(int port, uint32_t *payload); @@ -4728,81 +4725,6 @@ void pd_set_dfp_enter_mode_flag(int port, bool set) PE_CLR_FLAG(port, PE_FLAGS_MODAL_OPERATION); } -static int validate_mode_request(struct svdm_amode_data *modep, - uint16_t svid, int opos) -{ - if (!modep->fx) - return 0; - - if (svid != modep->fx->svid) { - CPRINTF("ERR:svid r:0x%04x != c:0x%04x\n", - svid, modep->fx->svid); - return 0; - } - - if (opos != modep->opos) { - CPRINTF("ERR:opos r:%d != c:%d\n", - opos, modep->opos); - return 0; - } - - return 1; -} - -static void dfp_consume_attention(int port, uint32_t *payload) -{ - uint16_t svid = PD_VDO_VID(payload[0]); - int opos = PD_VDO_OPOS(payload[0]); - struct svdm_amode_data *modep = pd_get_amode_data(port, svid); - - if (!modep || !validate_mode_request(modep, svid, opos)) - return; - - if (modep->fx->attention) - modep->fx->attention(port, payload); -} - -int pd_dfp_exit_mode(int port, uint16_t svid, int opos) -{ - struct svdm_amode_data *modep; - int idx; - - - /* - * Empty svid signals we should reset DFP VDM state by exiting all - * entered modes then clearing state. This occurs when we've - * disconnected or for hard reset. - */ - if (!svid) { - for (idx = 0; idx < PD_AMODE_COUNT; idx++) - if (pe[port].am_policy.amodes[idx].fx) - pe[port].am_policy.amodes[idx].fx->exit(port); - - pd_dfp_pe_init(port); - return 0; - } - - /* - * TODO(crosbug.com/p/33946) : below needs revisited to allow multiple - * mode exit. Additionally it should honor OPOS == 7 as DFP's request - * to exit all modes. We currently don't have any UFPs that support - * multiple modes on one SVID. - */ - modep = pd_get_amode_data(port, svid); - if (!modep || !validate_mode_request(modep, svid, opos)) - return 0; - - /* call DFPs exit function */ - modep->fx->exit(port); - - PE_CLR_FLAG(port, PE_FLAGS_MODAL_OPERATION); - - /* exit the mode */ - modep->opos = 0; - - return 1; -} - uint16_t pd_get_identity_vid(int port) { return PD_IDH_VID(pe[port].am_policy.identity[0]); diff --git a/include/usb_pd.h b/include/usb_pd.h index ebb5343abe..7b2e228b31 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -1629,6 +1629,14 @@ int pd_dfp_dp_get_pin_mode(int port, uint32_t status); int pd_dfp_exit_mode(int port, uint16_t svid, int opos); /** + * Consume the SVDM attention data + * + * @param port USB-C port number + * @param payload payload data. + */ +void dfp_consume_attention(int port, uint32_t *payload); + +/** * Initialize policy engine for DFP * * @param port USB-C port number |