summaryrefslogtreecommitdiff
path: root/board/nami/led.c
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2017-12-16 14:55:03 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-12-27 15:32:03 -0800
commit137a0e850aa5b598864a8b02bf9777415d892047 (patch)
treee89b038a010e7d7e8f844425a7432f0b3ad494e0 /board/nami/led.c
parent1c87ad4153488512792e6b7898408126111727cf (diff)
downloadchrome-ec-137a0e850aa5b598864a8b02bf9777415d892047.tar.gz
Nami: Derive board files from Nautilus
BUG=b:70157960 BRANCH=none TEST=make buildall Change-Id: Iecbca185a3575818892f66f988ad36b0b175f317 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>
Diffstat (limited to 'board/nami/led.c')
-rw-r--r--board/nami/led.c273
1 files changed, 87 insertions, 186 deletions
diff --git a/board/nami/led.c b/board/nami/led.c
index 9b6942d241..6b92ab6992 100644
--- a/board/nami/led.c
+++ b/board/nami/led.c
@@ -2,231 +2,132 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
- * Power and battery LED control for Fizz
+ * Power and battery LED control.
*/
+#include "battery.h"
+#include "charge_manager.h"
+#include "charge_state.h"
#include "chipset.h"
-#include "console.h"
#include "ec_commands.h"
#include "gpio.h"
#include "hooks.h"
+#include "host_command.h"
#include "led_common.h"
-#include "pwm.h"
-#include "timer.h"
+#include "system.h"
#include "util.h"
-const enum ec_led_id supported_led_ids[] = {EC_LED_ID_POWER_LED};
+#define BAT_LED_ON 1
+#define BAT_LED_OFF 0
+
+#define LED_TOTAL_TICKS 16
+#define LED_ON_TICKS 8
+
+const enum ec_led_id supported_led_ids[] = {
+ EC_LED_ID_POWER_LED,
+ EC_LED_ID_BATTERY_LED};
+
const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids);
enum led_color {
LED_OFF = 0,
LED_RED,
LED_GREEN,
- LED_AMBER,
+ LED_BLUE,
/* Number of colors, not a color itself */
LED_COLOR_COUNT
};
-static int set_color_power(enum led_color color, int duty)
-{
- int green = 0;
- int red = 0;
-
- if (duty < 0 || 100 < duty)
- return EC_ERROR_UNKNOWN;
-
- switch (color) {
- case LED_OFF:
- break;
- case LED_GREEN:
- green = 1;
- break;
- case LED_RED:
- red = 1;
- break;
- case LED_AMBER:
- green = 1;
- red = 1;
- break;
- default:
- return EC_ERROR_UNKNOWN;
- }
-
- if (red)
- pwm_set_duty(PWM_CH_LED_RED, duty);
- else
- pwm_set_duty(PWM_CH_LED_RED, 0);
-
- if (green)
- pwm_set_duty(PWM_CH_LED_GREEN, duty);
- else
- pwm_set_duty(PWM_CH_LED_GREEN, 0);
-
- return EC_SUCCESS;
-}
-
-static int set_color(enum ec_led_id id, enum led_color color, int duty)
+/**
+ * Set LED color
+ *
+ * @param color Enumerated color value
+ */
+static void set_color(enum led_color color)
{
- switch (id) {
- case EC_LED_ID_POWER_LED:
- return set_color_power(color, duty);
- default:
- return EC_ERROR_UNKNOWN;
- }
+ gpio_set_level(GPIO_POWER_LED, !(color == LED_BLUE));
+ gpio_set_level(GPIO_LED_ACIN, !(color == LED_GREEN));
+ gpio_set_level(GPIO_LED_CHARGE, !(color == LED_RED));
}
-#define LED_PULSE_US (2 * SECOND)
-/* 40 msec for nice and smooth transition. */
-#define LED_PULSE_TICK_US (40 * MSEC)
-
-/* When pulsing is enabled, brightness is incremented by <duty_inc> every
- * <interval> usec from 0 to 100% in LED_PULSE_US usec. Then it's decremented
- * likewise in LED_PULSE_US usec. */
-static struct {
- uint32_t interval;
- int duty_inc;
- enum led_color color;
- int duty;
-} led_pulse;
-
-#define CONFIG_TICK(interval, color) \
- config_tick((interval), 100 / (LED_PULSE_US / (interval)), (color))
-
-static void config_tick(uint32_t interval, int duty_inc, enum led_color color)
+void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range)
{
- led_pulse.interval = interval;
- led_pulse.duty_inc = duty_inc;
- led_pulse.color = color;
- led_pulse.duty = 0;
+ brightness_range[EC_LED_COLOR_RED] = 1;
+ brightness_range[EC_LED_COLOR_BLUE] = 1;
+ brightness_range[EC_LED_COLOR_GREEN] = 1;
}
-static void pulse_power_led(enum led_color color)
+int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness)
{
- set_color(EC_LED_ID_POWER_LED, color, led_pulse.duty);
- if (led_pulse.duty + led_pulse.duty_inc > 100)
- led_pulse.duty_inc = led_pulse.duty_inc * -1;
- else if (led_pulse.duty + led_pulse.duty_inc < 0)
- led_pulse.duty_inc = led_pulse.duty_inc * -1;
- led_pulse.duty += led_pulse.duty_inc;
-}
+ gpio_set_level(GPIO_POWER_LED, !brightness[EC_LED_COLOR_BLUE]);
+ gpio_set_level(GPIO_LED_ACIN, !brightness[EC_LED_COLOR_GREEN]);
+ gpio_set_level(GPIO_LED_CHARGE, !brightness[EC_LED_COLOR_RED]);
-static void led_tick(void);
-DECLARE_DEFERRED(led_tick);
-static void led_tick(void)
-{
- uint32_t elapsed;
- uint32_t next = 0;
- uint32_t start = get_time().le.lo;
- static uint8_t pwm_enabled = 0;
-
- if (!pwm_enabled) {
- pwm_enable(PWM_CH_LED_RED, 1);
- pwm_enable(PWM_CH_LED_GREEN, 1);
- pwm_enabled = 1;
- }
- if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
- pulse_power_led(led_pulse.color);
- elapsed = get_time().le.lo - start;
- next = led_pulse.interval > elapsed ? led_pulse.interval - elapsed : 0;
- hook_call_deferred(&led_tick_data, next);
+ return EC_SUCCESS;
}
-static void led_suspend(void)
-{
- CONFIG_TICK(LED_PULSE_TICK_US, LED_GREEN);
- led_tick();
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, led_suspend, HOOK_PRIO_DEFAULT);
-static void led_shutdown(void)
+static void nautilus_led_set_power_battery(void)
{
- hook_call_deferred(&led_tick_data, -1);
- if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
- set_color(EC_LED_ID_POWER_LED, LED_OFF, 0);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, led_shutdown, HOOK_PRIO_DEFAULT);
+ static unsigned int power_ticks;
+ enum led_color cur_led_color = LED_RED;
+ enum charge_state chg_state = charge_get_state();
+ int charge_percent = charge_get_percent();
+
+ if (chipset_in_state(CHIPSET_STATE_ON)) {
+ set_color(LED_BLUE);
+ return;
+ }
-static void led_resume(void)
-{
- /* Assume there is no race condition with led_tick, which also
- * runs in hook_task. */
- hook_call_deferred(&led_tick_data, -1);
- if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
- set_color(EC_LED_ID_POWER_LED, LED_GREEN, 100);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, led_resume, HOOK_PRIO_DEFAULT);
+ /* Flash red on critical battery, which usually inhibits AP power-on. */
+ if (battery_is_present() != BP_YES ||
+ charge_percent < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) {
+ set_color(((power_ticks++ % LED_TOTAL_TICKS) < LED_ON_TICKS) ?
+ LED_RED : LED_OFF);
+ return;
+ }
-void led_alert(int enable)
-{
- if (enable) {
- /* Overwrite the current signal */
- config_tick(1 * SECOND, 100, LED_RED);
- led_tick();
- } else {
- /* Restore the previous signal */
- if (chipset_in_state(CHIPSET_STATE_ON))
- led_resume();
- else if (chipset_in_state(CHIPSET_STATE_SUSPEND))
- led_suspend();
- else if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
- led_shutdown();
+ /* CHIPSET_STATE_OFF */
+ switch (chg_state) {
+ case PWR_STATE_DISCHARGE:
+ if ((charge_get_flags() & CHARGE_FLAG_EXTERNAL_POWER) &&
+ charge_percent >= BATTERY_LEVEL_NEAR_FULL)
+ cur_led_color = LED_GREEN;
+ else
+ cur_led_color = LED_OFF;
+ break;
+ case PWR_STATE_CHARGE:
+ cur_led_color = LED_RED;
+ break;
+ case PWR_STATE_ERROR:
+ cur_led_color = ((power_ticks++ % LED_TOTAL_TICKS)
+ < LED_ON_TICKS) ? LED_RED : LED_GREEN;
+ break;
+ case PWR_STATE_CHARGE_NEAR_FULL:
+ case PWR_STATE_IDLE: /* External power connected in IDLE. */
+ cur_led_color = LED_GREEN;
+ break;
+ default:
+ cur_led_color = LED_RED;
+ break;
}
-}
-void led_critical(void)
-{
- hook_call_deferred(&led_tick_data, -1);
- if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED))
- set_color(EC_LED_ID_POWER_LED, LED_RED, 100);
-}
+ set_color(cur_led_color);
-static int command_led(int argc, char **argv)
-{
- enum ec_led_id id = EC_LED_ID_POWER_LED;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- if (!strcasecmp(argv[1], "debug")) {
- led_auto_control(id, !led_auto_control_is_enabled(id));
- ccprintf("o%s\n", led_auto_control_is_enabled(id) ? "ff" : "n");
- } else if (!strcasecmp(argv[1], "off")) {
- set_color(id, LED_OFF, 0);
- } else if (!strcasecmp(argv[1], "red")) {
- set_color(id, LED_RED, 100);
- } else if (!strcasecmp(argv[1], "green")) {
- set_color(id, LED_GREEN, 100);
- } else if (!strcasecmp(argv[1], "amber")) {
- set_color(id, LED_AMBER, 100);
- } else if (!strcasecmp(argv[1], "alert")) {
- led_alert(1);
- } else if (!strcasecmp(argv[1], "crit")) {
- led_critical();
- } else {
- return EC_ERROR_PARAM1;
- }
- return EC_SUCCESS;
+ if (chg_state != PWR_STATE_ERROR)
+ power_ticks = 0;
}
-DECLARE_CONSOLE_COMMAND(led, command_led,
- "[debug|red|green|amber|off|alert|crit]",
- "Turn on/off LED.");
-void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range)
+/**
+ * Called by hook task every 250 ms
+ */
+static void led_tick(void)
{
- brightness_range[EC_LED_COLOR_RED] = 100;
- brightness_range[EC_LED_COLOR_GREEN] = 100;
- brightness_range[EC_LED_COLOR_AMBER] = 100;
+ if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED) &&
+ led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) {
+ nautilus_led_set_power_battery();
+ }
}
-int led_set_brightness(enum ec_led_id id, const uint8_t *brightness)
-{
- if (brightness[EC_LED_COLOR_RED])
- return set_color(id, LED_RED, brightness[EC_LED_COLOR_RED]);
- else if (brightness[EC_LED_COLOR_GREEN])
- return set_color(id, LED_GREEN, brightness[EC_LED_COLOR_GREEN]);
- else if (brightness[EC_LED_COLOR_AMBER])
- return set_color(id, LED_AMBER, brightness[EC_LED_COLOR_AMBER]);
- else
- return set_color(id, LED_OFF, 0);
-}
+DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT);