From e9584bc6cea8677979ffe2929e75f2ef037ec764 Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Fri, 28 Oct 2016 17:46:22 +0200 Subject: reef/pyro/eve/snappy: source 3A on one port Add a new source policy to provide 3A if there is only one port used as a source. Also ensure that the load switch on VBUS when sourcing power is properly configured to limit the current to 1.5A or 3.0A depending on the case. Signed-off-by: Vincent Palatin BRANCH=none BUG=chrome-os-partner:56110 TEST=manual: connect the laptop to a type-C sink with Twinkie in between, without anything else connected on the laptop, see 3A flowing when measuring with Twinkie ('tw vbus'), plug a dangling C-to-A receptacle dongle on the other port and see 1.5A flowing through Twinkie. Force the input current limit on the sink to 3.0A and see the laptop cutting VBUS. Change-Id: Ic94ba186fc0648e770c8d13be0f96b23e968f855 Reviewed-on: https://chromium-review.googlesource.com/403851 Commit-Ready: Vincent Palatin Tested-by: Vincent Palatin Reviewed-by: Shawn N --- board/eve/board.c | 3 +-- board/eve/board.h | 1 + board/eve/gpio.inc | 4 ++-- board/eve/usb_pd_policy.c | 53 +++++++++++++++++++++++++++++++++++++------- board/pyro/board.c | 3 +-- board/pyro/board.h | 1 + board/pyro/gpio.inc | 4 ++-- board/pyro/usb_pd_policy.c | 53 +++++++++++++++++++++++++++++++++++++------- board/reef/board.c | 3 +-- board/reef/board.h | 1 + board/reef/gpio.inc | 4 ++-- board/reef/usb_pd_policy.c | 53 +++++++++++++++++++++++++++++++++++++------- board/snappy/board.c | 3 +-- board/snappy/board.h | 1 + board/snappy/gpio.inc | 4 ++-- board/snappy/usb_pd_policy.c | 53 +++++++++++++++++++++++++++++++++++++------- 16 files changed, 196 insertions(+), 48 deletions(-) diff --git a/board/eve/board.c b/board/eve/board.c index d3edc9c072..7479b558e2 100644 --- a/board/eve/board.c +++ b/board/eve/board.c @@ -413,8 +413,7 @@ int board_set_active_charge_port(int charge_port) case 0: case 1: /* Don't charge from a source port */ - if (gpio_get_level(charge_port == 0 ? - GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN)) + if (board_vbus_source_enabled(charge_port)) return -1; bd9995x_port = bd9995x_pd_port_to_chg_port(charge_port); diff --git a/board/eve/board.h b/board/eve/board.h index 05a451c9a8..2212fecb85 100644 --- a/board/eve/board.h +++ b/board/eve/board.h @@ -122,6 +122,7 @@ #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_LOGGING #define CONFIG_USB_PD_LOG_SIZE 512 +#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_PORT_COUNT 2 #define CONFIG_USB_PD_QUIRK_SLOW_CC_STATUS #define CONFIG_USB_PD_VBUS_DETECT_CHARGER diff --git a/board/eve/gpio.inc b/board/eve/gpio.inc index 7d88a44998..172900781b 100644 --- a/board/eve/gpio.inc +++ b/board/eve/gpio.inc @@ -72,8 +72,8 @@ GPIO(TOUCHPAD_WAKE_L, PIN(7, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* INT# from Trac GPIO(DSP_WAKE_L, PIN(C, 6), GPIO_INPUT | GPIO_SEL_1P8V) /* INT# from DSP Mic */ /* 5V enables: INPUT=1.5A, OUT_LOW=OFF, OUT_HIGH=3A */ -GPIO(USB_C0_5V_EN, PIN(4, 2), GPIO_OUT_LOW) /* C0 5V Enable */ -GPIO(USB_C1_5V_EN, PIN(B, 1), GPIO_OUT_LOW) /* C1 5V Enable */ +GPIO(USB_C0_5V_EN, PIN(4, 2), GPIO_OUT_LOW | GPIO_PULL_UP) /* C0 5V Enable */ +GPIO(USB_C1_5V_EN, PIN(B, 1), GPIO_OUT_LOW | GPIO_PULL_UP) /* C1 5V Enable */ GPIO(USB_C0_CABLE_DET, PIN(D, 2), GPIO_INPUT) /* C0 Cable Detect */ GPIO(USB_C1_CABLE_DET, PIN(D, 3), GPIO_INPUT) /* C1 Cable Detect */ GPIO(USB_C0_PD_RST_L, PIN(0, 3), GPIO_OUT_LOW) /* C0 PD Reset */ diff --git a/board/eve/usb_pd_policy.c b/board/eve/usb_pd_policy.c index 3311f13b73..dbc510caf1 100644 --- a/board/eve/usb_pd_policy.c +++ b/board/eve/usb_pd_policy.c @@ -21,6 +21,7 @@ #include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_tcpm.h" #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) @@ -33,6 +34,10 @@ const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +const uint32_t pd_src_pdo_max[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max); const uint32_t pd_snk_pdo[] = { PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), @@ -51,9 +56,37 @@ void pd_transition_voltage(int idx) /* No-operation: we are always 5V */ } +static uint8_t vbus_en[CONFIG_USB_PD_PORT_COUNT]; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_COUNT] = {TYPEC_RP_1A5, TYPEC_RP_1A5}; + int board_vbus_source_enabled(int port) { - return gpio_get_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN); + return vbus_en[port]; +} + +static void board_vbus_update_source_current(int port) +{ + enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; + int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? + (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP); + + /* + * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance + * (2x 33k in parallel) on the NX5P3290 load switch ILIM pin, + * setting a minimum OCP current of 3186 mA. + * Putting an internal pull-up on USB_Cx_5V_EN, effectively put a 33k + * resistor on ILIM, setting a minimum OCP current of 1505 mA. + */ + gpio_set_level(gpio, vbus_en[port]); + gpio_set_flags(gpio, flags); +} + +void typec_set_source_current_limit(int port, int rp) +{ + vbus_rp[port] = rp; + + /* change the GPIO driving the load switch if needed */ + board_vbus_update_source_current(port); } int pd_set_power_supply_ready(int port) @@ -61,11 +94,13 @@ int pd_set_power_supply_ready(int port) /* Ensure we're not charging from this port */ bd9995x_select_input_port(bd9995x_pd_port_to_chg_port(port), 0); - /* Provide VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN, 1); + /* Ensure we advertise the proper available current quota */ + charge_manager_source_port(port, 1); pd_set_vbus_discharge(port, 0); + /* Provide VBUS */ + vbus_en[port] = 1; + board_vbus_update_source_current(port); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -75,19 +110,21 @@ int pd_set_power_supply_ready(int port) void pd_power_supply_reset(int port) { - enum gpio_signal gpio; int prev_en; - gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; - prev_en = gpio_get_level(gpio); + prev_en = vbus_en[port]; /* Disable VBUS */ - gpio_set_level(gpio, 0); + vbus_en[port] = 0; + board_vbus_update_source_current(port); /* Enable discharge if we were previously sourcing 5V */ if (prev_en) pd_set_vbus_discharge(port, 1); + /* 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); } diff --git a/board/pyro/board.c b/board/pyro/board.c index ebdb6d6198..7af0038af4 100644 --- a/board/pyro/board.c +++ b/board/pyro/board.c @@ -516,8 +516,7 @@ int board_set_active_charge_port(int charge_port) case 0: case 1: /* Don't charge from a source port */ - if (gpio_get_level(charge_port == 0 ? - GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN)) + if (board_vbus_source_enabled(charge_port)) return -1; bd9995x_port = bd9995x_pd_port_to_chg_port(charge_port); diff --git a/board/pyro/board.h b/board/pyro/board.h index 40533f0e05..e22ebb95a8 100644 --- a/board/pyro/board.h +++ b/board/pyro/board.h @@ -85,6 +85,7 @@ #define CONFIG_USB_PD_DISCHARGE_TCPC #define CONFIG_USB_PD_LOGGING #define CONFIG_USB_PD_LOG_SIZE 512 +#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_PORT_COUNT 2 #define CONFIG_USB_PD_QUIRK_SLOW_CC_STATUS #define CONFIG_USB_PD_VBUS_DETECT_CHARGER diff --git a/board/pyro/gpio.inc b/board/pyro/gpio.inc index fea1b8e81a..fca8bd3a0b 100644 --- a/board/pyro/gpio.inc +++ b/board/pyro/gpio.inc @@ -130,8 +130,8 @@ GPIO(USB_C1_PD_RST_ODL, PIN(7, 4), GPIO_ODR_LOW) * Configure as input to enable @ 1.5A, output-low to turn off, or output-high * to enable @ 3A. */ -GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW) /* EN_USB_C0_5V_OUT, Enable C0 */ -GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW) /* EN_USB_C1_5V_OUT, Enable C1 */ +GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C0_5V_OUT, Enable C0 */ +GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C1_5V_OUT, Enable C1 */ /* Clear for non-HDI breakout, must be pulled high */ GPIO(NC1, PIN(0, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_SEL_1P8V) diff --git a/board/pyro/usb_pd_policy.c b/board/pyro/usb_pd_policy.c index cf83ea05bc..3a77eb6cad 100644 --- a/board/pyro/usb_pd_policy.c +++ b/board/pyro/usb_pd_policy.c @@ -21,6 +21,7 @@ #include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_tcpm.h" #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) @@ -33,6 +34,10 @@ const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +const uint32_t pd_src_pdo_max[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max); const uint32_t pd_snk_pdo[] = { PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), @@ -51,9 +56,37 @@ void pd_transition_voltage(int idx) /* No-operation: we are always 5V */ } +static uint8_t vbus_en[CONFIG_USB_PD_PORT_COUNT]; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_COUNT] = {TYPEC_RP_1A5, TYPEC_RP_1A5}; + int board_vbus_source_enabled(int port) { - return gpio_get_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN); + return vbus_en[port]; +} + +static void board_vbus_update_source_current(int port) +{ + enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; + int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? + (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP); + + /* + * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance + * (2x 33k in parallel) on the NX5P3290 load switch ILIM pin, + * setting a minimum OCP current of 3186 mA. + * Putting an internal pull-up on USB_Cx_5V_EN, effectively put a 33k + * resistor on ILIM, setting a minimum OCP current of 1505 mA. + */ + gpio_set_level(gpio, vbus_en[port]); + gpio_set_flags(gpio, flags); +} + +void typec_set_source_current_limit(int port, int rp) +{ + vbus_rp[port] = rp; + + /* change the GPIO driving the load switch if needed */ + board_vbus_update_source_current(port); } int pd_set_power_supply_ready(int port) @@ -61,11 +94,13 @@ int pd_set_power_supply_ready(int port) /* Ensure we're not charging from this port */ bd9995x_select_input_port(bd9995x_pd_port_to_chg_port(port), 0); - /* Provide VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN, 1); + /* Ensure we advertise the proper available current quota */ + charge_manager_source_port(port, 1); pd_set_vbus_discharge(port, 0); + /* Provide VBUS */ + vbus_en[port] = 1; + board_vbus_update_source_current(port); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -75,19 +110,21 @@ int pd_set_power_supply_ready(int port) void pd_power_supply_reset(int port) { - enum gpio_signal gpio; int prev_en; - gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; - prev_en = gpio_get_level(gpio); + prev_en = vbus_en[port]; /* Disable VBUS */ - gpio_set_level(gpio, 0); + vbus_en[port] = 0; + board_vbus_update_source_current(port); /* Enable discharge if we were previously sourcing 5V */ if (prev_en) pd_set_vbus_discharge(port, 1); + /* 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); } diff --git a/board/reef/board.c b/board/reef/board.c index 997664d3a1..655a319506 100644 --- a/board/reef/board.c +++ b/board/reef/board.c @@ -547,8 +547,7 @@ int board_set_active_charge_port(int charge_port) case 0: case 1: /* Don't charge from a source port */ - if (gpio_get_level(charge_port == 0 ? - GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN)) + if (board_vbus_source_enabled(charge_port)) return -1; bd9995x_port = bd9995x_pd_port_to_chg_port(charge_port); diff --git a/board/reef/board.h b/board/reef/board.h index fae92a26ad..d2c6166ee9 100644 --- a/board/reef/board.h +++ b/board/reef/board.h @@ -87,6 +87,7 @@ #define CONFIG_USB_PD_DISCHARGE_TCPC #define CONFIG_USB_PD_LOGGING #define CONFIG_USB_PD_LOG_SIZE 512 +#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_PORT_COUNT 2 #define CONFIG_USB_PD_QUIRK_SLOW_CC_STATUS #define CONFIG_USB_PD_VBUS_DETECT_CHARGER diff --git a/board/reef/gpio.inc b/board/reef/gpio.inc index 2a7f7442f0..8a883251fc 100644 --- a/board/reef/gpio.inc +++ b/board/reef/gpio.inc @@ -126,8 +126,8 @@ GPIO(USB_C1_PD_RST_ODL, PIN(7, 4), GPIO_ODR_LOW) * Configure as input to enable @ 1.5A, output-low to turn off, or output-high * to enable @ 3A. */ -GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW) /* EN_USB_C0_5V_OUT, Enable C0 */ -GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW) /* EN_USB_C1_5V_OUT, Enable C1 */ +GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C0_5V_OUT, Enable C0 */ +GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C1_5V_OUT, Enable C1 */ /* Clear for non-HDI breakout, must be pulled high */ GPIO(NC1, PIN(0, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_SEL_1P8V) diff --git a/board/reef/usb_pd_policy.c b/board/reef/usb_pd_policy.c index 693bd6e2e4..bc530687bd 100644 --- a/board/reef/usb_pd_policy.c +++ b/board/reef/usb_pd_policy.c @@ -21,6 +21,7 @@ #include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_tcpm.h" #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) @@ -33,6 +34,10 @@ const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +const uint32_t pd_src_pdo_max[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max); const uint32_t pd_snk_pdo[] = { PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), @@ -51,9 +56,37 @@ void pd_transition_voltage(int idx) /* No-operation: we are always 5V */ } +static uint8_t vbus_en[CONFIG_USB_PD_PORT_COUNT]; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_COUNT] = {TYPEC_RP_1A5, TYPEC_RP_1A5}; + int board_vbus_source_enabled(int port) { - return gpio_get_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN); + return vbus_en[port]; +} + +static void board_vbus_update_source_current(int port) +{ + enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; + int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? + (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP); + + /* + * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance + * (2x 33k in parallel) on the NX5P3290 load switch ILIM pin, + * setting a minimum OCP current of 3186 mA. + * Putting an internal pull-up on USB_Cx_5V_EN, effectively put a 33k + * resistor on ILIM, setting a minimum OCP current of 1505 mA. + */ + gpio_set_level(gpio, vbus_en[port]); + gpio_set_flags(gpio, flags); +} + +void typec_set_source_current_limit(int port, int rp) +{ + vbus_rp[port] = rp; + + /* change the GPIO driving the load switch if needed */ + board_vbus_update_source_current(port); } int pd_set_power_supply_ready(int port) @@ -61,11 +94,13 @@ int pd_set_power_supply_ready(int port) /* Ensure we're not charging from this port */ bd9995x_select_input_port(bd9995x_pd_port_to_chg_port(port), 0); - /* Provide VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN, 1); + /* Ensure we advertise the proper available current quota */ + charge_manager_source_port(port, 1); pd_set_vbus_discharge(port, 0); + /* Provide VBUS */ + vbus_en[port] = 1; + board_vbus_update_source_current(port); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -75,19 +110,21 @@ int pd_set_power_supply_ready(int port) void pd_power_supply_reset(int port) { - enum gpio_signal gpio; int prev_en; - gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; - prev_en = gpio_get_level(gpio); + prev_en = vbus_en[port]; /* Disable VBUS */ - gpio_set_level(gpio, 0); + vbus_en[port] = 0; + board_vbus_update_source_current(port); /* Enable discharge if we were previously sourcing 5V */ if (prev_en) pd_set_vbus_discharge(port, 1); + /* 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); } diff --git a/board/snappy/board.c b/board/snappy/board.c index 58c83929a3..6510f2bdb4 100644 --- a/board/snappy/board.c +++ b/board/snappy/board.c @@ -515,8 +515,7 @@ int board_set_active_charge_port(int charge_port) case 0: case 1: /* Don't charge from a source port */ - if (gpio_get_level(charge_port == 0 ? - GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN)) + if (board_vbus_source_enabled(charge_port)) return -1; bd9995x_port = bd9995x_pd_port_to_chg_port(charge_port); diff --git a/board/snappy/board.h b/board/snappy/board.h index f7461676e7..b6cdfd8a62 100644 --- a/board/snappy/board.h +++ b/board/snappy/board.h @@ -84,6 +84,7 @@ #define CONFIG_USB_PD_DISCHARGE_TCPC #define CONFIG_USB_PD_LOGGING #define CONFIG_USB_PD_LOG_SIZE 512 +#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_PORT_COUNT 2 #define CONFIG_USB_PD_QUIRK_SLOW_CC_STATUS #define CONFIG_USB_PD_VBUS_DETECT_CHARGER diff --git a/board/snappy/gpio.inc b/board/snappy/gpio.inc index 5794f6f9fd..9cd800c5d0 100644 --- a/board/snappy/gpio.inc +++ b/board/snappy/gpio.inc @@ -131,8 +131,8 @@ GPIO(USB_C1_PD_RST_ODL, PIN(7, 4), GPIO_ODR_LOW) * Configure as input to enable @ 1.5A, output-low to turn off, or output-high * to enable @ 3A. */ -GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW) /* EN_USB_C0_5V_OUT, Enable C0 */ -GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW) /* EN_USB_C1_5V_OUT, Enable C1 */ +GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C0_5V_OUT, Enable C0 */ +GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C1_5V_OUT, Enable C1 */ /* Clear for non-HDI breakout, must be pulled high */ GPIO(NC1, PIN(0, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_SEL_1P8V) diff --git a/board/snappy/usb_pd_policy.c b/board/snappy/usb_pd_policy.c index cf83ea05bc..3a77eb6cad 100644 --- a/board/snappy/usb_pd_policy.c +++ b/board/snappy/usb_pd_policy.c @@ -21,6 +21,7 @@ #include "util.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_tcpm.h" #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) @@ -33,6 +34,10 @@ const uint32_t pd_src_pdo[] = { PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +const uint32_t pd_src_pdo_max[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max); const uint32_t pd_snk_pdo[] = { PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), @@ -51,9 +56,37 @@ void pd_transition_voltage(int idx) /* No-operation: we are always 5V */ } +static uint8_t vbus_en[CONFIG_USB_PD_PORT_COUNT]; +static uint8_t vbus_rp[CONFIG_USB_PD_PORT_COUNT] = {TYPEC_RP_1A5, TYPEC_RP_1A5}; + int board_vbus_source_enabled(int port) { - return gpio_get_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN); + return vbus_en[port]; +} + +static void board_vbus_update_source_current(int port) +{ + enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; + int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? + (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP); + + /* + * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance + * (2x 33k in parallel) on the NX5P3290 load switch ILIM pin, + * setting a minimum OCP current of 3186 mA. + * Putting an internal pull-up on USB_Cx_5V_EN, effectively put a 33k + * resistor on ILIM, setting a minimum OCP current of 1505 mA. + */ + gpio_set_level(gpio, vbus_en[port]); + gpio_set_flags(gpio, flags); +} + +void typec_set_source_current_limit(int port, int rp) +{ + vbus_rp[port] = rp; + + /* change the GPIO driving the load switch if needed */ + board_vbus_update_source_current(port); } int pd_set_power_supply_ready(int port) @@ -61,11 +94,13 @@ int pd_set_power_supply_ready(int port) /* Ensure we're not charging from this port */ bd9995x_select_input_port(bd9995x_pd_port_to_chg_port(port), 0); - /* Provide VBUS */ - gpio_set_level(port ? GPIO_USB_C1_5V_EN : - GPIO_USB_C0_5V_EN, 1); + /* Ensure we advertise the proper available current quota */ + charge_manager_source_port(port, 1); pd_set_vbus_discharge(port, 0); + /* Provide VBUS */ + vbus_en[port] = 1; + board_vbus_update_source_current(port); /* notify host of power info change */ pd_send_host_event(PD_EVENT_POWER_CHANGE); @@ -75,19 +110,21 @@ int pd_set_power_supply_ready(int port) void pd_power_supply_reset(int port) { - enum gpio_signal gpio; int prev_en; - gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; - prev_en = gpio_get_level(gpio); + prev_en = vbus_en[port]; /* Disable VBUS */ - gpio_set_level(gpio, 0); + vbus_en[port] = 0; + board_vbus_update_source_current(port); /* Enable discharge if we were previously sourcing 5V */ if (prev_en) pd_set_vbus_discharge(port, 1); + /* 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); } -- cgit v1.2.1