diff options
author | Peter Marheine <pmarheine@chromium.org> | 2019-11-11 14:31:27 +1100 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-12-10 01:56:14 +0000 |
commit | 2cb4d29ad22831110d1b5adec820794b6d76fae9 (patch) | |
tree | cf0261290612b0543ab22e8fca976b84090dde23 /board/puff/board.c | |
parent | f74ddb9de4f7e29402156904d3f16a8d01fb6df5 (diff) | |
download | chrome-ec-2cb4d29ad22831110d1b5adec820794b6d76fae9.tar.gz |
puff: implement PP5000 port power control
The EC watches current limiting on the USB and HDMI ports to keep system
load on the 5V rail within the limits of the regulator. The EC's goal is
to ensure that any single future state change (connecting or
disconnecting a port) doesn't push the 5V rail overcurrent.
Verification is done via symbolic execution with Klee; ensuring that
there exists no state where plugging something into a port with no
further changes would put us over the power budget. Sample verification
output:
> KLEE: Using Z3 solver backend
>
> KLEE: done: total instructions = 4439
> KLEE: done: completed paths = 30
> KLEE: done: generated tests = 30
v2: convert ad-hoc state space exploration for verification to symbolic
execution, allowing port control code to be reused for both.
BUG=b:143190102
TEST=make buildall
BRANCH=none
Change-Id: If06e319c8d38bd11b29a7e69499d40357176a97e
Signed-off-by: Peter Marheine <pmarheine@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1911261
Reviewed-by: Andrew McRae <amcrae@chromium.org>
Diffstat (limited to 'board/puff/board.c')
-rw-r--r-- | board/puff/board.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/board/puff/board.c b/board/puff/board.c index 7e27178469..4e78186b6c 100644 --- a/board/puff/board.c +++ b/board/puff/board.c @@ -55,6 +55,61 @@ static void tcpc_alert_event(enum gpio_signal signal) schedule_deferred_pd_interrupt(0); } +#include "port-sm.c" + +static bool usbc_overcurrent; +/* + * Update USB port power limits based on current state. + * + * Port power consumption is assumed to be negligible if not overcurrent, + * and we have two knobs: the front port power limit, and the USB-C power limit. + * Either one of the front ports may run at high power (one at a time) or we + * can limit both to low power. On USB-C we can similarly limit the port power, + * but there's only one port. + */ +void update_port_limits(void) +{ + struct port_states state = { + .bitfield = (!gpio_get_level(GPIO_USB_A0_OC_ODL) + << PORTMASK_FRONT_A0) | + (!gpio_get_level(GPIO_USB_A1_OC_ODL) + << PORTMASK_FRONT_A1) | + (!gpio_get_level(GPIO_USB_A2_OC_ODL) + << PORTMASK_REAR_A0) | + (!gpio_get_level(GPIO_USB_A3_OC_ODL) + << PORTMASK_REAR_A1) | + (!gpio_get_level(GPIO_USB_A4_OC_ODL) + << PORTMASK_REAR_A2) | + (!gpio_get_level(GPIO_HDMI_CONN0_OC_ODL) + << PORTMASK_HDMI0) | + (!gpio_get_level(GPIO_HDMI_CONN1_OC_ODL) + << PORTMASK_HDMI1) | + ((ppc_is_sourcing_vbus(0) && usbc_overcurrent) + << PORTMASK_TYPEC), + .front_a_limited = gpio_get_level(GPIO_USB_A_LOW_PWR_OD), + /* Assume high-power; there's no way to poll this. */ + /* + * TODO(b/143190102) add a way to poll port power limit so we + * can detect when it can be increased again if the port is + * already active. + */ + .c_low_power = 0, + }; + + update_port_state(&state); + + ppc_set_vbus_source_current_limit(0, + state.c_low_power ? TYPEC_RP_1A5 : TYPEC_RP_3A0); + /* Output high limits power */ + gpio_set_level(GPIO_USB_A_LOW_PWR_OD, state.front_a_limited); +} +DECLARE_DEFERRED(update_port_limits); + +static void port_ocp_interrupt(enum gpio_signal signal) +{ + hook_call_deferred(&update_port_limits_data, 0); +} + #include "gpio_list.h" /* Must come after other header files. */ /******************************************************************************/ @@ -227,6 +282,7 @@ const unsigned int ina3221_count = ARRAY_SIZE(ina3221); static void board_init(void) { + update_port_limits(); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -236,6 +292,11 @@ struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { }; unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); +/* USB-A port control */ +const int usb_port_enable[USB_PORT_COUNT] = { + GPIO_EN_PP5000_USB_VBUS, +}; + /* Power Delivery and charging functions */ void baseboard_tcpc_init(void) { @@ -283,4 +344,5 @@ void board_overcurrent_event(int port, int is_overcurrented) /* Sanity check the port. */ if ((port < 0) || (port >= CONFIG_USB_PD_PORT_MAX_COUNT)) return; + usbc_overcurrent = is_overcurrented; } |