From b47a5ca84dfd6b75a4cd76837d81cac0345c000f Mon Sep 17 00:00:00 2001 From: Vijay Hiremath Date: Tue, 3 Sep 2019 11:54:39 -0700 Subject: intelrvp: Enable USB-C SRC current limiting Enable SRC current limit pin of the type C current-limited power switch to provide more current when sourcing on only 1 port. BUG=b:140404596 BRANCH=none TEST=Manually tested on tglrvp a. 1 port is connected: ILIM pin of respective port's current limited power switch is high and able to source 3A. b. 2 ports are connected: ILIM pin of both port's current limited power switch is low and able to source 1.5A on each port. Change-Id: Ic6ce897e25a25b526c3c52bce8cbdc843ad419f9 Signed-off-by: Vijay Hiremath Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1783517 Reviewed-by: Keith Short --- baseboard/intelrvp/baseboard.h | 3 +++ baseboard/intelrvp/chg_usb_pd.c | 41 +++++++++++++++++++++++++++++--------- baseboard/intelrvp/usb_pd_policy.c | 24 ++++++++++++++++++---- 3 files changed, 55 insertions(+), 13 deletions(-) (limited to 'baseboard') diff --git a/baseboard/intelrvp/baseboard.h b/baseboard/intelrvp/baseboard.h index 751b684906..2180e36a37 100644 --- a/baseboard/intelrvp/baseboard.h +++ b/baseboard/intelrvp/baseboard.h @@ -219,6 +219,8 @@ struct tcpc_gpio_config_t { /* Enable VCONN */ struct vconn_gpio_t vconn; #endif + /* Enable source ILIM */ + struct tcpc_gpio_t src_ilim; }; extern const struct tcpc_gpio_config_t tcpc_gpios[]; @@ -228,6 +230,7 @@ void vbus0_evt(enum gpio_signal signal); void vbus1_evt(enum gpio_signal signal); void board_charging_enable(int port, int enable); void board_vbus_enable(int port, int enable); +void board_set_vbus_source_current_limit(int port, int rp); int ioexpander_read_intelrvp_version(int *port0, int *port1); void board_dc_jack_interrupt(enum gpio_signal signal); diff --git a/baseboard/intelrvp/chg_usb_pd.c b/baseboard/intelrvp/chg_usb_pd.c index ac3cdd78f3..59fcbaf41b 100644 --- a/baseboard/intelrvp/chg_usb_pd.c +++ b/baseboard/intelrvp/chg_usb_pd.c @@ -15,17 +15,40 @@ #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -static int board_charger_port_is_sourcing_vbus(int port) +static inline int is_typec_port(int port) { - int src_en; + return !(port == DEDICATED_CHARGE_PORT || port == CHARGE_PORT_NONE); +} + + +int board_vbus_source_enabled(int port) +{ + int src_en = 0; - /* DC Jack can't source VBUS */ - if (port == DEDICATED_CHARGE_PORT || port == CHARGE_PORT_NONE) - return 0; + /* Only Type-C ports can source VBUS */ + if (is_typec_port(port)) { + src_en = gpio_get_level(tcpc_gpios[port].src.pin); - src_en = gpio_get_level(tcpc_gpios[port].src.pin); + src_en = tcpc_gpios[port].src.pin_pol ? src_en : !src_en; + } - return tcpc_gpios[port].src.pin_pol ? src_en : !src_en; + return src_en; +} + +void board_set_vbus_source_current_limit(int port, int rp) +{ + int ilim_en; + + /* Only Type-C ports can source VBUS */ + if (is_typec_port(port)) { + /* Enable SRC ILIM if rp is MAX single source current */ + ilim_en = (rp == CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT && + board_vbus_source_enabled(port)); + + gpio_set_level(tcpc_gpios[port].src_ilim.pin, + tcpc_gpios[port].src_ilim.pin_pol ? + ilim_en : !ilim_en); + } } void board_charging_enable(int port, int enable) @@ -129,7 +152,7 @@ int board_set_active_charge_port(int port) int is_real_port = (port >= 0 && port < CHARGE_PORT_COUNT); /* check if we are source vbus on that port */ - int source = board_charger_port_is_sourcing_vbus(port); + int source = board_vbus_source_enabled(port); if (is_real_port && source) { CPRINTS("Skip enable p%d", port); @@ -155,7 +178,7 @@ int board_set_active_charge_port(int port) } /* Enable charging port */ - if (port != DEDICATED_CHARGE_PORT && port != CHARGE_PORT_NONE) + if (is_typec_port(port)) board_charging_enable(port, 1); CPRINTS("New chg p%d", port); diff --git a/baseboard/intelrvp/usb_pd_policy.c b/baseboard/intelrvp/usb_pd_policy.c index e0255ebc6b..c291b75647 100644 --- a/baseboard/intelrvp/usb_pd_policy.c +++ b/baseboard/intelrvp/usb_pd_policy.c @@ -3,6 +3,7 @@ * found in the LICENSE file. */ +#include "charge_manager.h" #include "console.h" #include "gpio.h" #include "system.h" @@ -50,6 +51,9 @@ int pd_set_power_supply_ready(int port) /* Provide VBUS */ board_vbus_enable(port, 1); + /* Ensure we advertise the proper available current quota */ + charge_manager_source_port(port, 1); + /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -61,6 +65,9 @@ void pd_power_supply_reset(int port) /* Disable VBUS */ board_vbus_enable(port, 0); + /* Give back the current quota we are no longer using */ + charge_manager_source_port(port, 0); + /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); } @@ -83,12 +90,13 @@ int pd_check_power_swap(int port) int pd_check_data_swap(int port, int data_role) { /* Allow data swap if we are a UFP, otherwise don't allow */ - return (data_role == PD_ROLE_UFP); + return data_role == PD_ROLE_UFP; } int pd_check_vconn_swap(int port) { - return 1; + /* Only allow vconn swap if PP5000 rail is enabled */ + return gpio_get_level(GPIO_EN_PP5000); } void pd_execute_data_swap(int port, int data_role) @@ -98,6 +106,8 @@ void pd_execute_data_swap(int port, int data_role) void pd_check_pr_role(int port, int pr_role, int flags) { + int partner_extpower; + /* * If partner is dual-role power and dualrole toggling is on, consider * if a power swap is necessary. @@ -109,7 +119,7 @@ void pd_check_pr_role(int port, int pr_role, int flags) * swap to become a source. If we are source and partner is * externally powered, swap to become a sink. */ - int partner_extpower = flags & PD_FLAGS_PARTNER_EXTPOWER; + partner_extpower = flags & PD_FLAGS_PARTNER_EXTPOWER; if ((!partner_extpower && pr_role == PD_ROLE_SINK) || (partner_extpower && pr_role == PD_ROLE_SOURCE)) @@ -120,10 +130,16 @@ void pd_check_pr_role(int port, int pr_role, int flags) void pd_check_dr_role(int port, int dr_role, int flags) { /* If UFP, try to switch to DFP */ - if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP) + if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP && + system_get_image_copy() != SYSTEM_IMAGE_RO) pd_request_data_swap(port); } +void typec_set_source_current_limit(int port, int rp) +{ + board_set_vbus_source_current_limit(port, rp); +} + /* ----------------- Vendor Defined Messages ------------------ */ const struct svdm_response svdm_rsp = { .identity = NULL, -- cgit v1.2.1