summaryrefslogtreecommitdiff
path: root/common/charge_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/charge_state.c')
-rw-r--r--common/charge_state.c33
1 files changed, 31 insertions, 2 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;