diff options
author | Peter Marheine <pmarheine@chromium.org> | 2019-12-10 11:11:18 +1100 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-12-31 02:02:02 +0000 |
commit | bc28967ad0ee8b684bea9146eff7f89045587678 (patch) | |
tree | 30cffedf2aa625cc1cb610a8efd5dcd78ded3523 | |
parent | dbc522bb9677d5b34ee989f8e961d5be40c354d7 (diff) | |
download | chrome-ec-bc28967ad0ee8b684bea9146eff7f89045587678.tar.gz |
puff: support switching between USB-C and barrel jack power
We let the charge controller decide which port to use, watching the
presence signal to tell the charge control what is connected. We only
allow switching the input when the system is off, since switching may
cause us to brown out.
This is mostly copied from Fizz; I'm unsure if we need to do anything
with the TCPPC when switching (Fizz has a GPIO that physically connects
or disconnects the type-C port).
BUG=b:143975429
TEST=booted on hardware, verified chgsup output with barrel jack
BRANCH=None
Change-Id: I6d2f8365c03aa44f272195708dd534fdc35cd2f6
Signed-off-by: Peter Marheine <pmarheine@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1958387
Reviewed-by: Andrew McRae <amcrae@chromium.org>
Commit-Queue: Andrew McRae <amcrae@chromium.org>
-rw-r--r-- | board/puff/board.c | 99 | ||||
-rw-r--r-- | board/puff/board.h | 5 | ||||
-rw-r--r-- | board/puff/gpio.inc | 2 |
3 files changed, 104 insertions, 2 deletions
diff --git a/board/puff/board.c b/board/puff/board.c index f5057a9c0a..5a19defffa 100644 --- a/board/puff/board.c +++ b/board/puff/board.c @@ -10,6 +10,7 @@ #include "button.h" #include "charge_manager.h" #include "charge_state_v2.h" +#include "chipset.h" #include "common.h" #include "cros_board_info.h" #include "driver/ina3221.h" @@ -144,6 +145,69 @@ static void port_ocp_interrupt(enum gpio_signal signal) hook_call_deferred(&update_port_limits_data, 0); } +/******************************************************************************/ +/* + * Barrel jack power supply handling + * + * EN_PPVAR_BJ_ADP_L must default active to ensure we can power on when the + * barrel jack is connected, and the USB-C port can bring the EC up fine in + * dead-battery mode. Both the USB-C and barrel jack switches do reverse + * protection, so we're safe to turn one on then the other off- but we should + * only do that if the system is off since it might still brown out. + */ +#define ADP_DEBOUNCE_MS 1000 /* Debounce time for BJ plug/unplug */ +/* Debounced connection state of the barrel jack */ +static int adp_connected = 1; +static void adp_state_init(void) +{ + adp_connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_L); + + /* Disable BJ power if not connected (we're on USB-C). */ + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, !adp_connected); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_INIT_EXTPOWER); + +static void adp_connect_deferred(void) +{ + struct charge_port_info pi = { 0 }; + int connected = gpio_get_level(GPIO_BJ_ADP_PRESENT_L); + + /* Debounce */ + if (connected == adp_connected) + return; + if (connected) { + pi.voltage = 19500; + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + /* + * TODO(b:143975429) set current according to SKU. + * Different SKUs will ship with different power bricks + * that have varying power, though setting this to the + * maximum current available on any SKU may be okay + * (assume the included brick is sufficient to run the + * system at max power and over-reporting available + * power will have no effect). + */ + pi.current = 4740; + } + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, + DEDICATED_CHARGE_PORT, &pi); + /* + * Explicitly notifies the host that BJ is plugged or unplugged + * (when running on a type-c adapter). + */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + adp_connected = connected; +} +DECLARE_DEFERRED(adp_connect_deferred); + +/* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ +void adp_connect_interrupt(enum gpio_signal signal) +{ + if (adp_connected == !gpio_get_level(GPIO_BJ_ADP_PRESENT_L)) + return; + hook_call_deferred(&adp_connect_deferred_data, ADP_DEBOUNCE_MS * MSEC); +} + #include "gpio_list.h" /* Must come after other header files. */ /******************************************************************************/ @@ -378,9 +442,42 @@ void board_reset_pd_mcu(void) msleep(BOARD_TCPC_C0_RESET_POST_DELAY); } -/* TODO: set the active charge port */ int board_set_active_charge_port(int port) { + const int active_port = charge_manager_get_active_charge_port(); + + if (port < 0 || CHARGE_PORT_COUNT <= port) + return EC_ERROR_INVAL; + + if (port == active_port) + return EC_SUCCESS; + + /* Don't charge from a source port */ + if (board_vbus_source_enabled(port)) + return EC_ERROR_INVAL; + + /* Change is only permitted while the system is off */ + if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) + return EC_ERROR_INVAL; + + CPRINTS("New charger p%d", port); + + switch (port) { + case CHARGE_PORT_TYPEC0: + /* TODO(b/143975429) need to touch the PD controller? */ + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 1); + break; + case CHARGE_PORT_BARRELJACK: + /* Make sure BJ adapter is sourcing power */ + if (gpio_get_level(GPIO_BJ_ADP_PRESENT_L)) + return EC_ERROR_INVAL; + /* TODO(b/143975429) need to touch the PD controller? */ + gpio_set_level(GPIO_EN_PPVAR_BJ_ADP_L, 0); + break; + default: + return EC_ERROR_INVAL; + } + return EC_SUCCESS; } diff --git a/board/puff/board.h b/board/puff/board.h index 6ad0ef4162..2073738029 100644 --- a/board/puff/board.h +++ b/board/puff/board.h @@ -177,6 +177,11 @@ #include "gpio_signal.h" #include "registers.h" +enum charge_port { + CHARGE_PORT_TYPEC0, + CHARGE_PORT_BARRELJACK, +}; + enum adc_channel { ADC_SNS_PP3300, /* ADC2 */ ADC_SNS_PP1050, /* ADC7 */ diff --git a/board/puff/gpio.inc b/board/puff/gpio.inc index e5e5610b3d..4e479c7484 100644 --- a/board/puff/gpio.inc +++ b/board/puff/gpio.inc @@ -37,6 +37,7 @@ GPIO_INT(IMVP8_VRRDY_OD, PIN(1, 6), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(USB_C0_TCPPC_INT_ODL, PIN(E, 0), GPIO_INT_FALLING, ppc_interrupt) GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(6, 2), GPIO_INT_FALLING, tcpc_alert_event) GPIO_INT(H1_EC_RECOVERY_BTN_ODL, PIN(2, 4), GPIO_INT_BOTH, button_interrupt) +GPIO_INT(BJ_ADP_PRESENT_L, PIN(8, 2), GPIO_INT_BOTH, adp_connect_interrupt) /* Port power control interrupts */ GPIO_INT(HDMI_CONN0_OC_ODL, PIN(0, 7), GPIO_INT_BOTH, port_ocp_interrupt) @@ -70,7 +71,6 @@ GPIO(EN_IMVP8_VR, PIN(F, 4), GPIO_OUT_LOW) /* Barreljack */ GPIO(EN_PPVAR_BJ_ADP_L, PIN(0, 4), GPIO_OUT_LOW) -GPIO(BJ_ADP_PRESENT_L, PIN(8, 2), GPIO_INPUT) /* USB type A */ GPIO(EN_PP5000_USB_VBUS, PIN(8, 3), GPIO_OUT_LOW) |