summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Marheine <pmarheine@chromium.org>2019-12-23 15:14:07 +1100
committerCommit Bot <commit-bot@chromium.org>2019-12-31 04:43:34 +0000
commit76f1cb778934bf14ffb830a8983f339b323f8b48 (patch)
tree5e47858c3a8935b3a864ae389823987075fa336c
parent14a1dcc4325e062a61f77df67c24c81c4dd13cd3 (diff)
downloadchrome-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.c39
-rw-r--r--board/puff/board.h1
-rw-r--r--board/puff/usb_pd_policy.c3
-rw-r--r--power/cometlake-discrete.c5
-rw-r--r--power/intel_x86.c80
-rw-r--r--power/intel_x86.h13
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 */