summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/charge_state_v1.c3
-rw-r--r--common/charge_state_v2.c92
-rw-r--r--include/charge_state.h3
-rw-r--r--test/sbs_charging_v2.c12
4 files changed, 43 insertions, 67 deletions
diff --git a/common/charge_state_v1.c b/common/charge_state_v1.c
index 9be0d47c15..a39499a75d 100644
--- a/common/charge_state_v1.c
+++ b/common/charge_state_v1.c
@@ -29,7 +29,8 @@
/* Voltage debounce time */
#define DEBOUNCE_TIME (10 * SECOND)
-#define LOW_BATTERY_SHUTDOWN_TIMEOUT_US (LOW_BATTERY_SHUTDOWN_TIMEOUT * SECOND)
+#define LOW_BATTERY_SHUTDOWN_TIMEOUT_US \
+ (CRITICAL_BATTERY_SHUTDOWN_TIMEOUT * SECOND)
#ifndef BATTERY_AP_OFF_LEVEL
#define BATTERY_AP_OFF_LEVEL 0
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
index 051113c0e2..e692f68703 100644
--- a/common/charge_state_v2.c
+++ b/common/charge_state_v2.c
@@ -28,8 +28,8 @@
#define CPUTS(outstr) cputs(CC_CHARGER, outstr)
#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
-#define LOW_BATTERY_SHUTDOWN_TIMEOUT_US (LOW_BATTERY_SHUTDOWN_TIMEOUT * SECOND)
-#define HIGH_TEMP_SHUTDOWN_TIMEOUT_US (HIGH_TEMP_SHUTDOWN_TIMEOUT * SECOND)
+#define CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US \
+ (CRITICAL_BATTERY_SHUTDOWN_TIMEOUT * SECOND)
#define PRECHARGE_TIMEOUT_US (PRECHARGE_TIMEOUT * SECOND)
#define LFCC_EVENT_THRESH 5 /* Full-capacity change reqd for host event */
@@ -45,7 +45,6 @@ static int state_machine_force_idle;
static int manual_mode; /* volt/curr are no longer maintained by charger */
static unsigned int user_current_limit = -1U;
test_export_static timestamp_t shutdown_warning_time;
-test_export_static timestamp_t shutdown_batttemp_warning_time;
static timestamp_t precharge_start_time;
static int battery_seems_to_be_dead;
static int battery_seems_to_be_disconnected;
@@ -402,87 +401,65 @@ static inline int battery_too_hot(int batt_temp_c)
batt_temp_c < batt_info->discharging_min_c));
}
-static void prevent_hot_discharge(void)
+/* True if we know the charge is too low, or we know the voltage is too low. */
+static inline int battery_too_low(void)
+{
+ return ((!(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
+ curr.batt.state_of_charge < BATTERY_LEVEL_SHUTDOWN) ||
+ (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) &&
+ curr.batt.voltage <= batt_info->voltage_min));
+}
+
+
+/*
+ * Send host event to the AP if the battery is temperature or charge level
+ * is critical. Force-shutdown if the problem isn't corrected after timeout.
+ */
+static void shutdown_on_critical_battery(void)
{
int batt_temp_c;
+ int battery_critical = 0;
/*
* TODO(crosbug.com/p/27642): The thermal loop should watch the battery
- * temp anyway, so it can turn fans on. It could also force an AP
- * shutdown if it's too hot, but AFAIK we don't have anything in place
- * to do a battery shutdown if it's really really hot. We probably
- * should, just in case.
+ * temp, so it can turn fans on.
*/
batt_temp_c = DECI_KELVIN_TO_CELSIUS(curr.batt.temperature);
-
- if (!battery_too_hot(batt_temp_c)) {
- /* Reset shutdown warning time */
- shutdown_batttemp_warning_time.val = 0;
- return;
+ if (battery_too_hot(batt_temp_c)) {
+ CPRINTS("Batt temp out of range: %dC", batt_temp_c);
+ battery_critical = 1;
}
- CPRINTS("Batt temp out of range %dC", batt_temp_c);
-
- if (!shutdown_batttemp_warning_time.val) {
- CPRINTS("charge warn shutdown due to battery temp %dC",
- batt_temp_c);
- shutdown_batttemp_warning_time.val = get_time().val;
- if (!chipset_in_state(CHIPSET_STATE_ANY_OFF))
- host_set_single_event(EC_HOST_EVENT_BATTERY_SHUTDOWN);
- } else if (get_time().val > shutdown_batttemp_warning_time.val +
- HIGH_TEMP_SHUTDOWN_TIMEOUT_US) {
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
-#ifdef CONFIG_HIBERNATE
- /* Timeout waiting for temp to change */
- CPRINTS("charge force EC hib due to batt temp %dC",
- batt_temp_c);
- system_hibernate(0, 0);
-#endif
- } else {
- CPRINTS("charge force shutdown due to batt temp %dC",
- batt_temp_c);
- chipset_force_shutdown();
- }
+ if (battery_too_low() && !curr.batt_is_charging) {
+ CPRINTS("Low battery: %d%%, %dmV",
+ curr.batt.state_of_charge, curr.batt.voltage);
+ battery_critical = 1;
}
-}
-
-/* True if we know the charge is too low, or we know the voltage is too low. */
-static inline int battery_too_low(void)
-{
- return ((!(curr.batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) &&
- curr.batt.state_of_charge < BATTERY_LEVEL_SHUTDOWN) ||
- (!(curr.batt.flags & BATT_FLAG_BAD_VOLTAGE) &&
- curr.batt.voltage <= batt_info->voltage_min));
-}
-/* Shut everything down before the battery completely dies. */
-static void prevent_deep_discharge(void)
-{
- if (!battery_too_low() || curr.batt_is_charging) {
+ if (!battery_critical) {
/* Reset shutdown warning time */
shutdown_warning_time.val = 0;
return;
}
- CPRINTS("Low battery: %d%%, %dmV",
- curr.batt.state_of_charge, curr.batt.voltage);
-
if (!shutdown_warning_time.val) {
- CPRINTS("charge warn shutdown due to low battery");
+ CPRINTS("charge warn shutdown due to critical battery");
shutdown_warning_time = get_time();
if (!chipset_in_state(CHIPSET_STATE_ANY_OFF))
host_set_single_event(EC_HOST_EVENT_BATTERY_SHUTDOWN);
} else if (get_time().val > shutdown_warning_time.val +
- LOW_BATTERY_SHUTDOWN_TIMEOUT_US) {
+ CRITICAL_BATTERY_SHUTDOWN_TIMEOUT_US) {
if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
#ifdef CONFIG_HIBERNATE
/* Timeout waiting for charger to provide more power */
- CPRINTS("charge force EC hibernate due to low battery");
+ CPRINTS(
+ "charge force EC hibernate due to critical battery");
system_hibernate(0, 0);
#endif
} else {
/* Timeout waiting for AP to shut down, so kill it */
- CPRINTS("charge force shutdown due to low battery");
+ CPRINTS(
+ "charge force shutdown due to critical battery");
chipset_force_shutdown();
}
}
@@ -628,8 +605,7 @@ void charger_task(void)
curr.batt_is_charging = curr.ac && (curr.batt.current >= 0);
/* Don't let the battery hurt itself. */
- prevent_hot_discharge();
- prevent_deep_discharge();
+ shutdown_on_critical_battery();
if (!curr.ac) {
curr.state = ST_DISCHARGE;
diff --git a/include/charge_state.h b/include/charge_state.h
index fea4231def..ab9c1043b5 100644
--- a/include/charge_state.h
+++ b/include/charge_state.h
@@ -11,8 +11,7 @@
/* Stuff that's common to all charger implementations can go here. */
/* Seconds after AP battery shutdown warning before we kill the AP */
-#define LOW_BATTERY_SHUTDOWN_TIMEOUT 30
-#define HIGH_TEMP_SHUTDOWN_TIMEOUT 30
+#define CRITICAL_BATTERY_SHUTDOWN_TIMEOUT 30
/* Seconds to spend trying to wake a non-responsive battery */
#define PRECHARGE_TIMEOUT 30
diff --git a/test/sbs_charging_v2.c b/test/sbs_charging_v2.c
index bb5097948c..a42d286378 100644
--- a/test/sbs_charging_v2.c
+++ b/test/sbs_charging_v2.c
@@ -222,7 +222,7 @@ static int test_charge_state(void)
TEST_ASSERT(state == PWR_STATE_DISCHARGE);
sb_write(SB_TEMPERATURE, CELSIUS_TO_DECI_KELVIN(90));
state = wait_charging_state();
- sleep(HIGH_TEMP_SHUTDOWN_TIMEOUT);
+ sleep(CRITICAL_BATTERY_SHUTDOWN_TIMEOUT);
TEST_ASSERT(is_shutdown);
TEST_ASSERT(state == PWR_STATE_DISCHARGE);
sb_write(SB_TEMPERATURE, CELSIUS_TO_DECI_KELVIN(40));
@@ -277,7 +277,7 @@ static int test_low_battery(void)
ccprintf("[CHARGING TEST] Low battery with AC and negative current\n");
sb_write(SB_CURRENT, -1000);
wait_charging_state();
- sleep(LOW_BATTERY_SHUTDOWN_TIMEOUT);
+ sleep(CRITICAL_BATTERY_SHUTDOWN_TIMEOUT);
TEST_ASSERT(is_hibernated);
ccprintf("[CHARGING TEST] Low battery shutdown S0->S5\n");
@@ -293,7 +293,7 @@ static int test_low_battery(void)
hook_notify(HOOK_CHIPSET_SHUTDOWN);
wait_charging_state();
/* after a while, the EC should hibernate */
- sleep(LOW_BATTERY_SHUTDOWN_TIMEOUT);
+ sleep(CRITICAL_BATTERY_SHUTDOWN_TIMEOUT);
TEST_ASSERT(is_hibernated);
ccprintf("[CHARGING TEST] Low battery shutdown S5\n");
@@ -303,7 +303,7 @@ static int test_low_battery(void)
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2);
wait_charging_state();
/* after a while, the EC should hibernate */
- sleep(LOW_BATTERY_SHUTDOWN_TIMEOUT);
+ sleep(CRITICAL_BATTERY_SHUTDOWN_TIMEOUT);
TEST_ASSERT(is_hibernated);
ccprintf("[CHARGING TEST] Low battery AP shutdown\n");
@@ -334,7 +334,7 @@ static int test_high_temp_battery(void)
wait_charging_state();
TEST_ASSERT(ev_is_set(EC_HOST_EVENT_BATTERY_SHUTDOWN));
TEST_ASSERT(!is_shutdown);
- sleep(HIGH_TEMP_SHUTDOWN_TIMEOUT);
+ sleep(CRITICAL_BATTERY_SHUTDOWN_TIMEOUT);
TEST_ASSERT(is_shutdown);
ccprintf("[CHARGING TEST] High battery temp S0->S5 hibernate\n");
@@ -666,7 +666,7 @@ static int test_low_battery_hostevents(void)
TEST_ASSERT(ev_is_set(EC_HOST_EVENT_BATTERY_SHUTDOWN));
TEST_ASSERT(!is_shutdown);
/* after a while, the AP should shut down */
- sleep(LOW_BATTERY_SHUTDOWN_TIMEOUT);
+ sleep(CRITICAL_BATTERY_SHUTDOWN_TIMEOUT);
TEST_ASSERT(is_shutdown);
return EC_SUCCESS;