summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2015-12-19 10:38:52 -0800
committerchrome-bot <chrome-bot@chromium.org>2016-01-06 18:48:11 -0800
commit0af6e77a3a90299418628a997c81436acbec242c (patch)
tree342623ba55704015efdd89515f893974471dcb5e
parent0c8a1b8d39734eaae692eacbe04894207bb2c6da (diff)
downloadchrome-ec-0af6e77a3a90299418628a997c81436acbec242c.tar.gz
charger: Change unlocked battery level ignore conditions
x86 systems will auto-power-on when power is applied to the EC. When the battery level is critically low, power-on is prevented, except when the system is unlocked. So, when unlocked, some systems will auto-power-on regardless of battery level, overcurrent the charger / battery, and then repeat forever. Prevent this reboot loop by ignoring auto-power-up when the battery is critically low, regardless of system unlocked status. BUG=chrome-os-partner:48339 TEST=Verify power-up is prevented on no-battery chell w/ donette. Then, run 'powerbtn' on EC console and verify system powers on (and overcurrents). BRANCH=None Change-Id: Ia631b5a8c45b42ec805e4a0c3f827929a0efd236 Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/319187 Commit-Ready: Shawn N <shawnn@chromium.org> Tested-by: Shawn N <shawnn@chromium.org> Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
-rw-r--r--board/samus/power_sequence.c2
-rw-r--r--common/charge_state_v1.c2
-rw-r--r--common/charge_state_v2.c18
-rw-r--r--common/lightbar.c2
-rw-r--r--common/power_button_x86.c24
-rw-r--r--include/charge_state.h5
-rw-r--r--include/charger.h2
-rw-r--r--power/skylake.c2
8 files changed, 31 insertions, 26 deletions
diff --git a/board/samus/power_sequence.c b/board/samus/power_sequence.c
index a3e40338f4..cac9647a44 100644
--- a/board/samus/power_sequence.c
+++ b/board/samus/power_sequence.c
@@ -228,7 +228,7 @@ enum power_state power_handle_state(enum power_state state)
case POWER_G3S5:
/* Return to G3 if battery level is too low */
if (charge_want_shutdown() ||
- charge_prevent_power_on()) {
+ charge_prevent_power_on(0)) {
CPRINTS("power-up inhibited");
chipset_force_g3();
return POWER_G3;
diff --git a/common/charge_state_v1.c b/common/charge_state_v1.c
index 4002901f76..b38bdc3e0d 100644
--- a/common/charge_state_v1.c
+++ b/common/charge_state_v1.c
@@ -682,7 +682,7 @@ int charge_want_shutdown(void)
charge_get_percent() < BATTERY_LEVEL_SHUTDOWN;
}
-int charge_prevent_power_on(void)
+int charge_prevent_power_on(int power_button_pressed)
{
int prevent_power_on = 0;
#ifdef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
index c49fc639eb..4401aa54bb 100644
--- a/common/charge_state_v2.c
+++ b/common/charge_state_v2.c
@@ -644,8 +644,6 @@ void charger_task(void)
charger_set_input_current(curr.desired_input_current);
}
- curr.chg.flags |= CHG_FLAG_INITIALIZED;
-
/*
* TODO(crosbug.com/p/27527). Sometimes the battery thinks its
* temperature is 6280C, which seems a bit high. Let's ignore
@@ -916,14 +914,20 @@ int charge_want_shutdown(void)
(curr.batt.state_of_charge < BATTERY_LEVEL_SHUTDOWN);
}
-int charge_prevent_power_on(void)
+int charge_prevent_power_on(int power_button_pressed)
{
int prevent_power_on = 0;
#ifdef CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON
struct batt_params params;
struct batt_params *current_batt_params = &curr.batt;
- int charger_is_uninitialized =
- !(curr.chg.flags & CHG_FLAG_INITIALIZED);
+ static int automatic_power_on = 1;
+
+ /*
+ * Remember that a power button was pressed, and assume subsequent
+ * power-ups are user-requested and non-automatic.
+ */
+ if (power_button_pressed)
+ automatic_power_on = 0;
/* If battery params seem uninitialized then retrieve them */
if (current_batt_params->is_present == BP_NOT_SURE) {
@@ -951,9 +955,9 @@ int charge_prevent_power_on(void)
/*
* Factory override: Always allow power on if WP is disabled,
- * except when EC is starting up, due to brown out potential.
+ * except when auto-power-on at EC startup.
*/
- prevent_power_on &= (system_is_locked() || charger_is_uninitialized);
+ prevent_power_on &= (system_is_locked() || automatic_power_on);
#endif
return prevent_power_on;
diff --git a/common/lightbar.c b/common/lightbar.c
index 2355067016..822cb77caf 100644
--- a/common/lightbar.c
+++ b/common/lightbar.c
@@ -268,7 +268,7 @@ static int get_battery_level(void)
#ifdef HAS_TASK_CHARGER
st.battery_percent = pct = charge_get_percent();
st.battery_is_charging = (PWR_STATE_DISCHARGE != charge_get_state());
- st.battery_is_power_on_prevented = charge_prevent_power_on();
+ st.battery_is_power_on_prevented = charge_prevent_power_on(0);
#endif
/* Find the new battery level */
diff --git a/common/power_button_x86.c b/common/power_button_x86.c
index 9ae2be1ff5..ce7bba990e 100644
--- a/common/power_button_x86.c
+++ b/common/power_button_x86.c
@@ -112,7 +112,7 @@ static const char * const state_names[] = {
*/
static uint64_t tnext_state;
-static void set_pwrbtn_to_pch(int high)
+static void set_pwrbtn_to_pch(int high, int init)
{
/*
* If the battery is discharging and low enough we'd shut down the
@@ -122,7 +122,7 @@ static void set_pwrbtn_to_pch(int high)
*/
#ifdef CONFIG_CHARGER
if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && !high &&
- (charge_want_shutdown() || charge_prevent_power_on())) {
+ (charge_want_shutdown() || charge_prevent_power_on(!init))) {
CPRINTS("PB PCH pwrbtn ignored due to battery level");
high = 1;
}
@@ -137,7 +137,7 @@ void power_button_pch_press(void)
/* Assert power button signal to PCH */
if (!power_button_is_pressed())
- set_pwrbtn_to_pch(0);
+ set_pwrbtn_to_pch(0, 0);
}
void power_button_pch_release(void)
@@ -145,7 +145,7 @@ void power_button_pch_release(void)
CPRINTS("PB PCH force release");
/* Deassert power button signal to PCH */
- set_pwrbtn_to_pch(1);
+ set_pwrbtn_to_pch(1, 0);
/*
* If power button is actually pressed, eat the next release so we
@@ -162,7 +162,7 @@ void power_button_pch_pulse(void)
CPRINTS("PB PCH pulse");
chipset_exit_hard_off();
- set_pwrbtn_to_pch(0);
+ set_pwrbtn_to_pch(0, 0);
pwrbtn_state = PWRBTN_STATE_LID_OPEN;
tnext_state = get_time().val + PWRBTN_INITIAL_US;
task_wake(TASK_ID_POWERBTN);
@@ -203,7 +203,7 @@ static void set_initial_pwrbtn_state(void)
*/
if (power_button_is_pressed()) {
CPRINTS("PB init-jumped-held");
- set_pwrbtn_to_pch(0);
+ set_pwrbtn_to_pch(0, 0);
} else {
CPRINTS("PB init-jumped");
}
@@ -270,12 +270,12 @@ static void state_machine(uint64_t tnow)
tnext_state = tnow + PWRBTN_DELAY_T0;
pwrbtn_state = PWRBTN_STATE_T0;
}
- set_pwrbtn_to_pch(0);
+ set_pwrbtn_to_pch(0, 0);
break;
case PWRBTN_STATE_T0:
tnext_state = tnow + PWRBTN_DELAY_T1;
pwrbtn_state = PWRBTN_STATE_T1;
- set_pwrbtn_to_pch(1);
+ set_pwrbtn_to_pch(1, 0);
break;
case PWRBTN_STATE_T1:
/*
@@ -286,12 +286,12 @@ static void state_machine(uint64_t tnow)
if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
CPRINTS("PB chipset already off");
else
- set_pwrbtn_to_pch(0);
+ set_pwrbtn_to_pch(0, 0);
pwrbtn_state = PWRBTN_STATE_HELD;
break;
case PWRBTN_STATE_RELEASED:
case PWRBTN_STATE_LID_OPEN:
- set_pwrbtn_to_pch(1);
+ set_pwrbtn_to_pch(1, 0);
pwrbtn_state = PWRBTN_STATE_IDLE;
break;
case PWRBTN_STATE_INIT_ON:
@@ -310,7 +310,7 @@ static void state_machine(uint64_t tnow)
* battery is handled inside set_pwrbtn_to_pch().
*/
chipset_exit_hard_off();
- set_pwrbtn_to_pch(0);
+ set_pwrbtn_to_pch(0, 1);
tnext_state = get_time().val + PWRBTN_INITIAL_US;
if (power_button_is_pressed()) {
@@ -329,7 +329,7 @@ static void state_machine(uint64_t tnow)
* button until it's released, so that holding down the
* recovery combination doesn't cause the chipset to shut back
* down. */
- set_pwrbtn_to_pch(1);
+ set_pwrbtn_to_pch(1, 0);
if (power_button_is_pressed())
pwrbtn_state = PWRBTN_STATE_EAT_RELEASE;
else
diff --git a/include/charge_state.h b/include/charge_state.h
index 97c6ca404e..3a86bf4baf 100644
--- a/include/charge_state.h
+++ b/include/charge_state.h
@@ -96,8 +96,11 @@ int charge_want_shutdown(void);
/**
* Return non-zero if the battery level is too low to allow power on, even if
* a charger is attached.
+ *
+ * @param power_button_pressed True if the power-up attempt is caused by a
+ * power button press.
*/
-int charge_prevent_power_on(void);
+int charge_prevent_power_on(int power_button_pressed);
/**
* Get the last polled battery/charger temperature.
diff --git a/include/charger.h b/include/charger.h
index 70d0ff7543..3141c89bab 100644
--- a/include/charger.h
+++ b/include/charger.h
@@ -49,8 +49,6 @@ void charger_get_params(struct charger_params *chg);
#define CHG_FLAG_BAD_INPUT_CURRENT 0x00000004
#define CHG_FLAG_BAD_STATUS 0x00000008
#define CHG_FLAG_BAD_OPTION 0x00000010
-/* Bit to indicate that the charger data has been initialized */
-#define CHG_FLAG_INITIALIZED 0x00000020
/* All of the above CHG_FLAG_BAD_* bits */
#define CHG_FLAG_BAD_ANY 0x0000001f
diff --git a/power/skylake.c b/power/skylake.c
index 8c28b6d42e..c15c26d1f7 100644
--- a/power/skylake.c
+++ b/power/skylake.c
@@ -198,7 +198,7 @@ static enum power_state _power_handle_state(enum power_state state)
* Allow up to 1s for charger to be initialized, in case
* we're trying to boot the AP with no battery.
*/
- while (charge_prevent_power_on() &&
+ while (charge_prevent_power_on(0) &&
tries++ < CHARGER_INITIALIZED_TRIES) {
msleep(CHARGER_INITIALIZED_DELAY_MS);
}