summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbe Levkoy <alevkoy@chromium.org>2020-06-03 11:06:53 -0600
committerCommit Bot <commit-bot@chromium.org>2020-06-11 19:44:59 +0000
commitb9203fa3b2b032c3aa7b2e3ccfb01dce7eea8f22 (patch)
tree7969549ba4fdc71e0d4427765543330f8f40df11
parent7b2203f0e45e6dc653aec4bc4c5cd4b72e844b9f (diff)
downloadchrome-ec-b9203fa3b2b032c3aa7b2e3ccfb01dce7eea8f22.tar.gz
TCPMv2: Support mode entry for SOP' and SOP''
Add a transmit type parameter to functions involved in mode entry; also add such a parameter to various functions calling those functions. For DisplayPort-specific definitions or calls, specify SOP; we do not currently support DisplayPort mode for cable plugs. For TCPMv1-specific code, specify SOP. TCPMv1 generally assumes that the discovery/mode structures are 1-dimensional, as they were previously, and changing that is outside the scope of this CL. BUG=b:155890173 TEST=Enter DP mode on Volteer with TCPMv2 TEST=Enter DP mode on Volteer with TCPMv1 TEST=Enter TBT mode on Volteer with TCPMV1 BRANCH=none Change-Id: I8afc75b3f3be8939c4645058ac4a31f24c88fb9e Signed-off-by: Abe Levkoy <alevkoy@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2229279 Reviewed-by: Diana Z <dzigterman@chromium.org> Commit-Queue: Diana Z <dzigterman@chromium.org>
-rw-r--r--baseboard/grunt/usb_pd_policy.c2
-rw-r--r--baseboard/kukui/usb_pd_policy.c2
-rw-r--r--baseboard/trogdor/usb_pd_policy.c2
-rw-r--r--baseboard/zork/usb_pd_policy.c2
-rw-r--r--board/chell/usb_pd_policy.c4
-rw-r--r--board/coffeecake/usb_pd_policy.c5
-rw-r--r--board/dingdong/usb_pd_policy.c5
-rw-r--r--board/hoho/usb_pd_policy.c5
-rw-r--r--board/pdeval-stm32f072/usb_pd_policy.c2
-rw-r--r--board/plankton/usb_pd_policy.c2
-rw-r--r--board/servo_v4/board.c4
-rw-r--r--board/servo_v4/usb_pd_policy.c4
-rw-r--r--common/usb_common.c2
-rw-r--r--common/usb_pd_alt_mode_dfp.c94
-rw-r--r--common/usb_pd_console_cmd.c3
-rw-r--r--common/usb_pd_host_cmd.c8
-rw-r--r--common/usb_pd_policy.c18
-rw-r--r--common/usb_pd_protocol.c21
-rw-r--r--common/usbc/dp_alt_mode.c10
-rw-r--r--common/usbc/usb_pd_dpm.c2
-rw-r--r--common/usbc/usb_pe_drp_sm.c72
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c38
-rw-r--r--include/usb_pd.h46
23 files changed, 228 insertions, 125 deletions
diff --git a/baseboard/grunt/usb_pd_policy.c b/baseboard/grunt/usb_pd_policy.c
index 0d2e41b64a..4b28081785 100644
--- a/baseboard/grunt/usb_pd_policy.c
+++ b/baseboard/grunt/usb_pd_policy.c
@@ -96,7 +96,7 @@ mux_state_t svdm_dp_mux_mode(int port)
__override int svdm_dp_config(int port, uint32_t *payload)
{
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]);
int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]);
mux_state_t mux_mode = svdm_dp_mux_mode(port);
diff --git a/baseboard/kukui/usb_pd_policy.c b/baseboard/kukui/usb_pd_policy.c
index feca48a8e7..1b28975fa1 100644
--- a/baseboard/kukui/usb_pd_policy.c
+++ b/baseboard/kukui/usb_pd_policy.c
@@ -158,7 +158,7 @@ __override int svdm_enter_dp_mode(int port, uint32_t mode_caps)
__override int svdm_dp_config(int port, uint32_t *payload)
{
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
int status = dp_status[port];
int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]);
int pin_mode;
diff --git a/baseboard/trogdor/usb_pd_policy.c b/baseboard/trogdor/usb_pd_policy.c
index 40cfd91319..dc4733d20d 100644
--- a/baseboard/trogdor/usb_pd_policy.c
+++ b/baseboard/trogdor/usb_pd_policy.c
@@ -96,7 +96,7 @@ int pd_snk_is_vbus_provided(int port)
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
__override int svdm_dp_config(int port, uint32_t *payload)
{
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
uint8_t pin_mode = get_dp_pin_mode(port);
if (!pin_mode)
diff --git a/baseboard/zork/usb_pd_policy.c b/baseboard/zork/usb_pd_policy.c
index 4650682ed8..e83172880b 100644
--- a/baseboard/zork/usb_pd_policy.c
+++ b/baseboard/zork/usb_pd_policy.c
@@ -105,7 +105,7 @@ mux_state_t svdm_dp_mux_mode(int port)
__override int svdm_dp_config(int port, uint32_t *payload)
{
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]);
int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]);
mux_state_t mux_mode = svdm_dp_mux_mode(port);
diff --git a/board/chell/usb_pd_policy.c b/board/chell/usb_pd_policy.c
index 478f656de2..2123c45d86 100644
--- a/board/chell/usb_pd_policy.c
+++ b/board/chell/usb_pd_policy.c
@@ -228,7 +228,7 @@ static int svdm_enter_dp_mode(int port, uint32_t mode_caps)
static int svdm_dp_status(int port, uint32_t *payload)
{
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
CMD_DP_STATUS | VDO_OPOS(opos));
@@ -245,7 +245,7 @@ static int svdm_dp_status(int port, uint32_t *payload)
static int svdm_dp_config(int port, uint32_t *payload)
{
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]);
int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]);
diff --git a/board/coffeecake/usb_pd_policy.c b/board/coffeecake/usb_pd_policy.c
index 99a0faec83..6da20a5b37 100644
--- a/board/coffeecake/usb_pd_policy.c
+++ b/board/coffeecake/usb_pd_policy.c
@@ -266,8 +266,11 @@ static int svdm_enter_mode(int port, uint32_t *payload)
return rv;
}
-int pd_alt_mode(int port, uint16_t svid)
+int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid)
{
+ if (type != TCPC_TX_SOP)
+ return 0;
+
if (svid == USB_SID_DISPLAYPORT)
return alt_mode[PD_AMODE_DISPLAYPORT];
else if (svid == USB_VID_GOOGLE)
diff --git a/board/dingdong/usb_pd_policy.c b/board/dingdong/usb_pd_policy.c
index a4bfec541d..f17802c82a 100644
--- a/board/dingdong/usb_pd_policy.c
+++ b/board/dingdong/usb_pd_policy.c
@@ -219,8 +219,11 @@ static int svdm_enter_mode(int port, uint32_t *payload)
return rv;
}
-int pd_alt_mode(int port, uint16_t svid)
+int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid)
{
+ if (type != TCPC_TX_SOP)
+ return 0;
+
if (svid == USB_SID_DISPLAYPORT)
return alt_mode[PD_AMODE_DISPLAYPORT];
else if (svid == USB_VID_GOOGLE)
diff --git a/board/hoho/usb_pd_policy.c b/board/hoho/usb_pd_policy.c
index 9bc8d3aa2f..4fe82320e8 100644
--- a/board/hoho/usb_pd_policy.c
+++ b/board/hoho/usb_pd_policy.c
@@ -194,8 +194,11 @@ static int svdm_enter_mode(int port, uint32_t *payload)
return rv;
}
-int pd_alt_mode(int port, uint16_t svid)
+int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid)
{
+ if (type != TCPC_TX_SOP)
+ return 0;
+
if (svid == USB_SID_DISPLAYPORT)
return alt_mode[PD_AMODE_DISPLAYPORT];
else if (svid == USB_VID_GOOGLE)
diff --git a/board/pdeval-stm32f072/usb_pd_policy.c b/board/pdeval-stm32f072/usb_pd_policy.c
index 775f8b8876..78026c9e7b 100644
--- a/board/pdeval-stm32f072/usb_pd_policy.c
+++ b/board/pdeval-stm32f072/usb_pd_policy.c
@@ -199,7 +199,7 @@ __override void svdm_safe_dp_mode(int port)
__override int svdm_dp_config(int port, uint32_t *payload)
{
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]);
#if defined(CONFIG_USB_PD_TCPM_MUX) && defined(CONFIG_USB_PD_TCPM_ANX7447)
const struct usb_mux *mux = &usb_muxes[port];
diff --git a/board/plankton/usb_pd_policy.c b/board/plankton/usb_pd_policy.c
index 87718648f1..f6701ab65e 100644
--- a/board/plankton/usb_pd_policy.c
+++ b/board/plankton/usb_pd_policy.c
@@ -236,7 +236,7 @@ int svdm_enter_mode(int port, uint32_t *payload)
return 1;
}
-int pd_alt_mode(int port, uint16_t svid)
+int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid)
{
return alt_mode;
}
diff --git a/board/servo_v4/board.c b/board/servo_v4/board.c
index 559b9bb5b0..fc6735e19c 100644
--- a/board/servo_v4/board.c
+++ b/board/servo_v4/board.c
@@ -78,7 +78,7 @@ static volatile int hpd_prev_level;
void hpd_irq_deferred(void)
{
- int dp_mode = pd_alt_mode(1, USB_SID_DISPLAYPORT);
+ int dp_mode = pd_alt_mode(1, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
if (dp_mode) {
pd_send_hpd(DUT, hpd_irq);
@@ -90,7 +90,7 @@ DECLARE_DEFERRED(hpd_irq_deferred);
void hpd_lvl_deferred(void)
{
int level = gpio_get_level(GPIO_DP_HPD);
- int dp_mode = pd_alt_mode(1, USB_SID_DISPLAYPORT);
+ int dp_mode = pd_alt_mode(1, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
if (level != hpd_prev_level) {
/* It's a glitch while in deferred or canceled action */
diff --git a/board/servo_v4/usb_pd_policy.c b/board/servo_v4/usb_pd_policy.c
index a8a6b8ee1f..b87130fbc8 100644
--- a/board/servo_v4/usb_pd_policy.c
+++ b/board/servo_v4/usb_pd_policy.c
@@ -950,9 +950,9 @@ static int svdm_enter_mode(int port, uint32_t *payload)
return 1;
}
-int pd_alt_mode(int port, uint16_t svid)
+int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid)
{
- if (svid == USB_SID_DISPLAYPORT)
+ if (type == TCPC_TX_SOP && svid == USB_SID_DISPLAYPORT)
return alt_mode;
return 0;
diff --git a/common/usb_common.c b/common/usb_common.c
index 156dc816cb..974e136a7b 100644
--- a/common/usb_common.c
+++ b/common/usb_common.c
@@ -645,7 +645,7 @@ static void pd_usb_billboard_deferred(void)
* 1. Will we have multiple type-C port UFPs
* 2. Will there be other modes applicable to DFPs besides DP
*/
- if (!pd_alt_mode(0, USB_SID_DISPLAYPORT))
+ if (!pd_alt_mode(0, TCPC_TX_SOP, USB_SID_DISPLAYPORT))
usb_connect();
}
}
diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c
index a5d7120669..421ae72024 100644
--- a/common/usb_pd_alt_mode_dfp.c
+++ b/common/usb_pd_alt_mode_dfp.c
@@ -50,33 +50,37 @@ __overridable const struct svdm_response svdm_rsp = {
.modes = NULL,
};
-static int pd_get_mode_idx(int port, uint16_t svid)
+static int pd_get_mode_idx(int port, enum tcpm_transmit_type type,
+ uint16_t svid)
{
- int i;
- /* TODO(b/150611251): Support SOP' */
- struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP);
+ int amode_idx;
+ struct partner_active_modes *active =
+ pd_get_partner_active_modes(port, type);
- for (i = 0; i < PD_AMODE_COUNT; i++) {
- if (disc->amodes[i].fx &&
- (disc->amodes[i].fx->svid == svid))
- return i;
+ for (amode_idx = 0; amode_idx < PD_AMODE_COUNT; amode_idx++) {
+ if (active->amodes[amode_idx].fx &&
+ (active->amodes[amode_idx].fx->svid == svid))
+ return amode_idx;
}
return -1;
}
-static int pd_allocate_mode(int port, uint16_t svid)
+static int pd_allocate_mode(int port, enum tcpm_transmit_type type,
+ uint16_t svid)
{
int i, j;
struct svdm_amode_data *modep;
- int mode_idx = pd_get_mode_idx(port, svid);
- /* TODO(b/150611251): Support SOP' and SOP'' */
- struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP);
+ int mode_idx = pd_get_mode_idx(port, type, svid);
+ struct pd_discovery *disc = pd_get_am_discovery(port, type);
+ struct partner_active_modes *active =
+ pd_get_partner_active_modes(port, type);
+ assert(active);
if (mode_idx != -1)
return mode_idx;
/* There's no space to enter another mode */
- if (disc->amode_idx == PD_AMODE_COUNT) {
+ if (active->amode_idx == PD_AMODE_COUNT) {
CPRINTF("ERR:NO AMODE SPACE\n");
return -1;
}
@@ -91,16 +95,18 @@ static int pd_allocate_mode(int port, uint16_t svid)
* discovered SVIDs; must also match the passed-in SVID
* if that was non-zero. Otherwise, go to the next
* discovered SVID.
+ * TODO(b/155890173): Support AP-directed mode entry
+ * where the mode is unknown to the TCPM.
*/
if ((svidp->svid != supported_modes[i].svid) ||
(svid && (svidp->svid != svid)))
continue;
- modep = &disc->amodes[disc->amode_idx];
+ modep = &active->amodes[active->amode_idx];
modep->fx = &supported_modes[i];
modep->data = &disc->svids[j];
- disc->amode_idx++;
- return disc->amode_idx - 1;
+ active->amode_idx++;
+ return active->amode_idx - 1;
}
}
return -1;
@@ -169,7 +175,7 @@ void pd_prepare_sysjump(void)
int pd_dfp_dp_get_pin_mode(int port, uint32_t status)
{
struct svdm_amode_data *modep =
- pd_get_amode_data(port, USB_SID_DISPLAYPORT);
+ pd_get_amode_data(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
uint32_t mode_caps;
uint32_t pin_caps;
@@ -199,30 +205,31 @@ int pd_dfp_dp_get_pin_mode(int port, uint32_t status)
return 1 << get_next_bit(&pin_caps);
}
-struct svdm_amode_data *pd_get_amode_data(int port, uint16_t svid)
+struct svdm_amode_data *pd_get_amode_data(int port,
+ enum tcpm_transmit_type type, uint16_t svid)
{
- int idx = pd_get_mode_idx(port, svid);
- /* TODO(b/150611251): Support SOP' */
- struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP);
+ int idx = pd_get_mode_idx(port, type, svid);
+ struct partner_active_modes *active =
+ pd_get_partner_active_modes(port, type);
+ assert(active);
- return (idx == -1) ? NULL : &disc->amodes[idx];
+ return (idx == -1) ? NULL : &active->amodes[idx];
}
/*
* Enter default mode ( payload[0] == 0 ) or attempt to enter mode via svid &
* opos
*/
-uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos)
+uint32_t pd_dfp_enter_mode(int port, enum tcpm_transmit_type type,
+ uint16_t svid, int opos)
{
- int mode_idx = pd_allocate_mode(port, svid);
- /* TODO(b/150611251): Support SOP' */
- struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP);
+ int mode_idx = pd_allocate_mode(port, type, svid);
struct svdm_amode_data *modep;
uint32_t mode_caps;
if (mode_idx == -1)
return 0;
- modep = &disc->amodes[mode_idx];
+ modep = &pd_get_partner_active_modes(port, type)->amodes[mode_idx];
if (!opos) {
/* choose the lowest as default */
@@ -230,7 +237,7 @@ uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos)
} else if (opos <= modep->data->mode_cnt) {
modep->opos = opos;
} else {
- CPRINTF("opos error\n");
+ CPRINTS("C%d: Invalid opos %d for SVID %x", port, opos, svid);
return 0;
}
@@ -244,11 +251,12 @@ uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos)
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)
+int pd_dfp_exit_mode(int port, enum tcpm_transmit_type type, uint16_t svid,
+ int opos)
{
struct svdm_amode_data *modep;
- /* TODO(b/150611251): Support SOP' */
- struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP);
+ struct partner_active_modes *active =
+ pd_get_partner_active_modes(port, type);
int idx;
/*
@@ -258,8 +266,8 @@ int pd_dfp_exit_mode(int port, uint16_t svid, int opos)
*/
if (!svid) {
for (idx = 0; idx < PD_AMODE_COUNT; idx++)
- if (disc->amodes[idx].fx)
- disc->amodes[idx].fx->exit(port);
+ if (active->amodes[idx].fx)
+ active->amodes[idx].fx->exit(port);
pd_dfp_discovery_init(port);
return 0;
@@ -271,7 +279,7 @@ int pd_dfp_exit_mode(int port, uint16_t svid, int opos)
* 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);
+ modep = pd_get_amode_data(port, type, svid);
if (!modep || !validate_mode_request(modep, svid, opos))
return 0;
@@ -289,7 +297,8 @@ 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);
+ struct svdm_amode_data *modep =
+ pd_get_amode_data(port, TCPC_TX_SOP, svid);
if (!modep || !validate_mode_request(modep, svid, opos))
return;
@@ -434,9 +443,9 @@ int dfp_discover_modes(int port, uint32_t *payload)
return 1;
}
-int pd_alt_mode(int port, uint16_t svid)
+int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid)
{
- struct svdm_amode_data *modep = pd_get_amode_data(port, svid);
+ struct svdm_amode_data *modep = pd_get_amode_data(port, type, svid);
return (modep) ? modep->opos : -1;
}
@@ -846,7 +855,12 @@ int enter_tbt_compat_mode(int port, enum tcpm_transmit_type sop,
struct pd_cable *cable = pd_get_cable_attributes(port);
/* Table F-12 TBT3 Cable Enter Mode Command */
- payload[0] = pd_dfp_enter_mode(port, USB_VID_INTEL, 0) |
+ /*
+ * Although TCPMv2 contemplates separate mode storage for each SOP
+ * type, TCPMv1 stores everything in the array for SOP.
+ */
+ /* TODO(b/148528713): Make this function generic to TCPM version. */
+ payload[0] = pd_dfp_enter_mode(port, TCPC_TX_SOP, USB_VID_INTEL, 0) |
VDO_SVDM_VERS(VDM_VER20);
/* For TBT3 Cable Enter Mode Command, number of Objects is 1 */
@@ -1061,7 +1075,7 @@ __overridable int svdm_enter_dp_mode(int port, uint32_t mode_caps)
__overridable int svdm_dp_status(int port, uint32_t *payload)
{
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
CMD_DP_STATUS | VDO_OPOS(opos));
@@ -1083,7 +1097,7 @@ __overridable uint8_t get_dp_pin_mode(int port)
__overridable int svdm_dp_config(int port, uint32_t *payload)
{
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]);
uint8_t pin_mode = get_dp_pin_mode(port);
mux_state_t mux_mode;
diff --git a/common/usb_pd_console_cmd.c b/common/usb_pd_console_cmd.c
index 22039eddc3..3fc6a6f35f 100644
--- a/common/usb_pd_console_cmd.c
+++ b/common/usb_pd_console_cmd.c
@@ -64,7 +64,8 @@ static void dump_pe(int port)
disc->svids[i].mode_vdo[j]);
ccprintf("\n");
- modep = pd_get_amode_data(port, disc->svids[i].svid);
+ modep = pd_get_amode_data(port, TCPC_TX_SOP,
+ disc->svids[i].svid);
if (modep) {
mode_caps = modep->data->mode_vdo[modep->opos - 1];
ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos,
diff --git a/common/usb_pd_host_cmd.c b/common/usb_pd_host_cmd.c
index 8bd9f16aea..6e8afe761e 100644
--- a/common/usb_pd_host_cmd.c
+++ b/common/usb_pd_host_cmd.c
@@ -125,7 +125,7 @@ static enum ec_status hc_remote_pd_set_amode(struct host_cmd_handler_args *args)
switch (p->cmd) {
case PD_EXIT_MODE:
- if (pd_dfp_exit_mode(p->port, p->svid, p->opos))
+ if (pd_dfp_exit_mode(p->port, TCPC_TX_SOP, p->svid, p->opos))
pd_send_vdm(p->port, p->svid,
CMD_EXIT_MODE | VDO_OPOS(p->opos), NULL, 0);
else {
@@ -134,7 +134,7 @@ static enum ec_status hc_remote_pd_set_amode(struct host_cmd_handler_args *args)
}
break;
case PD_ENTER_MODE:
- if (pd_dfp_enter_mode(p->port, p->svid, p->opos))
+ if (pd_dfp_enter_mode(p->port, TCPC_TX_SOP, p->svid, p->opos))
pd_send_vdm(p->port, p->svid, CMD_ENTER_MODE |
VDO_OPOS(p->opos), NULL, 0);
break;
@@ -190,10 +190,10 @@ static enum ec_status hc_remote_pd_get_amode(struct host_cmd_handler_args *args)
r->opos = 0;
memcpy(r->vdo, pd_get_mode_vdo(p->port, p->svid_idx, TCPC_TX_SOP),
sizeof(uint32_t) * PDO_MODES);
- modep = pd_get_amode_data(p->port, r->svid);
+ modep = pd_get_amode_data(p->port, TCPC_TX_SOP, r->svid);
if (modep)
- r->opos = pd_alt_mode(p->port, r->svid);
+ r->opos = pd_alt_mode(p->port, TCPC_TX_SOP, r->svid);
args->response_size = sizeof(*r);
return EC_RES_SUCCESS;
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
index 0d468b0ce8..b10b9cb8c7 100644
--- a/common/usb_pd_policy.c
+++ b/common/usb_pd_policy.c
@@ -206,6 +206,7 @@ void disable_enter_usb4_mode(int port)
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
static struct pd_discovery discovery[CONFIG_USB_PD_PORT_MAX_COUNT];
+static struct partner_active_modes partner_amodes[CONFIG_USB_PD_PORT_MAX_COUNT];
static bool is_tbt_compat_enabled(int port)
{
@@ -331,6 +332,7 @@ static bool is_cable_ready_to_enter_usb4(int port, int cnt)
void pd_dfp_discovery_init(int port)
{
memset(&discovery[port], 0, sizeof(struct pd_discovery));
+ memset(&partner_amodes[port], 0, sizeof(partner_amodes[0]));
}
static int dfp_discover_ident(uint32_t *payload)
@@ -354,6 +356,13 @@ struct pd_discovery *pd_get_am_discovery(int port, enum tcpm_transmit_type type)
return &discovery[port];
}
+struct partner_active_modes *pd_get_partner_active_modes(int port,
+ enum tcpm_transmit_type type)
+{
+ assert(type < AMODE_TYPE_COUNT);
+ return &partner_amodes[port];
+}
+
/* Note: Enter mode flag is not needed by TCPMv1 */
void pd_set_dfp_enter_mode_flag(int port, bool set)
{
@@ -656,7 +665,8 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
struct svdm_amode_data *modep;
- modep = pd_get_amode_data(port, PD_VDO_VID(payload[0]));
+ modep = pd_get_amode_data(port, TCPC_TX_SOP,
+ PD_VDO_VID(payload[0]));
#endif
switch (cmd) {
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
@@ -705,7 +715,8 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
* SVID.
*/
disable_tbt_compat_mode(port);
- payload[0] = pd_dfp_enter_mode(port, 0, 0);
+ payload[0] = pd_dfp_enter_mode(port,
+ TCPC_TX_SOP, 0, 0);
if (payload[0])
rsize = 1;
}
@@ -722,7 +733,8 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
rsize = 0;
} else {
if (!modep->opos)
- pd_dfp_enter_mode(port, 0, 0);
+ pd_dfp_enter_mode(port, TCPC_TX_SOP, 0,
+ 0);
if (modep->opos) {
rsize = modep->fx->status(port,
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 442432890e..b8cd5d7340 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -791,7 +791,7 @@ static inline void set_state(int port, enum pd_states next_state)
charge_manager_update_dualrole(port, CAP_UNKNOWN);
#endif
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- pd_dfp_exit_mode(port, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0);
#endif
/*
* Indicate that the port is disconnected by setting role to
@@ -1325,7 +1325,7 @@ void pd_execute_hard_reset(int port)
pd[port].msg_id = 0;
invalidate_last_message_id(port);
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
- pd_dfp_exit_mode(port, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0);
#endif
#ifdef CONFIG_USB_PD_REV30
@@ -2131,12 +2131,17 @@ static void exit_tbt_mode_sop_prime(int port)
if (!IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))
return;
- opos = pd_alt_mode(port, USB_VID_INTEL);
+ opos = pd_alt_mode(port, TCPC_TX_SOP, USB_VID_INTEL);
if (opos <= 0)
return;
CPRINTS("C%d Cable exiting TBT Compat mode", port);
- if (!pd_dfp_exit_mode(port, USB_VID_INTEL, opos))
+ /*
+ * Note: TCPMv2 contemplates separate discovery structures for each SOP
+ * type. TCPMv1 only uses one discovery structure, so all accesses
+ * specify TCPC_TX_SOP.
+ */
+ if (!pd_dfp_exit_mode(port, TCPC_TX_SOP, USB_VID_INTEL, opos))
return;
header = PD_HEADER(PD_DATA_VENDOR_DEF, pd[port].power_role,
@@ -2333,10 +2338,12 @@ __maybe_unused static void exit_supported_alt_mode(int port)
return;
for (i = 0; i < supported_modes_cnt; i++) {
- int opos = pd_alt_mode(port, supported_modes[i].svid);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP,
+ supported_modes[i].svid);
if (opos > 0 &&
- pd_dfp_exit_mode(port, supported_modes[i].svid, opos)) {
+ pd_dfp_exit_mode(
+ port, TCPC_TX_SOP, supported_modes[i].svid, opos)) {
CPRINTS("C%d Exiting ALT mode with SVID = 0x%x", port,
supported_modes[i].svid);
pd_send_vdm(port, supported_modes[i].svid,
@@ -4969,7 +4976,7 @@ int pd_is_port_enabled(int port)
void pd_send_hpd(int port, enum hpd_event hpd)
{
uint32_t data[1];
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
if (!opos)
return;
diff --git a/common/usbc/dp_alt_mode.c b/common/usbc/dp_alt_mode.c
index ba0b35550b..ff8909bbd6 100644
--- a/common/usbc/dp_alt_mode.c
+++ b/common/usbc/dp_alt_mode.c
@@ -58,11 +58,12 @@ void dp_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count,
uint32_t *vdm)
{
const struct svdm_amode_data *modep =
- pd_get_amode_data(port, USB_SID_DISPLAYPORT);
+ pd_get_amode_data(port, type, USB_SID_DISPLAYPORT);
const uint8_t vdm_cmd = PD_VDO_CMD(vdm[0]);
if (type != TCPC_TX_SOP || next_vdm_cmd[port] != vdm_cmd) {
print_unexpected_response(port, type, CMDT_RSP_ACK, vdm_cmd);
+ dpm_set_mode_entry_done(port);
return;
}
@@ -105,8 +106,8 @@ void dp_reset_next_command(int port)
int dp_setup_next_vdm(int port, int vdo_count, uint32_t *vdm)
{
- const struct svdm_amode_data *modep =
- pd_get_amode_data(port, USB_SID_DISPLAYPORT);
+ const struct svdm_amode_data *modep = pd_get_amode_data(port,
+ TCPC_TX_SOP, USB_SID_DISPLAYPORT);
int vdo_count_ret;
if (vdo_count < VDO_MAX_SIZE)
@@ -115,7 +116,8 @@ int dp_setup_next_vdm(int port, int vdo_count, uint32_t *vdm)
switch (next_vdm_cmd[port]) {
case CMD_ENTER_MODE:
/* Enter the first supported mode for DisplayPort. */
- vdm[0] = pd_dfp_enter_mode(port, USB_SID_DISPLAYPORT, 0);
+ vdm[0] = pd_dfp_enter_mode(port, TCPC_TX_SOP,
+ USB_SID_DISPLAYPORT, 0);
if (vdm[0] == 0)
return -1;
/* CMDT_INIT is 0, so this is a no-op */
diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c
index 44ec46e588..adfb64d8fd 100644
--- a/common/usbc/usb_pd_dpm.c
+++ b/common/usbc/usb_pd_dpm.c
@@ -101,7 +101,7 @@ void dpm_attempt_mode_entry(int port)
* TODO(b/155890173): Provide a host command to request that the PE send
* an arbitrary VDM via this mechanism.
*/
- if (!pd_setup_vdm_request(port, vdm, vdo_count)) {
+ if (!pd_setup_vdm_request(port, TCPC_TX_SOP, vdm, vdo_count)) {
dpm_set_mode_entry_done(port);
return;
}
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index 0db15df6ee..7c6d8a9f98 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -466,6 +466,8 @@ static struct policy_engine {
int32_t vpd_vdo;
/* Alternate mode discovery results */
struct pd_discovery discovery[DISCOVERY_TYPE_COUNT];
+ /* Active alternate modes */
+ struct partner_active_modes partner_amodes[AMODE_TYPE_COUNT];
/* Alternate mode object position */
int8_t alt_opos;
@@ -1063,7 +1065,7 @@ void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
void pe_exit_dp_mode(int port)
{
if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
if (opos <= 0)
return;
@@ -1075,7 +1077,8 @@ void pe_exit_dp_mode(int port)
* the mode to be cleaned up before return.
*/
CPRINTS("C%d Exiting DP mode", port);
- if (!pd_dfp_exit_mode(port, USB_SID_DISPLAYPORT, opos))
+ if (!pd_dfp_exit_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT,
+ opos))
return;
/*
@@ -1439,13 +1442,13 @@ static bool pe_attempt_port_discovery(int port)
}
#endif
-bool pd_setup_vdm_request(int port, uint32_t *vdm, uint32_t vdo_cnt)
+bool pd_setup_vdm_request(int port, enum tcpm_transmit_type tx_type,
+ uint32_t *vdm, uint32_t vdo_cnt)
{
if (vdo_cnt < VDO_HDR_SIZE || vdo_cnt > VDO_MAX_SIZE)
return false;
- /* TODO(b/155890173): Support cable plug */
- pe[port].partner_type = PORT;
+ pe[port].tx_type = tx_type;
memcpy(pe[port].vdm_data, vdm, vdo_cnt * sizeof(*vdm));
pe[port].vdm_cnt = vdo_cnt;
@@ -4183,7 +4186,7 @@ static void pe_do_port_discovery_run(int port)
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
uint32_t *payload = (uint32_t *)rx_emsg[port].buf;
struct svdm_amode_data *modep =
- pd_get_amode_data(port, PD_VDO_VID(payload[0]));
+ pd_get_amode_data(port, TCPC_TX_SOP, PD_VDO_VID(payload[0]));
int ret = 0;
if (!PE_CHK_FLAG(port,
@@ -4205,7 +4208,8 @@ static void pe_do_port_discovery_run(int port)
break;
case CMD_DISCOVER_MODES:
pe[port].vdm_cmd = CMD_ENTER_MODE;
- pe[port].vdm_data[0] = pd_dfp_enter_mode(port, 0, 0);
+ pe[port].vdm_data[0] =
+ pd_dfp_enter_mode(port, TCPC_TX_SOP, 0, 0);
if (pe[port].vdm_data[0])
ret = 1;
break;
@@ -4860,6 +4864,12 @@ static void pe_vdm_request_entry(int port)
{
print_current_state(port);
+ if (pe[port].tx_type == TCPC_TX_INVALID) {
+ CPRINTS("C%d: TX type expected to be set, returning", port);
+ set_state_pe(port, get_last_state_pe(port));
+ return;
+ }
+
/* All VDM sequences are Interruptible */
PE_SET_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
@@ -4873,8 +4883,7 @@ static void pe_vdm_request_entry(int port)
tx_emsg[port].len = pe[port].vdm_cnt * 4;
}
- /* TODO(b/155890173): Support cable plug */
- send_data_msg(port, TCPC_TX_SOP, PD_DATA_VENDOR_DEF);
+ send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF);
pe[port].vdm_response_timer = TIMER_DISABLED;
}
@@ -4909,9 +4918,8 @@ static void pe_vdm_request_run(int port)
cnt = PD_HEADER_CNT(rx_emsg[port].header);
ext = PD_HEADER_EXT(rx_emsg[port].header);
- if ((sop == TCPC_TX_SOP || sop == TCPC_TX_SOP_PRIME) &&
- type == PD_DATA_VENDOR_DEF && cnt > 0 &&
- ext == 0) {
+ if (sop == pe[port].tx_type && type == PD_DATA_VENDOR_DEF &&
+ cnt > 0 && ext == 0) {
if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_ACK) {
set_state_pe(port, PE_VDM_ACKED);
return;
@@ -4925,7 +4933,7 @@ static void pe_vdm_request_run(int port)
PE_FLAGS_VDM_REQUEST_BUSY);
}
} else {
- if ((sop == TCPC_TX_SOP || sop == TCPC_TX_SOP_PRIME) &&
+ if (sop == pe[port].tx_type &&
type == PD_CTRL_NOT_SUPPORTED &&
cnt == 0 && ext == 0) {
/* Equivalent meaning to a NAK */
@@ -4962,7 +4970,8 @@ static void pe_vdm_request_run(int port)
PE_SET_FLAG(port, PE_FLAGS_VDM_REQUEST_BUSY);
} else if (get_time().val > pe[port].vdm_response_timer) {
CPRINTF("C%d: VDM %s Response Timeout\n", port,
- pe[port].partner_type ? "Cable" : "Port");
+ pe[port].tx_type == TCPC_TX_SOP
+ ? "Port" : "Cable");
PE_SET_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED);
}
@@ -4990,6 +4999,9 @@ static void pe_vdm_request_run(int port)
static void pe_vdm_request_exit(int port)
{
+ /* Invalidate TX type so that it must be set before next call */
+ pe[port].tx_type = TCPC_TX_INVALID;
+
PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS);
}
@@ -5012,24 +5024,18 @@ static void pe_vdm_acked_entry(int port)
payload = (uint32_t *)rx_emsg[port].buf;
svid = PD_VDO_VID(payload[0]);
vdo_cmd = PD_VDO_CMD(payload[0]);
- sop = PD_HEADER_GET_SOP(rx_emsg[port].header);
- /* TODO(b/155890173): Support cable plug */
- if (sop == TCPC_TX_SOP) {
- /*
- * Handle Message From Port Partner
- */
- /* vdo_count must have been >= 1 to get into this state. */
- dpm_vdm_acked(port, sop, vdo_count, payload);
+ /* vdo_count must have been >= 1 to get into this state. */
+ dpm_vdm_acked(port, sop, vdo_count, payload);
- /*
- * TODO(b/155890173): Respect distinction between discovery and
- * mode entry in flags.
- */
- if (svid == USB_SID_DISPLAYPORT && vdo_cmd == CMD_DP_CONFIG)
- PE_SET_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
- }
+ /*
+ * TODO(b/155890173): Respect distinction between discovery and mode
+ * entry in flags.
+ */
+ if (sop == TCPC_TX_SOP && svid == USB_SID_DISPLAYPORT &&
+ vdo_cmd == CMD_DP_CONFIG)
+ PE_SET_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE);
if (pe[port].power_role == PD_ROLE_SOURCE) {
set_state_pe(port, PE_SRC_READY);
@@ -5659,6 +5665,7 @@ uint8_t pd_get_src_cap_cnt(int port)
void pd_dfp_discovery_init(int port)
{
memset(&pe[port].discovery, 0, sizeof(pe[port].discovery));
+ memset(pe[port].partner_amodes, 0, sizeof(pe[port].partner_amodes));
/* Reset the DPM and DP modules to enable alternate mode entry. */
dpm_init(port);
@@ -5671,6 +5678,13 @@ struct pd_discovery *pd_get_am_discovery(int port, enum tcpm_transmit_type type)
return &pe[port].discovery[type];
}
+struct partner_active_modes *pd_get_partner_active_modes(int port,
+ enum tcpm_transmit_type type)
+{
+ assert(type < AMODE_TYPE_COUNT);
+ return &pe[port].partner_amodes[type];
+}
+
struct pd_cable *pd_get_cable_attributes(int port)
{
return &pe[port].cable;
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
index 8258f9666f..b39ea83ca6 100644
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
@@ -1475,7 +1475,7 @@ static void handle_new_power_state(int port)
void pd_send_hpd(int port, enum hpd_event hpd)
{
uint32_t data[1];
- int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT);
if (!opos)
return;
@@ -1907,7 +1907,9 @@ static void tc_attach_wait_snk_run(const int port)
get_time().val > tc[port].pd_debounce) {
if (IS_ENABLED(CONFIG_USB_PE_SM) &&
IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
- pd_dfp_exit_mode(port, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, 0, 0);
}
/* We are detached */
@@ -2054,8 +2056,12 @@ static void tc_attached_snk_run(const int port)
!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
/* Detach detection */
if (!pd_is_vbus_present(port)) {
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- pd_dfp_exit_mode(port, 0, 0);
+ if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
+ pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME,
+ 0, 0);
+ }
set_state_tc(port, TC_UNATTACHED_SNK);
return;
@@ -2444,8 +2450,12 @@ static void tc_dbg_acc_snk_run(const int port)
!TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
/* Detach detection */
if (!pd_is_vbus_present(port)) {
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- pd_dfp_exit_mode(port, 0, 0);
+ if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
+ pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME,
+ 0, 0);
+ }
set_state_tc(port, TC_UNATTACHED_SNK);
return;
@@ -2862,8 +2872,12 @@ static void tc_attached_src_run(const int port)
!TC_CHK_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS)) {
if (IS_ENABLED(CONFIG_USB_PE_SM))
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- pd_dfp_exit_mode(port, 0, 0);
+ if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
+ pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME,
+ 0, 0);
+ }
set_state_tc(port, IS_ENABLED(CONFIG_USB_PD_TRY_SRC) ?
TC_TRY_WAIT_SNK : TC_UNATTACHED_SNK);
@@ -3303,8 +3317,12 @@ static void tc_ct_unattached_snk_run(int port)
if (get_time().val > tc[port].cc_debounce) {
if (new_cc_state == PD_CC_NONE &&
pd_check_vbus_level(port, VBUS_SAFE0V)) {
- if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
- pd_dfp_exit_mode(port, 0, 0);
+ if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
+ pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0);
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME,
+ 0, 0);
+ }
set_state_tc(port, TC_UNATTACHED_SNK);
return;
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 4b63eed869..34fe964966 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -371,11 +371,13 @@ enum pd_alternate_modes {
PD_AMODE_COUNT,
};
-/* Discover all SOP* communications when enabled */
+/* Discover and possibly enter modes for all SOP* communications when enabled */
#ifdef CONFIG_USB_PD_DECODE_SOP
#define DISCOVERY_TYPE_COUNT (TCPC_TX_SOP_PRIME + 1)
+#define AMODE_TYPE_COUNT (TCPC_TX_SOP_PRIME_PRIME + 1)
#else
#define DISCOVERY_TYPE_COUNT (TCPC_TX_SOP + 1)
+#define AMODE_TYPE_COUNT (TCPC_TX_SOP + 1)
#endif
/* Discovery results for a port partner (SOP) or cable plug (SOP') */
@@ -384,20 +386,24 @@ struct pd_discovery {
union disc_ident_ack identity;
/* Supported SVIDs and corresponding mode VDOs */
struct svid_mode_data svids[SVID_DISCOVERY_MAX];
- /* active modes */
- struct svdm_amode_data amodes[PD_AMODE_COUNT];
/* index of SVID currently being operated on */
int svid_idx;
/* Count of SVIDs discovered */
int svid_cnt;
- /* Next index to insert DFP alternate mode into amodes */
- int amode_idx;
/* Identity discovery state */
enum pd_discovery_state identity_discovery;
/* SVID discovery state */
enum pd_discovery_state svids_discovery;
};
+/* Active modes for a partner (SOP, SOP', or SOP'') */
+struct partner_active_modes {
+ /* Active modes */
+ struct svdm_amode_data amodes[PD_AMODE_COUNT];
+ /* Next index to insert DFP alternate mode into amodes */
+ int amode_idx;
+};
+
/*
* VDO : Vendor Defined Message Object
* VDM object is minimum of VDM header + 6 additional data objects.
@@ -1594,11 +1600,13 @@ int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload);
* Enter alternate mode on DFP
*
* @param port USB-C port number
+ * @param type Transmit type (SOP, SOP') for which to enter mode
* @param svid USB standard or vendor id to exit or zero for DFP amode reset.
* @param opos object position of mode to exit.
* @return vdm for UFP to be sent to enter mode or zero if not.
*/
-uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos);
+uint32_t pd_dfp_enter_mode(int port, enum tcpm_transmit_type type,
+ uint16_t svid, int opos);
/**
* Get DisplayPort pin mode for DFP to request from UFP's capabilities.
@@ -1613,11 +1621,13 @@ int pd_dfp_dp_get_pin_mode(int port, uint32_t status);
* Exit alternate mode on DFP
*
* @param port USB-C port number
+ * @param type Transmit type (SOP, SOP') for which to exit mode
* @param svid USB standard or vendor id to exit or zero for DFP amode reset.
* @param opos object position of mode to exit.
* @return 1 if UFP should be sent exit mode VDM.
*/
-int pd_dfp_exit_mode(int port, uint16_t svid, int opos);
+int pd_dfp_exit_mode(int port, enum tcpm_transmit_type type, uint16_t svid,
+ int opos);
/**
* Consume the SVDM attention data
@@ -1833,10 +1843,12 @@ bool pd_is_mode_discovered_for_svid(int port, enum tcpm_transmit_type type,
* Return the alternate mode entry and exit data
*
* @param port USB-C port number
+ * @param type Transmit type (SOP, SOP', SOP'') for mode data
* @param svid SVID
* @return pointer to SVDM mode data
*/
-struct svdm_amode_data *pd_get_amode_data(int port, uint16_t svid);
+struct svdm_amode_data *pd_get_amode_data(int port,
+ enum tcpm_transmit_type type, uint16_t svid);
/**
* Returns false if previous SOP' messageId count is different from received
@@ -1874,6 +1886,17 @@ struct pd_discovery *pd_get_am_discovery(int port,
enum tcpm_transmit_type type);
/*
+ * Returns the pointer to PD active alternate modes.
+ * Note: Caller function can mutate the data in this structure.
+ *
+ * @param port USB-C port number
+ * @param type Transmit type (SOP, SOP', SOP'') for active modes
+ * @return Pointer to PD active alternate modes.
+ */
+struct partner_active_modes *pd_get_partner_active_modes(int port,
+ enum tcpm_transmit_type type);
+
+/*
* Return the pointer to PD cable attributes
* Note: Caller function can mutate the data in this structure.
*
@@ -2228,13 +2251,15 @@ void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
/* Prepares the PE to send an VDM.
*
* @param port USB-C port number
+ * @param type Transmit type (SOP, SOP', SOP'') for VDM
* @param vdm Buffer containing the message body to send, including the VDM
* Header but not the Message Header.
* @param vdo_cnt The number of 32-bit VDOs in vdm, including the VDM Header;
* must be 1 - 7 inclusive.
* @return True if the setup was successful
*/
-bool pd_setup_vdm_request(int port, uint32_t *vdm, uint32_t vdo_cnt);
+bool pd_setup_vdm_request(int port, enum tcpm_transmit_type tx_type,
+ uint32_t *vdm, uint32_t vdo_cnt);
/* Power Data Objects for the source and the sink */
__override_proto extern const uint32_t pd_src_pdo[];
@@ -2259,10 +2284,11 @@ static inline void pd_send_host_event(int mask) { }
* Determine if in alternate mode or not.
*
* @param port port number.
+ * @param type Transmit type (SOP, SOP', SOP'') for alt mode status
* @param svid USB standard or vendor id
* @return object position of mode chosen in alternate mode otherwise zero.
*/
-int pd_alt_mode(int port, uint16_t svid);
+int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid);
/**
* Send hpd over USB PD.