diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-10-07 10:59:45 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2013-10-08 20:41:32 +0000 |
commit | ff8c8fee79e148567c0f2128db69563acb29ee54 (patch) | |
tree | 0d3daa52c091a36c997c0cd42be8267678a13f7f | |
parent | 99157c265c8353e166059e17d250d9991d4e7ae0 (diff) | |
download | chrome-ec-ff8c8fee79e148567c0f2128db69563acb29ee54.tar.gz |
rambi: Control LEDs using PWM
Rambi has a pair of LEDs which are attached to the PWM fan controller.
Add support for them. Also add a generic 'pwmduty' command which can
be used to get/set the duty cycle for any PWM channel.
Also fix rounding errors in pwm module, so that set/get duty doesn't
keep rounding down.
BUG=chrome-os-partner:22895
BRANCH=none
TEST=Boot rambi. LEDs are off.
pwmduty -> both are 0%
pwmduty 0 10 -> green LED on dimly
pwmduty 1 10 -> red LED on dimly
pwmduty 0 99 -> green LED on brightly
pwmduty 1 100 -> red LED on brightly
pwmduty 1 0 -> red LED off
pwmduty 1 -1 -> red LED turns back on because fan controller is disabled
pwmduty -> channel 0 at 99%, channel 1 disabled
Build all platforms. Pass all unit tests.
Change-Id: Ib0a6289a757554e696a9a0153a85bdc34e2ee2ae
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/172094
-rw-r--r-- | board/host/board.h | 1 | ||||
-rw-r--r-- | board/rambi/board.c | 6 | ||||
-rw-r--r-- | board/rambi/board.h | 1 | ||||
-rw-r--r-- | board/rambi/build.mk | 2 | ||||
-rw-r--r-- | board/rambi/led.c | 45 | ||||
-rw-r--r-- | chip/lm4/build.mk | 3 | ||||
-rw-r--r-- | chip/lm4/pwm.c | 15 | ||||
-rw-r--r-- | chip/stm32/pwm.c | 5 | ||||
-rw-r--r-- | common/build.mk | 8 | ||||
-rw-r--r-- | common/pwm_common.c | 63 | ||||
-rw-r--r-- | common/pwm_kblight.c (renamed from chip/lm4/pwm_kblight.c) | 7 | ||||
-rw-r--r-- | include/hooks.h | 2 |
12 files changed, 137 insertions, 21 deletions
diff --git a/board/host/board.h b/board/host/board.h index 6db70771ff..2529e15bc1 100644 --- a/board/host/board.h +++ b/board/host/board.h @@ -14,7 +14,6 @@ #define CONFIG_KEYBOARD_PROTOCOL_MKBP #define CONFIG_POWER_BUTTON #undef CONFIG_WATCHDOG -#define CONFIG_PWM #define CONFIG_SWITCH #undef CONFIG_CONSOLE_HISTORY diff --git a/board/rambi/board.c b/board/rambi/board.c index b864de5ef1..7a6f926763 100644 --- a/board/rambi/board.c +++ b/board/rambi/board.c @@ -110,7 +110,7 @@ const struct gpio_alt_func gpio_alt_funcs[] = { {GPIO_D, 0x0f, 2, MODULE_SPI}, /* SPI1 */ {GPIO_L, 0x3f, 15, MODULE_LPC}, /* LPC */ {GPIO_M, 0x33, 15, MODULE_LPC}, /* LPC */ - {GPIO_N, 0x50, 1, MODULE_PWM_LED}, /* Power LEDs */ + {GPIO_N, 0x50, 1, MODULE_PWM_LED, GPIO_OPEN_DRAIN}, /* Power LEDs */ }; const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs); @@ -152,8 +152,8 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* PWM channels */ const struct pwm_t pwm_channels[] = { - [PWM_CH_LED_GREEN] = {4, 0}, - [PWM_CH_LED_RED] = {3, 0}, + [PWM_CH_LED_GREEN] = {4, PWM_CONFIG_ACTIVE_LOW}, + [PWM_CH_LED_RED] = {3, PWM_CONFIG_ACTIVE_LOW}, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/board/rambi/board.h b/board/rambi/board.h index d9f038e850..2fdb718013 100644 --- a/board/rambi/board.h +++ b/board/rambi/board.h @@ -14,6 +14,7 @@ #define CONFIG_CMD_GSV #define CONFIG_EXTPOWER_GPIO #define CONFIG_KEYBOARD_PROTOCOL_8042 +#define CONFIG_LED_COMMON #undef CONFIG_PECI #define CONFIG_POWER_BUTTON #define CONFIG_POWER_BUTTON_X86 diff --git a/board/rambi/build.mk b/board/rambi/build.mk index 1843369ed4..ea89781339 100644 --- a/board/rambi/build.mk +++ b/board/rambi/build.mk @@ -9,4 +9,4 @@ # the IC is TI Stellaris LM4 CHIP:=lm4 -board-y=board.o +board-y=board.o led.o diff --git a/board/rambi/led.c b/board/rambi/led.c new file mode 100644 index 0000000000..451aae2bc3 --- /dev/null +++ b/board/rambi/led.c @@ -0,0 +1,45 @@ +/* Copyright (c) 2013 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. + * + * Battery LED control for Rambi + */ + +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "pwm.h" +#include "util.h" + +const enum ec_led_id supported_led_ids[] = {EC_LED_ID_BATTERY_LED}; +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +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; +} + +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_GREEN, brightness[EC_LED_COLOR_GREEN]); + return EC_SUCCESS; +} + +static void led_init(void) +{ + /* Configure GPIOs */ + gpio_config_module(MODULE_PWM_LED, 1); + + /* + * Enable PWMs and set to 0% duty cycle. If they're disabled, the LM4 + * seems to ground the pins instead of letting them float. + */ + pwm_enable(PWM_CH_LED_RED, 1); + pwm_set_duty(PWM_CH_LED_RED, 0); + + pwm_enable(PWM_CH_LED_GREEN, 1); + pwm_set_duty(PWM_CH_LED_GREEN, 0); +} +DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_DEFAULT); diff --git a/chip/lm4/build.mk b/chip/lm4/build.mk index 26532d347a..74ecd64d02 100644 --- a/chip/lm4/build.mk +++ b/chip/lm4/build.mk @@ -15,13 +15,12 @@ chip-y=clock.o gpio.o hwtimer.o jtag.o system.o uart.o # Optional chip modules chip-$(CONFIG_ADC)+=adc.o chip_temp_sensor.o chip-$(CONFIG_EEPROM)+=eeprom.o +chip-$(CONFIG_FAN)+=fan.o chip-$(CONFIG_FLASH)+=flash.o chip-$(CONFIG_I2C)+=i2c.o chip-$(CONFIG_LPC)+=lpc.o chip-$(CONFIG_PECI)+=peci.o chip-$(CONFIG_PWM)+=pwm.o -chip-$(CONFIG_FAN)+=fan.o -chip-$(CONFIG_PWM_KBLIGHT)+=pwm_kblight.o chip-$(CONFIG_SPI)+=spi.o chip-$(CONFIG_WATCHDOG)+=watchdog.o chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o diff --git a/chip/lm4/pwm.c b/chip/lm4/pwm.c index 5d797ded3a..68aae8fc8c 100644 --- a/chip/lm4/pwm.c +++ b/chip/lm4/pwm.c @@ -11,7 +11,6 @@ #include "pwm.h" #include "pwm_data.h" #include "registers.h" -#include "thermal.h" #include "util.h" /* Maximum RPM for PWM controller */ @@ -47,7 +46,10 @@ void pwm_set_duty(enum pwm_channel ch, int percent) else if (percent > 100) percent = 100; - duty = (MAX_PWM * percent) / 100; + if (pwm->flags & PWM_CONFIG_ACTIVE_LOW) + percent = 100 - percent; + + duty = (MAX_PWM * percent + 50) / 100; /* Always enable the channel */ pwm_enable(ch, 1); @@ -59,8 +61,13 @@ void pwm_set_duty(enum pwm_channel ch, int percent) int pwm_get_duty(enum pwm_channel ch) { const struct pwm_t *pwm = pwm_channels + ch; + int percent = ((LM4_FAN_FANCMD(pwm->channel) >> 16) * 100 + MAX_PWM / 2) + / MAX_PWM; + + if (pwm->flags & PWM_CONFIG_ACTIVE_LOW) + percent = 100 - percent; - return (LM4_FAN_FANCMD(pwm->channel) >> 16) * 100 / MAX_PWM; + return percent; } static void pwm_init(void) @@ -109,4 +116,4 @@ static void pwm_init(void) } } } -DECLARE_HOOK(HOOK_INIT, pwm_init, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_INIT, pwm_init, HOOK_PRIO_INIT_PWM); diff --git a/chip/stm32/pwm.c b/chip/stm32/pwm.c index 73db55334f..f9b1aeec10 100644 --- a/chip/stm32/pwm.c +++ b/chip/stm32/pwm.c @@ -135,6 +135,11 @@ void pwm_enable(enum pwm_channel ch, int enabled) pwm_disable(ch); } +int pwm_get_enabled(enum pwm_channel ch) +{ + return using_pwm[ch]; +} + static void pwm_reconfigure(enum pwm_channel ch) { using_pwm[ch] = 0; diff --git a/common/build.mk b/common/build.mk index d4151e0245..7fa8e043d4 100644 --- a/common/build.mk +++ b/common/build.mk @@ -37,6 +37,7 @@ common-$(CONFIG_EXTPOWER_FALCO)+=extpower_falco.o common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o common-$(CONFIG_EXTPOWER_KIRBY)+=extpower_kirby.o common-$(CONFIG_EXTPOWER_SPRING)+=extpower_spring.o +common-$(CONFIG_FAN)+=pwm_fan.o common-$(CONFIG_FLASH)+=flash_common.o common-$(CONFIG_FMAP)+=fmap.o common-$(CONFIG_I2C)+=i2c_common.o @@ -53,16 +54,17 @@ common-$(CONFIG_ONEWIRE)+=onewire.o common-$(CONFIG_POWER_BUTTON)+=power_button.o common-$(CONFIG_POWER_BUTTON_X86)+=power_button_x86.o common-$(CONFIG_PSTORE)+=pstore_commands.o -common-$(CONFIG_FAN)+=pwm_fan.o +common-$(CONFIG_PWM)+=pwm_common.o +common-$(CONFIG_PWM_KBLIGHT)+=pwm_kblight.o common-$(CONFIG_REGULATOR_IR357X)+=regulator_ir357x.o common-$(CONFIG_SWITCH)+=switch.o -common-$(CONFIG_WIRELESS)+=wireless.o common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o thermal.o common-$(CONFIG_TEMP_SENSOR_G781)+=temp_sensor_g781.o common-$(CONFIG_TEMP_SENSOR_TMP006)+=temp_sensor_tmp006.o -common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o common-$(CONFIG_USB_PORT_POWER_DUMB)+=usb_port_power_dumb.o +common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o common-$(CONFIG_USB_SWITCH_TSU6721)+=usb_switch_tsu6721.o +common-$(CONFIG_WIRELESS)+=wireless.o common-$(HAS_TASK_CHIPSET)+=chipset.o common-$(HAS_TASK_CONSOLE)+=console.o common-$(HAS_TASK_HOSTCMD)+=host_command.o host_event_commands.o diff --git a/common/pwm_common.c b/common/pwm_common.c new file mode 100644 index 0000000000..3a3073d142 --- /dev/null +++ b/common/pwm_common.c @@ -0,0 +1,63 @@ +/* Copyright (c) 2013 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. + */ + +#include "common.h" +#include "console.h" +#include "pwm.h" +#include "util.h" + +/** + * Print status of a PWM channel. + * + * @param ch Channel to print. + */ +static void print_channel(enum pwm_channel ch) +{ + if (pwm_get_enabled(ch)) + ccprintf(" %d: %d%%\n", ch, pwm_get_duty(ch)); + else + ccprintf(" %d: disabled\n", ch); +} + +static int cc_pwm_duty(int argc, char **argv) +{ + int percent = 0; + int ch; + char *e; + + if (argc < 2) { + ccprintf("PWM channels:\n"); + for (ch = 0; ch < PWM_CH_COUNT; ch++) + print_channel(ch); + return EC_SUCCESS; + } + + ch = strtoi(argv[1], &e, 0); + if (*e || ch < 0 || ch >= PWM_CH_COUNT) + return EC_ERROR_PARAM1; + + if (argc > 2) { + percent = strtoi(argv[2], &e, 0); + if (*e || percent > 100) { + /* Bad param */ + return EC_ERROR_PARAM1; + } else if (percent < 0) { + /* Negative = disable */ + pwm_enable(ch, 0); + } else { + ccprintf("Setting channel %d to %d%%\n", ch, percent); + pwm_enable(ch, 1); + pwm_set_duty(ch, percent); + } + } + + print_channel(ch); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(pwmduty, cc_pwm_duty, + "[channel [<percent> | -1=disable]]", + "Get/set PWM duty cycles ", + NULL); diff --git a/chip/lm4/pwm_kblight.c b/common/pwm_kblight.c index f76f0399e1..41448ce7e8 100644 --- a/chip/lm4/pwm_kblight.c +++ b/common/pwm_kblight.c @@ -5,7 +5,6 @@ /* PWM control module for Chromebook keyboard backlight. */ -#include "clock.h" #include "common.h" #include "console.h" #include "gpio.h" @@ -13,15 +12,9 @@ #include "host_command.h" #include "lid_switch.h" #include "pwm.h" -#include "registers.h" #include "system.h" -#include "task.h" -#include "timer.h" #include "util.h" -/* Max PWM for controller */ -#define MAX_PWM 0x1ff - #define PWMKBD_SYSJUMP_TAG 0x504b /* "PK" */ #define PWM_HOOK_VERSION 1 /* Saved PWM state across sysjumps */ diff --git a/include/hooks.h b/include/hooks.h index da46610505..fb3e6c236b 100644 --- a/include/hooks.h +++ b/include/hooks.h @@ -27,6 +27,8 @@ enum hook_priority { HOOK_PRIO_INIT_LID = HOOK_PRIO_FIRST + 3, /* Power button inits before chipset and switch */ HOOK_PRIO_INIT_POWER_BUTTON = HOOK_PRIO_FIRST + 4, + /* PWM inits before modules which might use it (fans, LEDs) */ + HOOK_PRIO_INIT_PWM = HOOK_PRIO_FIRST + 5, /* Specific values to lump temperature-related hooks together */ HOOK_PRIO_TEMP_SENSOR = 6000, |