summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-10-02 14:12:45 -0700
committerGerrit <chrome-bot@google.com>2012-10-02 16:05:17 -0700
commit3c06f602b638f1f6eff1bde29dd1cbd3caf8c707 (patch)
tree36aafe2f0351ca239df50193333f244bfb72b712
parent2768a49fd1540cfc42652357bea6497b52042a36 (diff)
downloadchrome-ec-3c06f602b638f1f6eff1bde29dd1cbd3caf8c707.tar.gz
link: Add charge_near_full state
Tell the host the battery is no longer charging when it hits 97%, and set the power adapter LED to green. This solves several problems: 1) The last 3% of charge takes a looong time. Kernel/ACPI/UI already have a hack to show the battery as charged when it's about 3% from full, but the EC still showed a yellow LED. 2) If the system is charged and you briefly unplug the adapter, the LED turned yellow for a long time as it slowly trickle-charged. Now it goes right to green. 3) A fully-charged battery will drop below 100% charge as it settles, but won't accept more current at that time. This caused the LED to turn yellow and stay there until the battery finally settled down to ~96%, at which point it'd accept more current and top itself off. The whole time it did this, the kernel/ACPI/UI hack from (1) would keep reporting "battery full". Now the LED stays green too. BUG=chrome-os-partner:11248 BRANCH=link TEST=manual - Discharge system to <95% full. - Plug adapter in. LED should come on yellow. - At around 97% full, the LED should turn green. - Around that the UI will display "battery full". (Note that due to rounding, the UI may take a few minutes to display "battery full" after the LED goes green; that's ok) - Unplug and replug adapter. LED should come on green. UI still reports "battery full". Change-Id: Ie56fbf3a05239e73d2c765bb98d36aa5cfedc2ef Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/34452
-rw-r--r--common/charge_state.c33
-rw-r--r--include/battery.h4
-rw-r--r--include/charge_state.h12
3 files changed, 44 insertions, 5 deletions
diff --git a/common/charge_state.c b/common/charge_state.c
index c1454996cb..b0deee1f2c 100644
--- a/common/charge_state.c
+++ b/common/charge_state.c
@@ -359,7 +359,11 @@ static enum power_state state_idle(struct power_state_context *ctx)
return PWR_STATE_ERROR;
}
update_charger_time(ctx, get_time());
- return PWR_STATE_CHARGE;
+
+ if (ctx->curr.batt.state_of_charge < NEAR_FULL_THRESHOLD)
+ return PWR_STATE_CHARGE;
+ else
+ return PWR_STATE_CHARGE_NEAR_FULL;
}
return PWR_STATE_UNCHANGE;
@@ -602,6 +606,7 @@ void charge_state_machine_task(void)
break;
case PWR_STATE_IDLE0:
new_state = state_idle(ctx);
+ /* If still idling, move from IDLE0 to IDLE */
if (new_state == PWR_STATE_UNCHANGE)
new_state = PWR_STATE_IDLE;
break;
@@ -613,6 +618,22 @@ void charge_state_machine_task(void)
break;
case PWR_STATE_CHARGE:
new_state = state_charge(ctx);
+ if (new_state == PWR_STATE_UNCHANGE &&
+ (ctx->curr.batt.state_of_charge >=
+ NEAR_FULL_THRESHOLD)) {
+ /* Almost done charging */
+ new_state = PWR_STATE_CHARGE_NEAR_FULL;
+ }
+ break;
+
+ case PWR_STATE_CHARGE_NEAR_FULL:
+ new_state = state_charge(ctx);
+ if (new_state == PWR_STATE_UNCHANGE &&
+ (ctx->curr.batt.state_of_charge <
+ NEAR_FULL_THRESHOLD)) {
+ /* Battery below almost-full threshold. */
+ new_state = PWR_STATE_CHARGE;
+ }
break;
case PWR_STATE_ERROR:
new_state = state_error(ctx);
@@ -648,6 +669,13 @@ void charge_state_machine_task(void)
*/
sleep_usec = POLL_PERIOD_SHORT;
break;
+ case PWR_STATE_CHARGE_NEAR_FULL:
+ /*
+ * Battery is almost charged. The last few percent
+ * take a loooong time, so fall through and look like
+ * we're charged. This mirrors similar hacks at the
+ * ACPI/kernel/UI level.
+ */
case PWR_STATE_IDLE:
batt_flags = *ctx->memmap_batt_flags;
batt_flags &= ~EC_BATT_FLAG_CHARGING;
@@ -659,7 +687,8 @@ void charge_state_machine_task(void)
rv_setled = powerled_set(POWERLED_GREEN);
last_setled_time = get_time().val;
- sleep_usec = POLL_PERIOD_LONG;
+ sleep_usec = (new_state == PWR_STATE_IDLE ?
+ POLL_PERIOD_LONG : POLL_PERIOD_CHARGE);
break;
case PWR_STATE_DISCHARGE:
batt_flags = *ctx->memmap_batt_flags;
diff --git a/include/battery.h b/include/battery.h
index f647a29bc0..02001b763a 100644
--- a/include/battery.h
+++ b/include/battery.h
@@ -16,8 +16,8 @@
/* Stop charge when state of charge reaches this percentage */
#define STOP_CHARGE_THRESHOLD 100
-/* Threshold for power led to turn green */
-#define POWERLED_GREEN_THRESHOLD 90
+/* Tell host we're charged at this percentage */
+#define NEAR_FULL_THRESHOLD 97
/* Precharge only when state of charge is below this level */
#define PRE_CHARGE_THRESHOLD 25
diff --git a/include/charge_state.h b/include/charge_state.h
index 9b4e6d364f..d3b310607e 100644
--- a/include/charge_state.h
+++ b/include/charge_state.h
@@ -48,19 +48,28 @@
/* Power states */
enum power_state {
+ /* Meta-state; unchanged from previous time through task loop */
PWR_STATE_UNCHANGE = 0,
+ /* (Re-)initalizing charge state machine */
PWR_STATE_INIT,
+ /* Just transitioned from init to idle */
PWR_STATE_IDLE0,
+ /* Idle; AC present */
PWR_STATE_IDLE,
+ /* Discharging */
PWR_STATE_DISCHARGE,
+ /* Charging */
PWR_STATE_CHARGE,
+ /* Charging, almost fully charged */
+ PWR_STATE_CHARGE_NEAR_FULL,
+ /* Charging state machine error */
PWR_STATE_ERROR
};
/* Debugging constants, in the same order as enum power_state. This string
* table was moved here to sync with enum above.
*/
-#define POWER_STATE_NAME_TABLE \
+#define POWER_STATE_NAME_TABLE \
{ \
"unchange", \
"init", \
@@ -68,6 +77,7 @@ enum power_state {
"idle", \
"discharge", \
"charge", \
+ "charge_near_full", \
"error" \
}
/* End of POWER_STATE_NAME_TABLE macro */