diff options
author | Peter Marheine <pmarheine@chromium.org> | 2019-12-23 15:14:07 +1100 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-12-31 04:43:34 +0000 |
commit | 76f1cb778934bf14ffb830a8983f339b323f8b48 (patch) | |
tree | 5e47858c3a8935b3a864ae389823987075fa336c | |
parent | 14a1dcc4325e062a61f77df67c24c81c4dd13cd3 (diff) | |
download | chrome-ec-76f1cb778934bf14ffb830a8983f339b323f8b48.tar.gz |
puff: prevent AP boot when there isn't enough power
The common x86 state machine does this, but the EC-controlled sequencing
did not. Since trying to boot the AP without enough power will cause
the system to brown out, we need to do it too.
TEST=boot prevented on hardware
BRANCH=none
BUG=b:146515963
Change-Id: I7dbe6ab962fbe47d4d866be98d4174291c757c72
Signed-off-by: Peter Marheine <pmarheine@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1980104
Reviewed-by: Andrew McRae <amcrae@chromium.org>
-rw-r--r-- | board/puff/board.c | 39 | ||||
-rw-r--r-- | board/puff/board.h | 1 | ||||
-rw-r--r-- | board/puff/usb_pd_policy.c | 3 | ||||
-rw-r--r-- | power/cometlake-discrete.c | 5 | ||||
-rw-r--r-- | power/intel_x86.c | 80 | ||||
-rw-r--r-- | power/intel_x86.h | 13 |
6 files changed, 85 insertions, 56 deletions
diff --git a/board/puff/board.c b/board/puff/board.c index 590085e8a5..1889ca8467 100644 --- a/board/puff/board.c +++ b/board/puff/board.c @@ -157,26 +157,17 @@ static void port_ocp_interrupt(enum gpio_signal signal) */ #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 int8_t adp_connected = -1; static void adp_connect_deferred(void) { struct charge_port_info pi = { 0 }; - int connected = gpio_get_level(GPIO_BJ_ADP_PRESENT_L); + int connected = !gpio_get_level(GPIO_BJ_ADP_PRESENT_L); /* Debounce */ if (connected == adp_connected) return; if (connected) { - pi.voltage = 19500; + pi.voltage = 19000; if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) /* * TODO(b:143975429) set current according to SKU. @@ -191,11 +182,6 @@ static void adp_connect_deferred(void) } 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); @@ -203,11 +189,26 @@ 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); } +static void adp_state_init(void) +{ + /* + * Initialize all charge suppliers to 0. The charge manager waits until + * all ports have reported in before doing anything. + */ + for (int i = 0; i < CHARGE_PORT_COUNT; i++) { + for (int j = 0; j < CHARGE_SUPPLIER_COUNT; j++) + charge_manager_update_charge(j, i, NULL); + } + + /* Report charge state from the barrel jack. */ + adp_connect_deferred(); +} +DECLARE_HOOK(HOOK_INIT, adp_state_init, HOOK_PRIO_CHARGE_MANAGER_INIT + 1); + + #include "gpio_list.h" /* Must come after other header files. */ /******************************************************************************/ diff --git a/board/puff/board.h b/board/puff/board.h index 2073738029..5b124b50cb 100644 --- a/board/puff/board.h +++ b/board/puff/board.h @@ -118,6 +118,7 @@ /* Charger */ #define CONFIG_CHARGE_MANAGER +#undef CONFIG_CHARGE_MANAGER_SAFE_MODE #define CONFIG_CHARGER_INPUT_CURRENT 512 /* Allow low-current USB charging */ /* USB type C */ diff --git a/board/puff/usb_pd_policy.c b/board/puff/usb_pd_policy.c index 13aea2afb6..dd4b8e19bd 100644 --- a/board/puff/usb_pd_policy.c +++ b/board/puff/usb_pd_policy.c @@ -65,5 +65,8 @@ int pd_snk_is_vbus_provided(int port) int board_vbus_source_enabled(int port) { + /* Ignore non-PD ports (the barrel jack). */ + if (port >= CONFIG_USB_PD_PORT_MAX_COUNT) + return 0; return ppc_is_sourcing_vbus(port); } diff --git a/power/cometlake-discrete.c b/power/cometlake-discrete.c index 5ab923499c..94b4723d33 100644 --- a/power/cometlake-discrete.c +++ b/power/cometlake-discrete.c @@ -286,6 +286,11 @@ enum power_state power_handle_state(enum power_state state) switch (state) { case POWER_G3S5: + if (intel_x86_wait_power_up_ok() != EC_SUCCESS) { + chipset_force_shutdown( + CHIPSET_SHUTDOWN_BATTERY_INHIBIT); + return POWER_G3; + } /* Power-up steps 2a-2h. */ #ifdef CONFIG_POWER_PP5000_CONTROL power_5v_enable(task_get_current(), 1); diff --git a/power/intel_x86.c b/power/intel_x86.c index c60c1f94e3..ecf36268cb 100644 --- a/power/intel_x86.c +++ b/power/intel_x86.c @@ -432,47 +432,11 @@ enum power_state common_intel_x86_power_handle_state(enum power_state state) #endif case POWER_G3S5: -#ifdef CONFIG_CHARGER - { - int tries = 0; - - /* - * Allow charger to be initialized for upto defined tries, - * in case we're trying to boot the AP with no battery. - */ - while ((tries < CHARGER_INITIALIZED_TRIES) && - is_power_up_inhibited()) { - msleep(CHARGER_INITIALIZED_DELAY_MS); - tries++; - } - - /* - * Return to G3 if battery level is too low. Set - * power_up_inhibited in order to check the eligibility to boot - * AP up after battery SOC changes. - */ - if (tries == CHARGER_INITIALIZED_TRIES) { - CPRINTS("power-up inhibited"); - power_up_inhibited = 1; + if (intel_x86_wait_power_up_ok() != EC_SUCCESS) { chipset_force_shutdown( CHIPSET_SHUTDOWN_BATTERY_INHIBIT); return POWER_G3; } - - power_up_inhibited = 0; - } -#endif - -#ifdef CONFIG_VBOOT_EFS - /* - * We have to test power readiness here (instead of S5->S3) - * because when entering S5, EC enables EC_ROP_SLP_SUS pin - * which causes (short-powered) system to brown out. - */ - while (!system_can_boot_ap()) - msleep(200); -#endif - #ifdef CONFIG_CHIPSET_HAS_PRE_INIT_CALLBACK /* * Callback to do pre-initialization within the context of @@ -743,3 +707,45 @@ void chipset_reset(enum chipset_reset_reason reason) udelay(32 * MSEC); gpio_set_level(GPIO_SYS_RESET_L, 1); } + +enum ec_error_list intel_x86_wait_power_up_ok(void) +{ +#ifdef CONFIG_CHARGER + int tries = 0; + + /* + * Allow charger to be initialized for up to defined tries, + * in case we're trying to boot the AP with no battery. + */ + while ((tries < CHARGER_INITIALIZED_TRIES) && + is_power_up_inhibited()) { + msleep(CHARGER_INITIALIZED_DELAY_MS); + tries++; + } + + /* + * Return to G3 if battery level is too low. Set + * power_up_inhibited in order to check the eligibility to boot + * AP up after battery SOC changes. + */ + if (tries == CHARGER_INITIALIZED_TRIES) { + CPRINTS("power-up inhibited"); + power_up_inhibited = 1; + return EC_ERROR_TIMEOUT; + } + + power_up_inhibited = 0; +#endif + +#ifdef CONFIG_VBOOT_EFS + /* + * We have to test power readiness here (instead of S5->S3) + * because when entering S5, EC enables EC_ROP_SLP_SUS pin + * which causes (short-powered) system to brown out. + */ + while (!system_can_boot_ap()) + msleep(200); +#endif + + return EC_SUCCESS; +} diff --git a/power/intel_x86.h b/power/intel_x86.h index b1e60bd17f..3f4d8ff6f0 100644 --- a/power/intel_x86.h +++ b/power/intel_x86.h @@ -62,4 +62,17 @@ enum power_state chipset_force_g3(void); */ enum power_state common_intel_x86_power_handle_state(enum power_state state); +/** + * Wait for power-up to be allowed based on available power. + * + * This delays G3->S5 until there is enough power to boot the AP, waiting + * first until the charger (if any) is ready, then for there to be sufficient + * power. + * + * In case of error, the caller should not allow power-up past G3. + * + * @return EC_SUCCESS if OK. + */ +enum ec_error_list intel_x86_wait_power_up_ok(void); + #endif /* __CROS_EC_INTEL_X86_H */ |