diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-03-14 12:39:00 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-03-14 15:44:14 -0700 |
commit | 75acd4065ab720cdb72c165aa2d3b3e48852267a (patch) | |
tree | 75d5a6da1d374cab94f2786e91891c377ffdbd66 | |
parent | 10d845eb10e4a7030815c687b13bbd09e905edb8 (diff) | |
download | chrome-ec-75acd4065ab720cdb72c165aa2d3b3e48852267a.tar.gz |
Clean up power LED state machine on link
The power LED now has its own tick-based handler which knows how to
blink the LED and resend the desired LED state to work around the
flaky 1-wire connection.
Removes a bunch of LED state code from charge_state.c.
No user-visible impact. Does not need to go into link branch.
BUG=chromium-os:18256
BRANCH=none
TEST=manual
1) Discharge battery to <97%
2) Plug in AC. LED=yellow
3) 'ectool chargeforceidle 1' from root shell. LED=blinking green/off.
4) 'ectool chargeforceidle 0' from root shell. LED=yellow.
5) Wait for battery >= 97% (or 'battfake 98' from EC console). LED=green.
6) Unplug battery. LED=red (may take 10 sec).
7) Replug battery. LED=green.
Change-Id: I999ee3e1abe269bb3f737bbc75e0b872316605ce
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/45469
Reviewed-by: Vic Yang <victoryang@chromium.org>
-rw-r--r-- | common/charge_state.c | 55 | ||||
-rw-r--r-- | common/power_led.c | 74 | ||||
-rw-r--r-- | include/charge_state.h | 9 | ||||
-rw-r--r-- | include/power_led.h | 29 |
4 files changed, 91 insertions, 76 deletions
diff --git a/common/charge_state.c b/common/charge_state.c index 5cbea09aa6..8c93595d15 100644 --- a/common/charge_state.c +++ b/common/charge_state.c @@ -15,7 +15,6 @@ #include "gpio.h" #include "hooks.h" #include "host_command.h" -#include "power_led.h" #include "printf.h" #include "smart_battery.h" #include "switch.h" @@ -31,9 +30,6 @@ /* Voltage debounce time */ #define DEBOUNCE_TIME (10 * SECOND) -/* Time period between setting power LED */ -#define SET_LED_PERIOD (10 * SECOND) - /* Timeout after AP battery shutdown warning before we kill the AP */ #define LOW_BATTERY_SHUTDOWN_TIMEOUT_US (30 * SECOND) @@ -577,6 +573,16 @@ enum power_state charge_get_state(void) return task_ctx.curr.state; } +uint32_t charge_get_flags(void) +{ + uint32_t flags = 0; + + if (state_machine_force_idle) + flags |= CHARGE_FLAG_FORCE_IDLE; + + return flags; +} + int charge_get_percent(void) { return task_ctx.curr.batt.state_of_charge; @@ -603,18 +609,6 @@ static int exit_force_idle_mode(void) return EC_SUCCESS; } -static enum powerled_color force_idle_led_blink(void) -{ - static enum powerled_color last = POWERLED_GREEN; - - if (last == POWERLED_GREEN) - last = POWERLED_OFF; - else - last = POWERLED_GREEN; - - return last; -} - /** * Battery charging task */ @@ -625,9 +619,6 @@ void charge_state_machine_task(void) int sleep_usec = POLL_PERIOD_SHORT, diff_usec, sleep_next; enum power_state new_state; uint8_t batt_flags; - enum powerled_color led_color = POWERLED_OFF; - int rv_setled = 0; - uint64_t last_setled_time = 0; while (1) { state_common(ctx); @@ -724,10 +715,6 @@ void charge_state_machine_task(void) *ctx->memmap_batt_flags = batt_flags; /* Charge done */ - led_color = POWERLED_GREEN; - rv_setled = powerled_set(POWERLED_GREEN); - last_setled_time = get_time().val; - sleep_usec = (new_state == PWR_STATE_IDLE ? POLL_PERIOD_LONG : POLL_PERIOD_CHARGE); break; @@ -745,36 +732,14 @@ void charge_state_machine_task(void) *ctx->memmap_batt_flags = batt_flags; /* Charging */ - led_color = POWERLED_YELLOW; - rv_setled = powerled_set(POWERLED_YELLOW); - last_setled_time = get_time().val; - sleep_usec = POLL_PERIOD_CHARGE; break; case PWR_STATE_ERROR: /* Error */ - led_color = POWERLED_RED; - rv_setled = powerled_set(POWERLED_RED); - last_setled_time = get_time().val; - sleep_usec = POLL_PERIOD_CHARGE; break; case PWR_STATE_UNCHANGE: /* Don't change sleep duration */ - if (state_machine_force_idle) - powerled_set(force_idle_led_blink()); - else if (rv_setled || get_time().val - last_setled_time - > SET_LED_PERIOD) { - /* - * Power LED may go off if AC adapter is - * partially removed, even though AC power is - * still provided. Update the power LED - * periodically so it will come back on in this - * case. - */ - rv_setled = powerled_set(led_color); - last_setled_time = get_time().val; - } break; default: /* Other state; poll quickly and hope it goes away */ diff --git a/common/power_led.c b/common/power_led.c index 1e4b89505b..25af303421 100644 --- a/common/power_led.c +++ b/common/power_led.c @@ -1,18 +1,28 @@ -/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Power LED control for Chrome EC */ +#include "charge_state.h" #include "console.h" +#include "hooks.h" #include "onewire.h" -#include "power_led.h" +#include "switch.h" #include "timer.h" #include "util.h" #define POWERLED_RETRIES 10 +enum powerled_color { + POWERLED_OFF = 0, + POWERLED_RED, + POWERLED_YELLOW, + POWERLED_GREEN, + POWERLED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + static const uint8_t led_masks[POWERLED_COLOR_COUNT] = {0xff, 0xfe, 0xfc, 0xfd}; static const char * const color_names[POWERLED_COLOR_COUNT] = { "off", "red", "yellow", "green"}; @@ -50,7 +60,7 @@ static int powerled_set_mask(int mask) return EC_SUCCESS; } -int powerled_set(enum powerled_color color) +static int powerled_set(enum powerled_color color) { int rv = EC_SUCCESS; int i; @@ -79,6 +89,64 @@ int powerled_set(enum powerled_color color) } /*****************************************************************************/ +/* Hooks */ + +static void powerled_tick(void) +{ + static enum powerled_color current_color = POWERLED_COLOR_COUNT; + static int tick_count; + enum powerled_color new_color = POWERLED_OFF; + + tick_count++; + + if (!switch_get_ac_present()) { + /* AC isn't present, so the power LED on the AC plug is off */ + current_color = POWERLED_OFF; + return; + } + + /* Translate charge state to LED color */ + switch (charge_get_state()) { + case PWR_STATE_IDLE: + if (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE) + new_color = ((tick_count & 1) ? + POWERLED_GREEN : POWERLED_OFF); + else + new_color = POWERLED_GREEN; + break; + case PWR_STATE_CHARGE: + new_color = POWERLED_YELLOW; + break; + case PWR_STATE_CHARGE_NEAR_FULL: + new_color = POWERLED_GREEN; + break; + case PWR_STATE_ERROR: + new_color = POWERLED_RED; + break; + default: + /* Other states don't change LED color */ + break; + } + + /* + * The power adapter on link can partially unplug and lose its LED + * state. There's no way to detect this, so just assume it forgets its + * state every 10 seconds. + */ + if (!(tick_count % 10)) + current_color = POWERLED_COLOR_COUNT; + + /* If current color is still correct, leave now */ + if (new_color == current_color) + return; + + /* Update LED */ + if (!powerled_set(new_color)) + current_color = new_color; +} +DECLARE_HOOK(HOOK_SECOND, powerled_tick, HOOK_PRIO_DEFAULT); + +/*****************************************************************************/ /* Console commands */ static int command_powerled(int argc, char **argv) diff --git a/include/charge_state.h b/include/charge_state.h index fcb68be89d..bf6404593e 100644 --- a/include/charge_state.h +++ b/include/charge_state.h @@ -62,6 +62,10 @@ enum power_state { PWR_STATE_ERROR }; +/* Charge state flags */ +/* Forcing idle state */ +#define CHARGE_FLAG_FORCE_IDLE (1 << 0) + /* Debugging constants, in the same order as enum power_state. This string * table was moved here to sync with enum above. */ @@ -128,6 +132,11 @@ enum power_state trickle_charge(struct power_state_context *ctx); enum power_state charge_get_state(void); /** + * Return current charge state flags (CHARGE_FLAG_*) + */ +uint32_t charge_get_flags(void); + +/** * Return current battery charge percentage. */ int charge_get_percent(void); diff --git a/include/power_led.h b/include/power_led.h index 2fd7322095..20b3f7793f 100644 --- a/include/power_led.h +++ b/include/power_led.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,33 +10,6 @@ #include "common.h" -/* Interface for LM4-based boards */ - -enum powerled_color { - POWERLED_OFF = 0, - POWERLED_RED, - POWERLED_YELLOW, - POWERLED_GREEN, - POWERLED_COLOR_COUNT /* Number of colors, not a color itself */ -}; - -#ifdef CONFIG_POWER_LED - -/** - * Set the power adapter LED - * - * @param color Color to set LED - * - * @return EC_SUCCESS, or non-zero if error. - */ -int powerled_set(enum powerled_color color); - -#else - -static inline int powerled_set(enum powerled_color color) { return 0; } - -#endif - /* Interface for STM32-based boards */ enum powerled_state { |