summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-03-14 12:39:00 -0700
committerChromeBot <chrome-bot@google.com>2013-03-14 15:44:14 -0700
commit75acd4065ab720cdb72c165aa2d3b3e48852267a (patch)
tree75d5a6da1d374cab94f2786e91891c377ffdbd66
parent10d845eb10e4a7030815c687b13bbd09e905edb8 (diff)
downloadchrome-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.c55
-rw-r--r--common/power_led.c74
-rw-r--r--include/charge_state.h9
-rw-r--r--include/power_led.h29
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 {