diff --git a/board/fruitpie/usb_pd_policy.c b/board/fruitpie/usb_pd_policy.c index 06a8a44ba7..1d8cc7523e 100644 --- a/board/fruitpie/usb_pd_policy.c +++ b/board/fruitpie/usb_pd_policy.c @@ -18,16 +18,17 @@ #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL), - PDO_FIXED(5000, 3000, 0), - PDO_FIXED(12000, 3000, 0), - PDO_FIXED(20000, 2000, 0), + PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), + PDO_FIXED(5000, 3000, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), + PDO_FIXED(12000, 3000, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), + PDO_FIXED(20000, 3000, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); const uint32_t pd_snk_pdo[] = { - PDO_BATT(4500, 5500, 15000), - PDO_BATT(11500, 12500, 36000), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_BATT(5000, 20000, 15000), + PDO_VAR(5000, 20000, 3000), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/host/usb_pd_policy.c b/board/host/usb_pd_policy.c index c1630aff0d..5c39558b41 100644 --- a/board/host/usb_pd_policy.c +++ b/board/host/usb_pd_policy.c @@ -18,8 +18,9 @@ const uint32_t pd_src_pdo[] = { const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); const uint32_t pd_snk_pdo[] = { - PDO_BATT(4500, 5500, 15000), - PDO_BATT(11500, 12500, 36000), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_BATT(5000, 20000, 15000), + PDO_VAR(5000, 20000, 3000), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/plankton/usb_pd_policy.c b/board/plankton/usb_pd_policy.c index f213fce9ca..c4367a094d 100644 --- a/board/plankton/usb_pd_policy.c +++ b/board/plankton/usb_pd_policy.c @@ -23,10 +23,10 @@ /* Source PDOs */ const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL), - PDO_FIXED(5000, 3000, PDO_FIXED_EXTERNAL), - PDO_FIXED(12000, 3000, PDO_FIXED_EXTERNAL), - PDO_FIXED(20000, 3000, PDO_FIXED_EXTERNAL), + PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), + PDO_FIXED(5000, 3000, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), + PDO_FIXED(12000, 3000, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), + PDO_FIXED(20000, 3000, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), }; static const int pd_src_pdo_cnts[3] = { [SRC_CAP_5V] = 2, @@ -38,9 +38,9 @@ static int pd_src_pdo_idx; /* Fake PDOs : we just want our pre-defined voltages */ const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, 0), - PDO_FIXED(12000, 500, 0), - PDO_FIXED(20000, 500, 0), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_FIXED(12000, 500, PDO_FIXED_DUAL_ROLE), + PDO_FIXED(20000, 500, PDO_FIXED_DUAL_ROLE), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/ryu/usb_pd_policy.c b/board/ryu/usb_pd_policy.c index 561e6666ab..d092d521f4 100644 --- a/board/ryu/usb_pd_policy.c +++ b/board/ryu/usb_pd_policy.c @@ -18,17 +18,16 @@ #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -/* TODO(crosbug.com/p/28869): update source and sink tables to spec. */ const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL), - PDO_FIXED(5000, 900, 0), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_FIXED(5000, 900, PDO_FIXED_DUAL_ROLE), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); -/* TODO(crosbug.com/p/28869): update source and sink tables to spec. */ const uint32_t pd_snk_pdo[] = { - PDO_BATT(4500, 5500, 15000), - PDO_BATT(11500, 12500, 36000), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_BATT(5000, 20000, 10000), + PDO_VAR(5000, 20000, 3000), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/ryu_p2/usb_pd_policy.c b/board/ryu_p2/usb_pd_policy.c index 73688b218d..550b20d77a 100644 --- a/board/ryu_p2/usb_pd_policy.c +++ b/board/ryu_p2/usb_pd_policy.c @@ -18,17 +18,16 @@ #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -/* TODO(crosbug.com/p/28869): update source and sink tables to spec. */ const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL), - PDO_FIXED(5000, 900, 0), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_FIXED(5000, 900, PDO_FIXED_DUAL_ROLE), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); -/* TODO(crosbug.com/p/28869): update source and sink tables to spec. */ const uint32_t pd_snk_pdo[] = { - PDO_BATT(4500, 5500, 15000), - PDO_BATT(11500, 12500, 36000), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_BATT(5000, 20000, 10000), + PDO_VAR(5000, 20000, 3000), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c index c25c05e9fc..cecf5a7987 100644 --- a/board/samus_pd/usb_pd_policy.c +++ b/board/samus_pd/usb_pd_policy.c @@ -19,17 +19,16 @@ #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -/* TODO(crossbug.com/p/28869): update source and sink tables to spec. */ const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL), - PDO_FIXED(5000, 900, 0), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_FIXED(5000, 900, PDO_FIXED_DUAL_ROLE), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); -/* TODO(crossbug.com/p/28869): update source and sink tables to spec. */ const uint32_t pd_snk_pdo[] = { - PDO_BATT(4500, 5500, 15000), - PDO_BATT(11500, 12500, 36000), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_BATT(5000, 20000, 15000), + PDO_VAR(5000, 20000, 3000), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/twinkie/usb_pd_policy.c b/board/twinkie/usb_pd_policy.c index d71770e4ec..1179318efd 100644 --- a/board/twinkie/usb_pd_policy.c +++ b/board/twinkie/usb_pd_policy.c @@ -18,16 +18,17 @@ #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL), - PDO_FIXED(5000, 3000, 0), - PDO_FIXED(12000, 3000, 0), - PDO_FIXED(20000, 2000, 0), + PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), + PDO_FIXED(5000, 3000, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), + PDO_FIXED(12000, 3000, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), + PDO_FIXED(20000, 3000, PDO_FIXED_EXTERNAL|PDO_FIXED_DUAL_ROLE), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); const uint32_t pd_snk_pdo[] = { - PDO_BATT(4500, 5500, 15000), - PDO_BATT(11500, 12500, 36000), + PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE), + PDO_BATT(5000, 20000, 15000), + PDO_VAR(5000, 20000, 3000), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c index 103450e24a..96713e1d18 100644 --- a/board/zinger/usb_pd_policy.c +++ b/board/zinger/usb_pd_policy.c @@ -149,9 +149,9 @@ static void discharge_voltage(int target_volt) /* Power Delivery Objects */ const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL), - PDO_FIXED(5000, RATED_CURRENT, 0), - PDO_FIXED(12000, RATED_CURRENT, 0), - PDO_FIXED(20000, RATED_CURRENT, 0), + PDO_FIXED(5000, RATED_CURRENT, PDO_FIXED_EXTERNAL), + PDO_FIXED(12000, RATED_CURRENT, PDO_FIXED_EXTERNAL), + PDO_FIXED(20000, RATED_CURRENT, PDO_FIXED_EXTERNAL), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); diff --git a/common/charge_manager.c b/common/charge_manager.c index 3bea74747f..c884c05500 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -201,8 +201,8 @@ static int hc_pd_power_info(struct host_cmd_handler_args *args) else r->role = USB_PD_PORT_POWER_DISCONNECTED; - /* TODO: fill in appropriate dual-role status */ - r->dualrole = 0; + /* Is port partner dual-role capable */ + r->dualrole = pd_get_partner_dualrole_capable(port); if (sup == CHARGE_SUPPLIER_NONE) { r->type = USB_CHG_TYPE_NONE; diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index c44e070043..804c50787b 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -235,6 +235,8 @@ static struct pd_protocol { uint64_t src_recover; /* Flag for sending pings in SRC_READY */ uint8_t ping_enabled; + /* Port partner is a dual-role power device */ + uint8_t drp_partner; #ifdef CONFIG_USB_PD_DUAL_ROLE /* Current limit / voltage based on the last request message */ @@ -305,6 +307,7 @@ static inline void set_state(int port, enum pd_states next_state) if (next_state == PD_STATE_SRC_DISCONNECTED) { pd[port].dev_id = 0; + pd[port].drp_partner = 0; #ifdef CONFIG_USB_PD_ALT_MODE_DFP pd_exit_mode(port, NULL); #else @@ -317,6 +320,11 @@ static inline void set_state(int port, enum pd_states next_state) pd_set_vconn(port, pd[port].polarity, 0); #endif } +#ifdef CONFIG_USB_PD_DUAL_ROLE + else if (next_state == PD_STATE_SNK_DISCONNECTED) { + pd[port].drp_partner = 0; + } +#endif #ifdef CONFIG_LOW_POWER_IDLE /* If any PD port is connected, then disable deep sleep */ @@ -730,6 +738,10 @@ static void pd_send_request_msg(int port) if (res == EC_SUCCESS) { pd[port].curr_limit = curr_limit; pd[port].supply_voltage = supply_voltage; + /* src cap 0 should be fixed PDO, get dualrole power capable */ + if ((pd_src_caps[port][0] & PDO_TYPE_MASK) == PDO_TYPE_FIXED) + pd[port].drp_partner = (pd_src_caps[port][0] & + PDO_FIXED_DUAL_ROLE) ? 1 : 0; res = send_request(port, rdo); if (res >= 0) set_state(port, PD_STATE_SNK_REQUESTED); @@ -783,6 +795,10 @@ static void handle_data_request(int port, uint16_t head, break; case PD_DATA_SINK_CAP: + /* snk cap 0 should be fixed PDO, get dualrole power capable */ + if ((payload[0] & PDO_TYPE_MASK) == PDO_TYPE_FIXED) + pd[port].drp_partner = + (payload[0] & PDO_FIXED_DUAL_ROLE) ? 1 : 0; break; case PD_DATA_VENDOR_DEF: handle_vdm_request(port, cnt, payload); @@ -1170,6 +1186,12 @@ int pd_get_polarity(int port) return pd[port].polarity; } +int pd_get_partner_dualrole_capable(int port) +{ + /* return dualrole status of port partner */ + return pd[port].drp_partner; +} + void pd_comm_enable(int enable) { pd_comm_enabled = enable; @@ -1236,7 +1258,7 @@ void pd_task(void) #endif /* CONFIG_USB_PD_DUAL_ROLE */ enum pd_states this_state; timestamp_t now; - int caps_count = 0; + int caps_count = 0, src_ready_vdms_sent = 0; /* Initialize TX pins and put them in Hi-Z */ pd_tx_init(); @@ -1383,6 +1405,7 @@ void pd_task(void) res = send_control(port, PD_CTRL_PS_RDY); if (res >= 0) { timeout = PD_T_SEND_SOURCE_CAP; + src_ready_vdms_sent = 0; /* it'a time to ping regularly the sink */ set_state(port, PD_STATE_SRC_READY); } else { @@ -1392,7 +1415,15 @@ void pd_task(void) } break; case PD_STATE_SRC_READY: + timeout = PD_T_SOURCE_ACTIVITY; if (pd[port].last_state != pd[port].task_state) { + /* Get sink cap to know if dual-role device */ + send_control(port, PD_CTRL_GET_SINK_CAP); + break; + } + + /* Send VDMs once after get sink cap */ + if (!src_ready_vdms_sent) { #ifdef CONFIG_USB_PD_SIMPLE_DFP /* * For simple devices that don't support @@ -1408,20 +1439,17 @@ void pd_task(void) pd_send_vdm(port, USB_SID_PD, CMD_DISCOVER_IDENT, NULL, 0); #endif - } - - if (!pd[port].ping_enabled) { - timeout = PD_T_SOURCE_ACTIVITY; + src_ready_vdms_sent = 1; break; } + if (!pd[port].ping_enabled) + break; + /* Verify that the sink is alive */ res = send_control(port, PD_CTRL_PING); - if (res >= 0) { - /* schedule next keep-alive */ - timeout = PD_T_SOURCE_ACTIVITY; + if (res >= 0) break; - } /* Ping dropped. Try soft reset. */ set_state(port, PD_STATE_SOFT_RESET); @@ -1955,10 +1983,11 @@ static int command_pd(int argc, char **argv) "SOFT_RESET", "HARD_RESET", "BIST", }; BUILD_ASSERT(ARRAY_SIZE(state_names) == PD_STATE_COUNT); - ccprintf("Port C%d, %s - Role: %s Polarity: CC%d State: %s\n", + ccprintf("Port C%d, %s - Role: %s Polarity: CC%d DRP: %d, " + "State: %s\n", port, pd_comm_enabled ? "Enabled" : "Disabled", pd[port].role == PD_ROLE_SOURCE ? "SRC" : "SNK", - pd[port].polarity + 1, + pd[port].polarity + 1, pd[port].drp_partner, state_names[pd[port].task_state]); } else { return EC_ERROR_PARAM1; diff --git a/include/usb_pd.h b/include/usb_pd.h index 1eede4fd89..7b00486b5f 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -43,6 +43,7 @@ enum pd_errors { #define PDO_FIXED_SUSPEND (1 << 28) /* USB Suspend supported */ #define PDO_FIXED_EXTERNAL (1 << 27) /* Externally powered */ #define PDO_FIXED_COMM_CAP (1 << 26) /* USB Communications Capable */ +#define PDO_FIXED_DATA_SWAP (1 << 25) /* Data role swap command supported */ #define PDO_FIXED_PEAK_CURR () /* [21..20] Peak current */ #define PDO_FIXED_VOLT(mv) (((mv)/50) << 10) /* Voltage in 50mV units */ #define PDO_FIXED_CURR(ma) (((ma)/10) << 0) /* Max current in 10mA units */ @@ -971,6 +972,13 @@ int pd_is_connected(int port); */ int pd_get_polarity(int port); +/** + * Get port partner dual-role capable status + * + * @param port USB-C port number + */ +int pd_get_partner_dualrole_capable(int port); + /** * Set the PD communication enabled flag. When communication is disabled, * the port can still detect connection and source power but will not