diff options
author | Ting Shen <phoenixshen@google.com> | 2019-10-30 16:23:14 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-12-27 08:52:16 +0000 |
commit | 8893119c6fab824abef7e38a2a902fbf5f6f353f (patch) | |
tree | d4a30d92476fd3be8b1ea1486e16539c02f406bb | |
parent | d15356206765437a27bc975c46175b055ff25af7 (diff) | |
download | chrome-ec-8893119c6fab824abef7e38a2a902fbf5f6f353f.tar.gz |
jacuzzi: enable led
Implemented pwm module using it8801, and enable led_pwm on jacuzzi.
BUG=b:135086465
TEST=1) verify the led status looks good (full=green, charging=blue)
2) enable CONFIG_CMD_LEDTEST and verify the color settings looks
good.
BRANCH=none
Change-Id: Ifa682473c02fec98ae026e2502df775505d614d7
Signed-off-by: Ting Shen <phoenixshen@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1892381
Reviewed-by: Eric Yilun Lin <yllin@chromium.org>
Tested-by: Ting Shen <phoenixshen@chromium.org>
Commit-Queue: Ting Shen <phoenixshen@chromium.org>
-rw-r--r-- | board/jacuzzi/board.c | 10 | ||||
-rw-r--r-- | board/jacuzzi/board.h | 15 | ||||
-rw-r--r-- | board/jacuzzi/build.mk | 2 | ||||
-rw-r--r-- | board/jacuzzi/led.c | 67 | ||||
-rw-r--r-- | driver/ioexpander/it8801.c | 86 | ||||
-rw-r--r-- | driver/ioexpander/it8801.h | 60 | ||||
-rw-r--r-- | include/config.h | 5 |
7 files changed, 238 insertions, 7 deletions
diff --git a/board/jacuzzi/board.c b/board/jacuzzi/board.c index 49bd9e191c..0626e97b37 100644 --- a/board/jacuzzi/board.c +++ b/board/jacuzzi/board.c @@ -32,8 +32,6 @@ #include "lid_switch.h" #include "power.h" #include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" #include "registers.h" #include "spi.h" #include "system.h" @@ -114,6 +112,14 @@ const struct pi3usb9201_config_t pi3usb9201_bc12_chips[] = { }; /******************************************************************************/ +const struct it8801_pwm_t it8801_pwm_channels[] = { + [PWM_CH_LED_RED] = { 1 }, + [PWM_CH_LED_GREEN] = { 2 }, + [PWM_CH_LED_BLUE] = { 3 }, +}; +BUILD_ASSERT(ARRAY_SIZE(it8801_pwm_channels) == PWM_CH_COUNT); + +/******************************************************************************/ const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = { { .bus_type = EC_BUS_TYPE_I2C, diff --git a/board/jacuzzi/board.h b/board/jacuzzi/board.h index e965ce128f..288d5e3faf 100644 --- a/board/jacuzzi/board.h +++ b/board/jacuzzi/board.h @@ -22,9 +22,6 @@ #define CONFIG_CHIPSET_POWER_SEQ_VERSION 1 #endif -/* TODO(b:135086465) led implementation */ -#undef CONFIG_LED_COMMON - #define CONFIG_BATTERY_HW_PRESENT_CUSTOM #define CONFIG_CHARGER_PSYS @@ -89,6 +86,11 @@ #define PD_OPERATING_POWER_MW 30000 +#define CONFIG_LED_PWM +#define CONFIG_LED_PWM_CHARGE_STATE_ONLY +#define CONFIG_IO_EXPANDER_IT8801_PWM +#define CONFIG_LED_PWM_COUNT 1 + #ifndef __ASSEMBLER__ enum adc_channel { @@ -126,6 +128,13 @@ enum battery_type { BATTERY_TYPE_COUNT, }; +enum pwm_channel { + PWM_CH_LED_RED, + PWM_CH_LED_GREEN, + PWM_CH_LED_BLUE, + PWM_CH_COUNT +}; + #include "gpio_signal.h" #include "registers.h" diff --git a/board/jacuzzi/build.mk b/board/jacuzzi/build.mk index 7f9669d7d7..e449fce9fc 100644 --- a/board/jacuzzi/build.mk +++ b/board/jacuzzi/build.mk @@ -12,4 +12,4 @@ CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f09x BASEBOARD:=kukui -board-y=battery.o board.o +board-y=battery.o board.o led.o diff --git a/board/jacuzzi/led.c b/board/jacuzzi/led.c new file mode 100644 index 0000000000..26ef39a245 --- /dev/null +++ b/board/jacuzzi/led.c @@ -0,0 +1,67 @@ +/* Copyright 2019 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 and battery LED control for Jacuzzi + */ + +#include "common.h" +#include "driver/ioexpander/it8801.h" +#include "ec_commands.h" +#include "led_common.h" +#include "led_pwm.h" + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_POWER_LED, +}; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +struct pwm_led led_color_map[EC_LED_COLOR_COUNT] = { + [EC_LED_COLOR_RED] = {5, 0, 0}, + [EC_LED_COLOR_GREEN] = {0, 5, 0}, + [EC_LED_COLOR_BLUE] = {0, 0, 5}, + [EC_LED_COLOR_YELLOW] = {5, 5, 0}, + [EC_LED_COLOR_WHITE] = {2, 2, 2}, + [EC_LED_COLOR_AMBER] = {5, 3, 0}, +}; + +struct pwm_led pwm_leds[CONFIG_LED_PWM_COUNT] = { + [PWM_LED0] = { + .ch0 = PWM_CH_LED_RED, + .ch1 = PWM_CH_LED_GREEN, + .ch2 = PWM_CH_LED_BLUE, + .enable = &it8801_pwm_enable, + .set_duty = &it8801_pwm_set_duty, + }, +}; + +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_GREEN] = 100; + brightness_range[EC_LED_COLOR_YELLOW] = 100; + brightness_range[EC_LED_COLOR_AMBER] = 100; + brightness_range[EC_LED_COLOR_BLUE] = 100; + brightness_range[EC_LED_COLOR_WHITE] = 100; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (brightness[EC_LED_COLOR_RED]) + set_pwm_led_color(PWM_LED0, EC_LED_COLOR_RED); + else if (brightness[EC_LED_COLOR_GREEN]) + set_pwm_led_color(PWM_LED0, EC_LED_COLOR_GREEN); + else if (brightness[EC_LED_COLOR_YELLOW]) + set_pwm_led_color(PWM_LED0, EC_LED_COLOR_YELLOW); + else if (brightness[EC_LED_COLOR_AMBER]) + set_pwm_led_color(PWM_LED0, EC_LED_COLOR_AMBER); + else if (brightness[EC_LED_COLOR_BLUE]) + set_pwm_led_color(PWM_LED0, EC_LED_COLOR_BLUE); + else if (brightness[EC_LED_COLOR_WHITE]) + set_pwm_led_color(PWM_LED0, EC_LED_COLOR_WHITE); + else + /* Otherwise, the "color" is "off". */ + set_pwm_led_color(PWM_LED0, -1); + + return EC_SUCCESS; +} diff --git a/driver/ioexpander/it8801.c b/driver/ioexpander/it8801.c index 6b1184c740..00e40e12ed 100644 --- a/driver/ioexpander/it8801.c +++ b/driver/ioexpander/it8801.c @@ -6,13 +6,13 @@ #include "common.h" #include "console.h" #include "gpio.h" -#include "hooks.h" #include "i2c.h" #include "it8801.h" #include "keyboard_raw.h" #include "keyboard_scan.h" #include "registers.h" #include "task.h" +#include "util.h" #define CPRINTS(format, args...) cprints(CC_KEYSCAN, format, ## args) @@ -225,3 +225,87 @@ static int it8801_dump(int argc, char **argv) } DECLARE_CONSOLE_COMMAND(it8801_dump, it8801_dump, "NULL", "Dumps IT8801 registers"); + +#ifdef CONFIG_IO_EXPANDER_IT8801_PWM + +struct it8801_pwm_gpio_map { + int port; + int mask; +}; + +const static struct it8801_pwm_gpio_map it8801_pwm_gpio_map[] = { + [1] = {.port = 1, .mask = BIT(2)}, + [2] = {.port = 1, .mask = BIT(3)}, + [3] = {.port = 1, .mask = BIT(4)}, + [4] = {.port = 1, .mask = BIT(5)}, + [7] = {.port = 2, .mask = BIT(0)}, + [8] = {.port = 2, .mask = BIT(3)}, + [9] = {.port = 2, .mask = BIT(2)}, +}; + +void it8801_pwm_enable(enum pwm_channel ch, int enabled) +{ + int port, mask, val, index; + + index = it8801_pwm_channels[ch].index; + if (index < 0 || index >= ARRAY_SIZE(it8801_pwm_gpio_map)) + return; + port = it8801_pwm_gpio_map[index].port; + mask = it8801_pwm_gpio_map[index].mask; + if (port == 0 && mask == 0) + return; + + /* + * PWM1~4,7: alt func 1 + * PWM8,9: alt func 2 + */ + if (it8801_pwm_channels[ch].index <= 7) + it8801_write(IT8801_REG_GPIO_CR(port, mask), + 0x1 << IT8801_GPIOAFS_SHIFT); + else + it8801_write(IT8801_REG_GPIO_CR(port, mask), + 0x2 << IT8801_GPIOAFS_SHIFT); + + it8801_read(IT8801_REG_PWMMCR(it8801_pwm_channels[ch].index), &val); + val &= (~IT8801_PWMMCR_MCR_MASK); + if (enabled) + val |= IT8801_PWMMCR_MCR_BLINKING; + it8801_write(IT8801_REG_PWMMCR(it8801_pwm_channels[ch].index), val); +} + +int it88801_pwm_get_enabled(enum pwm_channel ch) +{ + int val; + + if (it8801_read(IT8801_REG_PWMMCR(it8801_pwm_channels[ch].index), &val)) + return 0; + return (val & IT8801_PWMMCR_MCR_MASK) == IT8801_PWMMCR_MCR_BLINKING; +} + +void it8801_pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty) +{ + duty = MIN(duty, 255); + duty = MAX(duty, 0); + it8801_write(IT8801_REG_PWMDCR(it8801_pwm_channels[ch].index), duty); +} + +uint16_t it8801_pwm_get_raw_duty(enum pwm_channel ch) +{ + int val; + + if (it8801_read(IT8801_REG_PWMDCR(it8801_pwm_channels[ch].index), &val)) + return 0; + return val; +} + +void it8801_pwm_set_duty(enum pwm_channel ch, int percent) +{ + return it8801_pwm_set_raw_duty(ch, (100 - percent) * 255 / 100); +} + +int it8801_pwm_get_duty(enum pwm_channel ch) +{ + return 100 - it8801_pwm_get_raw_duty(ch) * 100 / 255; +} + +#endif /* CONFIG_IO_EXPANDER_IT8801_PWM */ diff --git a/driver/ioexpander/it8801.h b/driver/ioexpander/it8801.h index 9b84adf764..b7e661effa 100644 --- a/driver/ioexpander/it8801.h +++ b/driver/ioexpander/it8801.h @@ -40,7 +40,67 @@ #define IT8801_REG_HBVIDR 0xFF #define IT8801_KSO_COUNT 18 +/* GPIO Register map */ +/* Input pin status register */ +#define IT8801_REG_GPIO_IPSR(port) (0x00 + (port)) +/* Set output value register */ +#define IT8801_REG_GPIO_SOVR(port) (0x05 + (port)) +/* Control register */ +#define IT8801_REG_GPIO_CR(port, mask) \ + (0x0A + (port) * 8 + GPIO_MASK_TO_NUM(mask)) +/* Interrupt status register */ +#define IT8801_REG_GPIO_ISR(port) (0x32 + (port)) +/* Interrupt enable register */ +#define IT8801_REG_GPIO_IER(port) (0x37 + (port)) + +/* Control register values */ +#define IT8801_GPIOAFS_SHIFT 6 /* bit 6~7 */ + +#define IT8801_GPIODIR BIT(5) /* direction, output=1 */ + +#define IT8801_GPIOIOT_SHIFT 3 /* bit 3~4 */ +#define IT8801_GPIOIOT_MASK 0x3 +#define IT8801_GPIOIOT_INT_LEVEL 0 +#define IT8801_GPIOIOT_INT_RISING 1 +#define IT8801_GPIOIOT_INT_FALLING 2 +#define IT8801_GPIOIOT_INT_EDGE 3 /* = RISING + FALLING */ +#define IT8801_GPIOIOT_OPEN_DRAIN 2 + +#define IT8801_GPIOPOL BIT(2) /* polarity */ +#define IT8801_GPIOPDE BIT(1) /* pull-down enable */ +#define IT8801_GPIOPUE BIT(0) /* pull-up enable */ + /* ISR for IT8801's SMB_INT# */ void io_expander_it8801_interrupt(enum gpio_signal signal); +#ifdef CONFIG_IO_EXPANDER_IT8801_PWM + +/* Mapping PWM_CH_LED_* to it8801 channel */ +struct it8801_pwm_t { + int index; +}; + +extern const struct it8801_pwm_t it8801_pwm_channels[]; + +/* standard pwm interface as defined in pwm.h */ +void it8801_pwm_enable(enum pwm_channel ch, int enabled); +int it88801_pwm_get_enabled(enum pwm_channel ch); +void it8801_pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty); +uint16_t it8801_pwm_get_raw_duty(enum pwm_channel ch); +void it8801_pwm_set_duty(enum pwm_channel ch, int percent); +int it8801_pwm_get_duty(enum pwm_channel ch); + +#define IT8801_REG_PWMMCR(n) (0x60 + ((n) - 1) * 8) +#define IT8801_REG_PWMDCR(n) (0x64 + ((n) - 1) * 8) +#define IT8801_REG_PWMPRSL(n) (0x66 + ((n) - 1) * 8) +#define IT8801_REG_PWMPRSM(n) (0x67 + ((n) - 1) * 8) + +#define IT8801_PWMMCR_MCR_MASK 0x3 +#define IT8801_PWMMCR_MCR_OFF 0 +#define IT8801_PWMMCR_MCR_BLINKING 1 +#define IT8801_PWMMCR_MCR_BREATHING 2 +#define IT8801_PWMMCR_MCR_ON 3 + +#endif /* CONFIG_IO_EXPANDER_IT8801_PWM */ + #endif /* __CROS_EC_KBEXPANDER_IT8801_H */ diff --git a/include/config.h b/include/config.h index 6e440a2eb9..b78a3fc1ff 100644 --- a/include/config.h +++ b/include/config.h @@ -2546,6 +2546,11 @@ /*****************************************************************************/ +/* + * Enable IT8801 pwm module. + */ +#undef CONFIG_IO_EXPANDER_IT8801_PWM + /*****************************************************************************/ /* Support common LED interface */ |