From c8e38a9314d10fa5984e80869d26aef334769645 Mon Sep 17 00:00:00 2001 From: Wonjoon Lee Date: Thu, 28 Apr 2016 14:39:31 +0900 Subject: kevin: Add support 3 color LED When system on .always blue When system is off .discharging : off .charging : red .full-charged : green Error : red - green switching BUG=None TEST=See LED behavier on kevin Change-Id: I93f0dbb503c68999825c455c8dc81b6bdaf397b4 Signed-off-by: Wonjoon Lee Reviewed-on: https://chromium-review.googlesource.com/341113 Reviewed-by: Shawn N --- board/kevin/board.c | 6 +- board/kevin/board.h | 7 ++- board/kevin/build.mk | 2 +- board/kevin/gpio.inc | 6 +- board/kevin/led.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 182 insertions(+), 10 deletions(-) create mode 100644 board/kevin/led.c diff --git a/board/kevin/board.c b/board/kevin/board.c index 059055a84b..2beb74ea81 100644 --- a/board/kevin/board.c +++ b/board/kevin/board.c @@ -68,10 +68,10 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_FULL_LED] = { 0, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_GREEN] = { 0, PWM_CONFIG_DSLEEP, 100 }, [PWM_CH_BKLIGHT] = { 2, 0, 10000 }, - [PWM_CH_CHG_LED] = { 3, PWM_CONFIG_DSLEEP, 100 }, - [PWM_CH_PWR_LED] = { 4, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_BLUE] = { 4, PWM_CONFIG_DSLEEP, 100 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/board/kevin/board.h b/board/kevin/board.h index 08408d24b9..a450316f30 100644 --- a/board/kevin/board.h +++ b/board/kevin/board.h @@ -14,6 +14,7 @@ #define CONFIG_HOSTCMD_SPS #define CONFIG_POWER_COMMON #define CONFIG_PWM +#define CONFIG_LED_COMMON #define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */ @@ -111,10 +112,10 @@ enum adc_channel { }; enum pwm_channel { - PWM_CH_FULL_LED, + PWM_CH_LED_GREEN, PWM_CH_BKLIGHT, - PWM_CH_CHG_LED, - PWM_CH_PWR_LED, + PWM_CH_LED_RED, + PWM_CH_LED_BLUE, /* Number of PWM channels */ PWM_CH_COUNT }; diff --git a/board/kevin/build.mk b/board/kevin/build.mk index 7c7ca73c7f..ef4fa6e4f0 100644 --- a/board/kevin/build.mk +++ b/board/kevin/build.mk @@ -11,5 +11,5 @@ CHIP:=npcx CHIP_VARIANT:=npcx5m5g board-y=battery.o -board-y+=board.o +board-y+=board.o led.o board-y+=usb_pd_policy.o diff --git a/board/kevin/gpio.inc b/board/kevin/gpio.inc index b280bfb679..d93b4d92d6 100644 --- a/board/kevin/gpio.inc +++ b/board/kevin/gpio.inc @@ -127,11 +127,11 @@ ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C3SDA/I2C3SCL GPIOD0/D1 */ ALTERNATE(PIN_MASK(D, 0x03), 1, MODULE_I2C, 0) -/* PWM0 / LED_FULL PWM2 / BLPWM */ +/* PWM0 / LED_GREEN(net LED_ACIN), PWM2 / BLPWM */ ALTERNATE(PIN_MASK(C, 0x18), 1, MODULE_PWM, 0) -/* PWM3 / CHGLED */ +/* PWM3 / LED_RED(net LED_CHARGE) */ ALTERNATE(PIN_MASK(8, 0x01), 1, MODULE_PWM, 0) -/* PWM4 / PWRLED */ +/* PWM4 / LED_BLUE(net LED_POWER) */ ALTERNATE(PIN_MASK(B, 0x40), 1, MODULE_PWM, 0) /* CR_SIN/SOUT GPIO64/65 */ ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, GPIO_PULL_UP) diff --git a/board/kevin/led.c b/board/kevin/led.c new file mode 100644 index 0000000000..a3a10935a7 --- /dev/null +++ b/board/kevin/led.c @@ -0,0 +1,171 @@ +/* Copyright 2016 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/Battery LED control for Kevin + */ + +#include "charge_state.h" +#include "chipset.h" +#include "console.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "registers.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_PWM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_PWM, format, ## args) + +#define LED_TOTAL_TICKS 16 +#define LED_ON_TICKS 8 + +static int led_debug; + +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_BLUE, + + /* Number of colors, not a color itself */ + LED_COLOR_COUNT +}; + +/* Brightness vs. color, in the order of off, red, green and blue */ +static const uint8_t color_brightness[LED_COLOR_COUNT][3] = { + /* {Red, Blue, Green}, */ + [LED_OFF] = {100, 100, 100}, + [LED_RED] = {90, 100, 100}, + [LED_GREEN] = {100, 100, 80}, + [LED_BLUE] = {100, 80, 100}, +}; + +/** + * Set LED color + * + * @param color Enumerated color value + */ +static void set_color(enum led_color color) +{ + pwm_set_duty(PWM_CH_LED_RED, color_brightness[color][0]); + pwm_set_duty(PWM_CH_LED_BLUE, color_brightness[color][1]); + pwm_set_duty(PWM_CH_LED_GREEN, color_brightness[color][2]); +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + brightness_range[EC_LED_COLOR_RED] = 100; + brightness_range[EC_LED_COLOR_BLUE] = 100; + brightness_range[EC_LED_COLOR_GREEN] = 100; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + pwm_set_duty(PWM_CH_LED_RED, brightness[EC_LED_COLOR_RED]); + pwm_set_duty(PWM_CH_LED_BLUE, brightness[EC_LED_COLOR_BLUE]); + pwm_set_duty(PWM_CH_LED_GREEN, brightness[EC_LED_COLOR_GREEN]); + return EC_SUCCESS; +} + +static void kevin_led_set_power_battery(void) +{ + static int power_ticks; + + if (chipset_in_state(CHIPSET_STATE_ON)) { + set_color(LED_BLUE); + return; + } + + /* CHIPSET_STATE_OFF */ + switch (charge_get_state()) { + case PWR_STATE_DISCHARGE: + set_color(LED_OFF); + break; + case PWR_STATE_CHARGE: + set_color(LED_RED); + break; + case PWR_STATE_ERROR: + power_ticks++; + set_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. */ + set_color(LED_GREEN); + break; + default: + set_color(LED_RED); + break; + } + if ((charge_get_state()) != PWR_STATE_ERROR) + power_ticks = 0; +} + +static void led_init(void) +{ + /* + * Enable PWMs and set to 0% duty cycle. If they're disabled, + * seems to ground the pins instead of letting them float. + */ + pwm_enable(PWM_CH_LED_RED, 1); + pwm_enable(PWM_CH_LED_GREEN, 1); + pwm_enable(PWM_CH_LED_BLUE, 1); + + set_color(LED_OFF); +} +/* After pwm_pin_init() */ +DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_INIT_PWM + 2); + +/** + * Called by hook task every 250 ms + */ +static void led_tick(void) +{ + if (led_debug) + return; + + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED) && + led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { + kevin_led_set_power_battery(); + return; + } + + set_color(LED_OFF); +} +DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); + +/******************************************************************/ +/* Console commands */ +static int command_led_color(int argc, char **argv) +{ + if (argc > 1) { + if (!strcasecmp(argv[1], "debug")) { + led_debug ^= 1; + CPRINTF("led_debug = %d\n", led_debug); + } else if (!strcasecmp(argv[1], "off")) { + set_color(LED_OFF); + } else if (!strcasecmp(argv[1], "red")) { + set_color(LED_RED); + } else if (!strcasecmp(argv[1], "green")) { + set_color(LED_GREEN); + } else if (!strcasecmp(argv[1], "blue")) { + set_color(LED_BLUE); + } else { + /* maybe handle charger_discharge_on_ac() too? */ + return EC_ERROR_PARAM1; + } + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(ledcolor, command_led_color, + "[debug|red|green|blue|off]", + "Change LED color", + NULL); -- cgit v1.2.1