From 79ae73477c1d6a84ce9c64eb82a183a163aa3646 Mon Sep 17 00:00:00 2001 From: Aseda Aboagye Date: Thu, 10 Aug 2017 13:12:30 -0700 Subject: charge_manager: Consider port in source PDO. When CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT is defined for a board, as its name implies, the board can source a higher current if there is only one port acting as a source. This commit fixes an issue with selecting the right source capability message to advertise. charge_manager_get_source_pdo() was simply checking if there was more than one sink connected, instead of checking if there were any *other* sinks connected. In the event that a sink was connected to a different port, we would advertise the max source PDO. BUG=b:64037926, b:35577509 BRANCH=gru,eve,reef TEST=Connect sink to port 1. Connect a AMA to port 0 that claims that VBUS isn't necessary. Start sending source caps, verify that the max PDO is not being advertised in the source caps. Change-Id: Ie4145ecaf98d5b9070ad3e8b139e5653685fa801 Signed-off-by: Aseda Aboagye Reviewed-on: https://chromium-review.googlesource.com/610479 Commit-Ready: Aseda Aboagye Tested-by: Aseda Aboagye Reviewed-by: Shawn N --- board/plankton/usb_pd_policy.c | 2 +- board/servo_v4/usb_pd_policy.c | 2 +- common/charge_manager.c | 24 ++++++++++++------------ common/usb_pd_policy.c | 4 ++-- common/usb_pd_protocol.c | 4 ++-- include/charge_manager.h | 5 +++-- include/usb_pd.h | 3 ++- util/genvif.c | 2 +- 8 files changed, 24 insertions(+), 22 deletions(-) diff --git a/board/plankton/usb_pd_policy.c b/board/plankton/usb_pd_policy.c index 6db20d33cb..42dd5180f8 100644 --- a/board/plankton/usb_pd_policy.c +++ b/board/plankton/usb_pd_policy.c @@ -55,7 +55,7 @@ void board_set_source_cap(enum board_src_cap cap) pd_src_pdo_idx = cap; } -int charge_manager_get_source_pdo(const uint32_t **src_pdo) +int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) { *src_pdo = pd_src_pdo; return pd_src_pdo_cnts[pd_src_pdo_idx]; diff --git a/board/servo_v4/usb_pd_policy.c b/board/servo_v4/usb_pd_policy.c index 019b35f763..011994a2c9 100644 --- a/board/servo_v4/usb_pd_policy.c +++ b/board/servo_v4/usb_pd_policy.c @@ -352,7 +352,7 @@ int board_select_rp_value(int port, int rp) return pd_set_rp_rd(port, TYPEC_CC_RP, rp); } -int charge_manager_get_source_pdo(const uint32_t **src_pdo) +int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) { int pdo_cnt; /* diff --git a/common/charge_manager.c b/common/charge_manager.c index 7b119da347..9d9226cb19 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -963,20 +963,20 @@ void charge_manager_source_port(int port, int enable) } } -int charge_manager_get_source_pdo(const uint32_t **src_pdo) +int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port) { - int p; - int count = 0; - - /* count the number of connected sinks */ - for (p = 0; p < CONFIG_USB_PD_PORT_COUNT; p++) - if (source_port_bitmap & (1 << p)) - count++; - - /* send the maximum current if we are sourcing only on one port */ - *src_pdo = count <= 1 ? pd_src_pdo_max : pd_src_pdo; + /* Are there any other connected sinks? */ + if (source_port_bitmap & ~(1 << port)) { + *src_pdo = pd_src_pdo; + return pd_src_pdo_cnt; + } - return count <= 1 ? pd_src_pdo_cnt : pd_src_pdo_max_cnt; + /* + * If not, send the maximum current since we're sourcing on only one + * port. + */ + *src_pdo = pd_src_pdo_max; + return pd_src_pdo_max_cnt; } #endif /* CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT */ diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c index 62f9ecbfa5..cf58e7ff07 100644 --- a/common/usb_pd_policy.c +++ b/common/usb_pd_policy.c @@ -33,7 +33,7 @@ static int rw_flash_changed = 1; -int pd_check_requested_voltage(uint32_t rdo) +int pd_check_requested_voltage(uint32_t rdo, const int port) { int max_ma = rdo & 0x3FF; int op_ma = (rdo >> 10) & 0x3FF; @@ -43,7 +43,7 @@ int pd_check_requested_voltage(uint32_t rdo) #if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) const uint32_t *src_pdo; - const int pdo_cnt = charge_manager_get_source_pdo(&src_pdo); + const int pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); #else const uint32_t *src_pdo = pd_src_pdo; const int pdo_cnt = pd_src_pdo_cnt; diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 2f701e6bfc..0526aaaf65 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -441,7 +441,7 @@ static int send_source_cap(int port) #if defined(CONFIG_USB_PD_DYNAMIC_SRC_CAP) || \ defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) const uint32_t *src_pdo; - const int src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo); + const int src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, port); #else const uint32_t *src_pdo = pd_src_pdo; const int src_pdo_cnt = pd_src_pdo_cnt; @@ -801,7 +801,7 @@ static void handle_data_request(int port, uint16_t head, #endif /* CONFIG_USB_PD_DUAL_ROLE */ case PD_DATA_REQUEST: if ((pd[port].power_role == PD_ROLE_SOURCE) && (cnt == 1)) - if (!pd_check_requested_voltage(payload[0])) { + if (!pd_check_requested_voltage(payload[0], port)) { if (send_control(port, PD_CTRL_ACCEPT) < 0) /* * if we fail to send accept, do diff --git a/include/charge_manager.h b/include/charge_manager.h index 2137899a13..037723047c 100644 --- a/include/charge_manager.h +++ b/include/charge_manager.h @@ -161,10 +161,11 @@ void charge_manager_source_port(int port, int enable); /** * Get PD source power data objects. * - * @param src_pdo pointer to the data to return. + * @param src_pdo Pointer to the data to return. + * @param port Current port to evaluate against. * @return number of PDOs returned. */ -int charge_manager_get_source_pdo(const uint32_t **src_pdo); +int charge_manager_get_source_pdo(const uint32_t **src_pdo, const int port); /* Board-level callback functions */ diff --git a/include/usb_pd.h b/include/usb_pd.h index cefe8abe06..9deed54b88 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -942,9 +942,10 @@ int pd_is_valid_input_voltage(int mv); * Request a new operating voltage. * * @param rdo Request Data Object with the selected operating point. + * @param port The port which the request came in on. * @return EC_SUCCESS if we can get the requested voltage/OP, <0 else. */ -int pd_check_requested_voltage(uint32_t rdo); +int pd_check_requested_voltage(uint32_t rdo, const int port); /** * Run board specific checks on request message diff --git a/util/genvif.c b/util/genvif.c index 6b3d685b37..865ae550df 100644 --- a/util/genvif.c +++ b/util/genvif.c @@ -48,7 +48,7 @@ enum system_image_copy_t system_get_image_copy(void) static void init_src_pdos(void) { #ifdef CONFIG_USB_PD_DYNAMIC_SRC_CAP - src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo); + src_pdo_cnt = charge_manager_get_source_pdo(&src_pdo, 0); #else src_pdo_cnt = pd_src_pdo_cnt; src_pdo = pd_src_pdo; -- cgit v1.2.1