diff options
author | Daisuke Nojiri <dnojiri@chromium.org> | 2017-09-15 13:43:46 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-09-19 21:46:24 -0700 |
commit | d8612351ea07a406adc998d74d4015da41672c51 (patch) | |
tree | 28ba7734aed644ca5101a1798e53db86e17a1555 | |
parent | 253fe7adc3d07e234ce97b6352bf0ff78fabfd58 (diff) | |
download | chrome-ec-d8612351ea07a406adc998d74d4015da41672c51.tar.gz |
Fizz: Pulse LED
This change makes the power LEDs pulse using PWM.
S0: solid green.
S3: pulsing amber (= mix of green and red)
S5: off
BUG=b:64975836
BRANCH=none
TEST=Verify LED behavior described above on Proto3
Change-Id: I696cf8279dd762236b7b7f000a316820d58916bf
Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/669773
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
-rw-r--r-- | board/fizz/board.c | 10 | ||||
-rw-r--r-- | board/fizz/board.h | 7 | ||||
-rw-r--r-- | board/fizz/ec.tasklist | 1 | ||||
-rw-r--r-- | board/fizz/gpio.inc | 5 | ||||
-rw-r--r-- | board/fizz/led.c | 109 |
5 files changed, 101 insertions, 31 deletions
diff --git a/board/fizz/board.c b/board/fizz/board.c index 0fd6e6dd76..b57a0fa58f 100644 --- a/board/fizz/board.c +++ b/board/fizz/board.c @@ -23,6 +23,7 @@ #include "driver/tcpm/ps8xxx.h" #include "driver/tcpm/tcpci.h" #include "driver/tcpm/tcpm.h" +#include "espi.h" #include "extpower.h" #include "gpio.h" #include "hooks.h" @@ -32,6 +33,8 @@ #include "pi3usb9281.h" #include "power.h" #include "power_button.h" +#include "pwm.h" +#include "pwm_chip.h" #include "spi.h" #include "switch.h" #include "system.h" @@ -44,7 +47,6 @@ #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" -#include "espi.h" #define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) #define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) @@ -461,3 +463,9 @@ int board_has_working_reset_flags(void) /* All other board versions should have working reset flags */ return 1; } + +const struct pwm_t pwm_channels[] = { + [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, + [PWM_CH_LED_GREEN] = { 5, PWM_CONFIG_DSLEEP, 100 }, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/board/fizz/board.h b/board/fizz/board.h index 723df09813..1259dea23d 100644 --- a/board/fizz/board.h +++ b/board/fizz/board.h @@ -31,6 +31,7 @@ #define CONFIG_I2C_MASTER #undef CONFIG_LID_SWITCH #define CONFIG_POWER_BUTTON_IGNORE_LID +#define CONFIG_PWM #define CONFIG_LTO #define CONFIG_CHIP_PANIC_BACKUP #define CONFIG_SPI_FLASH_REGS @@ -206,6 +207,12 @@ enum button { BUTTON_COUNT }; +enum pwm_channel { + PWM_CH_LED_RED, + PWM_CH_LED_GREEN, + PWM_CH_COUNT +}; + /* TODO(crosbug.com/p/61098): Verify the numbers below. */ /* * delay to turn on the power supply max is ~16ms. diff --git a/board/fizz/ec.tasklist b/board/fizz/ec.tasklist index b60ae990a7..58d509ebbd 100644 --- a/board/fizz/ec.tasklist +++ b/board/fizz/ec.tasklist @@ -22,6 +22,7 @@ #define CONFIG_TASK_LIST \ TASK_ALWAYS(HOOKS, hook_task, NULL, 2048) \ + TASK_ALWAYS(LED, led_task, NULL, TASK_STACK_SIZE) \ /* Larger stack for RW verification (i.e. sha256, rsa) */ \ TASK_NOTEST(CHIPSET, chipset_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(PDCMD, pd_command_task, NULL, TASK_STACK_SIZE) \ diff --git a/board/fizz/gpio.inc b/board/fizz/gpio.inc index 4640e3c4da..da1fbcab25 100644 --- a/board/fizz/gpio.inc +++ b/board/fizz/gpio.inc @@ -44,8 +44,6 @@ GPIO(PMIC_INT_L, PIN(6, 0), GPIO_INPUT) /* PMIC interrupt */ /* Fizz specific pins */ GPIO(LAN_PWR_EN, PIN(8, 3), GPIO_OUT_HIGH) /* Ethernet power enabled */ -GPIO(PWR_RED_LED, PIN(8, 0), GPIO_OUT_HIGH) /* Power Red LED */ -GPIO(PWR_GRN_LED, PIN(B, 7), GPIO_OUT_HIGH) /* Power Green LED */ /* TODO(crosbug.com/p/61098): Make use of these GPIOs */ GPIO(PP3300_USB_PD, PIN(6, 7), GPIO_OUTPUT) @@ -104,3 +102,6 @@ ALTERNATE(PIN_MASK(9, 0x06), 1, MODULE_I2C, 0) /* GPIO91-92 */ /* EC_I2C2_PMIC ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* GPIOB4-B5 */ /* EC_I2C0_0_USBC_3V3_SDA/SCL */ ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* GPOPB2-B3 */ /* EC_I2C0_1_3V3_SDA/SCL */ ALTERNATE(PIN_MASK(D, 0x03), 1, MODULE_I2C, 0) /* GPIOD0-D1 */ /* EC_I2C3_SENSOR_1V8_SDA/SCL */ +/* Alternate functions for LED PWM */ +ALTERNATE(PIN_MASK(8, 0x01), 1, MODULE_PWM, 0) /* GPIO80 PWM3 Red*/ +ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* GPOB7 PWM5 Green*/ diff --git a/board/fizz/led.c b/board/fizz/led.c index e6f336968a..0227f8498f 100644 --- a/board/fizz/led.c +++ b/board/fizz/led.c @@ -11,6 +11,8 @@ #include "gpio.h" #include "hooks.h" #include "led_common.h" +#include "pwm.h" +#include "timer.h" #include "util.h" static int led_debug; @@ -25,11 +27,14 @@ enum led_color { LED_COLOR_COUNT }; -static int led_set_color_power(enum led_color color) +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; @@ -47,49 +52,93 @@ static int led_set_color_power(enum led_color color) return EC_ERROR_UNKNOWN; } - gpio_set_level(GPIO_PWR_GRN_LED, green); - gpio_set_level(GPIO_PWR_RED_LED, red); + 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 led_set_color(enum ec_led_id id, enum led_color color) +static int set_color(enum ec_led_id id, enum led_color color, int duty) { switch (id) { case EC_LED_ID_POWER_LED: - return led_set_color_power(color); + return set_color_power(color, duty); default: return EC_ERROR_UNKNOWN; } } +/* led task increments brightness by <duty_inc> every <task_frequency_us> to go + * from 0% to 100% in <LED_PULSE_US>. Then it decreases brightness likewise in + * <LED_PULSE_US>. So, total time for one cycle is <LED_PULSE_US> x 2. */ +#define LED_PULSE_US (2 * SECOND) +static uint32_t task_frequency_us; +static int duty_inc; + +static void set_task_frequency(uint32_t usec) +{ + task_frequency_us = usec; + duty_inc = 100 / (LED_PULSE_US / task_frequency_us); +} + static void led_set_power(void) { - static uint8_t suspend_ticks; + static int duty = 0; if (chipset_in_state(CHIPSET_STATE_ON)) - led_set_color(EC_LED_ID_POWER_LED, LED_GREEN); + set_color(EC_LED_ID_POWER_LED, LED_GREEN, 100); else if (chipset_in_state( CHIPSET_STATE_SUSPEND | CHIPSET_STATE_STANDBY)) - /* Blink once every four seconds. */ - led_set_color(EC_LED_ID_POWER_LED, - (suspend_ticks % 4) ? LED_OFF : LED_GREEN); + set_color(EC_LED_ID_POWER_LED, LED_AMBER, duty); else - led_set_color(EC_LED_ID_POWER_LED, LED_OFF); + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); - suspend_ticks++; + if (duty + duty_inc > 100) + duty_inc = duty_inc * -1; + else if (duty + duty_inc < 0) + duty_inc = duty_inc * -1; + duty += duty_inc; } -/** - * Called by hook task every 250 ms - */ -static void led_tick(void) +void led_task(void *u) +{ + uint32_t interval; + uint32_t start; + + while (1) { + start = get_time().le.lo; + if (!led_debug) + led_set_power(); + interval = get_time().le.lo - start; + if (task_frequency_us > interval) + usleep(task_frequency_us - interval); + } +} + +static void led_init(void) { - if (led_debug) - return; - led_set_power(); + /* + * 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); + + /* 40 msec for nice and smooth transition */ + set_task_frequency(40 * MSEC); + + /* From users' perspective, system-on means AP-on */ + set_color(EC_LED_ID_POWER_LED, LED_OFF, 0); } -DECLARE_HOOK(HOOK_SECOND, led_tick, HOOK_PRIO_DEFAULT); +/* After pwm_pin_init() */ +DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_DEFAULT); static int command_led(int argc, char **argv) { @@ -102,19 +151,23 @@ static int command_led(int argc, char **argv) led_debug ^= 1; ccprintf("led_debug %s\n", led_debug ? "on" : "off"); } else if (!strcasecmp(argv[1], "off")) { - led_set_color(id, LED_OFF); + set_color(id, LED_OFF, 0); } else if (!strcasecmp(argv[1], "red")) { - led_set_color(id, LED_RED); + set_color(id, LED_RED, 100); } else if (!strcasecmp(argv[1], "green")) { - led_set_color(id, LED_GREEN); + set_color(id, LED_GREEN, 100); } else if (!strcasecmp(argv[1], "amber")) { - led_set_color(id, LED_AMBER); + set_color(id, LED_AMBER, 100); } else { - /* maybe handle charger_discharge_on_ac() too? */ - return EC_ERROR_PARAM1; + char *e; + uint32_t msec = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM1; + set_task_frequency(msec * MSEC); } return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(led, command_led, - "[debug|red|green|amber|off]", - "Turn on/off LED"); + "[debug|red|green|amber|off|num]", + "Turn on/off LED. If a number is given, it changes led" + "task frequency (msec)."); |