summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/charge_state_v2.c58
-rw-r--r--include/charge_state_v2.h1
-rw-r--r--test/sbs_charging_v2.c4
3 files changed, 34 insertions, 29 deletions
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
index 2346ddd131..74d8e910f5 100644
--- a/common/charge_state_v2.c
+++ b/common/charge_state_v2.c
@@ -200,17 +200,8 @@ static void update_dynamic_battery_info(void)
curr.batt.state_of_charge <= BATTERY_LEVEL_CRITICAL)
tmp |= EC_BATT_FLAG_LEVEL_CRITICAL;
- switch (curr.state) {
- case ST_DISCHARGE:
- tmp |= EC_BATT_FLAG_DISCHARGING;
- break;
- case ST_CHARGE:
- tmp |= EC_BATT_FLAG_CHARGING;
- break;
- default:
- /* neither charging nor discharging */
- break;
- }
+ tmp |= curr.batt_is_charging ? EC_BATT_FLAG_CHARGING :
+ EC_BATT_FLAG_DISCHARGING;
/* Tell the AP to re-read battery status if charge state changes */
if (*memmap_flags != tmp)
@@ -237,6 +228,7 @@ static void dump_charge_state(void)
#define DUMP_BATT(FLD, FMT) ccprintf("\t" #FLD " = " FMT "\n", curr.batt. FLD)
ccprintf("state = %s\n", state_list[curr.state]);
DUMP(ac, "%d");
+ DUMP(batt_is_charging, "%d");
ccprintf("chg.*:\n");
DUMP_CHG(voltage, "%dmV");
DUMP_CHG(current, "%dmA");
@@ -272,8 +264,7 @@ static void show_charging_progress(void)
{
int rv, minutes, to_full;
- if (curr.state == ST_IDLE ||
- curr.state == ST_DISCHARGE) {
+ if (!curr.batt_is_charging) {
rv = battery_time_to_empty(&minutes);
to_full = 0;
} else {
@@ -414,7 +405,7 @@ static inline int battery_too_low(void)
/* Shut everything down before the battery completely dies. */
static void prevent_deep_discharge(void)
{
- if (!battery_too_low()) {
+ if (!battery_too_low() || curr.batt_is_charging) {
/* Reset shutdown warning time */
shutdown_warning_time.val = 0;
return;
@@ -423,22 +414,24 @@ static void prevent_deep_discharge(void)
CPRINTS("Low battery: %d%%, %dmV",
curr.batt.state_of_charge, curr.batt.voltage);
- if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
-#ifdef CONFIG_HIBERNATE
- /* AP is off, so shut down the EC now */
- CPRINTS("charge force EC hibernate due to low battery");
- system_hibernate(0, 0);
-#endif
- } else if (!shutdown_warning_time.val) {
- /* Warn AP battery level is so low we'll shut down */
+ if (!shutdown_warning_time.val) {
CPRINTS("charge warn shutdown due to low battery");
shutdown_warning_time = get_time();
- host_set_single_event(EC_HOST_EVENT_BATTERY_SHUTDOWN);
+ 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) {
- /* Timeout waiting for AP to shut down, so kill it */
- CPRINTS("charge force shutdown due to low battery");
- chipset_force_shutdown();
+ 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");
+ system_hibernate(0, 0);
+#endif
+ } else {
+ /* Timeout waiting for AP to shut down, so kill it */
+ CPRINTS("charge force shutdown due to low battery");
+ chipset_force_shutdown();
+ }
}
}
@@ -574,11 +567,18 @@ void charger_task(void)
if (curr.batt.flags & BATT_FLAG_BAD_ANY)
problem(PR_BATT_FLAGS, curr.batt.flags);
+ /*
+ * If AC is present, check if input current is sufficient to
+ * actually charge battery.
+ */
+ curr.batt_is_charging = curr.ac && (curr.batt.current >= 0);
+
+ /* Don't let the battery hurt itself. */
+ prevent_hot_discharge();
+ prevent_deep_discharge();
+
if (!curr.ac) {
curr.state = ST_DISCHARGE;
- /* Don't let the battery hurt itself. */
- prevent_hot_discharge();
- prevent_deep_discharge();
goto wait_for_it;
}
diff --git a/include/charge_state_v2.h b/include/charge_state_v2.h
index b8503fcc9c..37b88326c9 100644
--- a/include/charge_state_v2.h
+++ b/include/charge_state_v2.h
@@ -27,6 +27,7 @@ enum charge_state_v2 {
struct charge_state_data {
timestamp_t ts;
int ac;
+ int batt_is_charging;
struct charger_params chg;
struct batt_params batt;
enum charge_state_v2 state;
diff --git a/test/sbs_charging_v2.c b/test/sbs_charging_v2.c
index 31dfb34e25..bb15a8d18b 100644
--- a/test/sbs_charging_v2.c
+++ b/test/sbs_charging_v2.c
@@ -285,6 +285,8 @@ static int test_low_battery(void)
mock_chipset_state = CHIPSET_STATE_SOFT_OFF;
hook_notify(HOOK_CHIPSET_SHUTDOWN);
wait_charging_state();
+ /* after a while, the EC should hibernate */
+ sleep(LOW_BATTERY_SHUTDOWN_TIMEOUT);
TEST_ASSERT(is_hibernated);
ccprintf("[CHARGING TEST] Low battery shutdown S5\n");
@@ -293,6 +295,8 @@ static int test_low_battery(void)
wait_charging_state();
sb_write(SB_RELATIVE_STATE_OF_CHARGE, 2);
wait_charging_state();
+ /* after a while, the EC should hibernate */
+ sleep(LOW_BATTERY_SHUTDOWN_TIMEOUT);
TEST_ASSERT(is_hibernated);
ccprintf("[CHARGING TEST] Low battery AP shutdown\n");