summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2017-09-15 13:43:46 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-09-19 21:46:24 -0700
commitd8612351ea07a406adc998d74d4015da41672c51 (patch)
tree28ba7734aed644ca5101a1798e53db86e17a1555
parent253fe7adc3d07e234ce97b6352bf0ff78fabfd58 (diff)
downloadchrome-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.c10
-rw-r--r--board/fizz/board.h7
-rw-r--r--board/fizz/ec.tasklist1
-rw-r--r--board/fizz/gpio.inc5
-rw-r--r--board/fizz/led.c109
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).");