diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2012-06-20 23:50:35 +0000 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-06-22 11:34:17 -0700 |
commit | b84ef3b1f2e8f266435030654976b409889a0344 (patch) | |
tree | 07e0618b3d617c86d0012493052fd5fffd87c9bd | |
parent | 232363bac25dc6af5d2ff580fded6baff9546398 (diff) | |
download | chrome-ec-b84ef3b1f2e8f266435030654976b409889a0344.tar.gz |
stm32: drive the keyboard power LED
Put the power LED in the right state (off, on, breathing) depending on
the AP state (off, running, suspending).
The power LED is connected to GPIO B3.
The AP suspend detection is done through GPIO A7.
(so we no longer configure it as SPI alternate function)
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BUG=chrome-os-partner:10647
TEST=on Lucas DVT, boot/stop the board and see the LED on and off.
Change-Id: I42121aacab35e9da7a751dc9f56bcc5af7850783
Reviewed-on: https://gerrit.chromium.org/gerrit/25880
Reviewed-by: David Hendricks <dhendrix@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Commit-Ready: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | board/daisy/board.c | 4 | ||||
-rw-r--r-- | board/daisy/board.h | 2 | ||||
-rw-r--r-- | board/daisy/ec.tasklist | 1 | ||||
-rw-r--r-- | board/snow/board.c | 11 | ||||
-rw-r--r-- | board/snow/board.h | 2 | ||||
-rw-r--r-- | board/snow/ec.tasklist | 1 | ||||
-rw-r--r-- | common/gaia_power.c | 77 |
7 files changed, 90 insertions, 8 deletions
diff --git a/board/daisy/board.c b/board/daisy/board.c index fa15b04ebe..8f20fdb18f 100644 --- a/board/daisy/board.c +++ b/board/daisy/board.c @@ -33,8 +33,10 @@ /* GPIO interrupt handlers prototypes */ #ifndef CONFIG_TASK_GAIAPOWER #define gaia_power_event NULL +#define gaia_suspend_event NULL #else void gaia_power_event(enum gpio_signal signal); +void gaia_suspend_event(enum gpio_signal signal); #endif #ifndef CONFIG_TASK_KEYSCAN #define matrix_interrupt NULL @@ -48,6 +50,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"XPSHOLD", GPIO_A, (1<<3), GPIO_INT_RISING, gaia_power_event}, {"CHARGER_INT", GPIO_C, (1<<4), GPIO_INT_RISING, NULL}, {"LID_OPEN", GPIO_C, (1<<13), GPIO_INT_BOTH, NULL}, + {"SUSPEND_L", GPIO_A, (1<<7), GPIO_INT_BOTH, gaia_suspend_event}, {"KB_IN00", GPIO_C, (1<<8), GPIO_KB_INPUT, matrix_interrupt}, {"KB_IN01", GPIO_C, (1<<9), GPIO_KB_INPUT, matrix_interrupt}, {"KB_IN02", GPIO_C, (1<<10), GPIO_KB_INPUT, matrix_interrupt}, @@ -66,6 +69,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"PMIC_PWRON_L", GPIO_A, (1<<12), GPIO_OUT_HIGH, NULL}, {"ENTERING_RW", GPIO_H, (1<<0), GPIO_OUT_LOW, NULL}, {"CHARGER_EN", GPIO_B, (1<<2), GPIO_OUT_LOW, NULL}, + {"POWER_LED_L", GPIO_B, (1<<3), GPIO_OUT_HIGH, NULL}, {"EC_INT", GPIO_B, (1<<9), GPIO_HI_Z, NULL}, {"CODEC_INT", GPIO_H, (1<<1), GPIO_HI_Z, NULL}, {"KB_OUT00", GPIO_B, (1<<0), GPIO_KB_OUTPUT, NULL}, diff --git a/board/daisy/board.h b/board/daisy/board.h index 542a2fa967..fe0a708620 100644 --- a/board/daisy/board.h +++ b/board/daisy/board.h @@ -48,6 +48,7 @@ enum gpio_signal { GPIO_SOC1V8_XPSHOLD, /* App Processor ON */ GPIO_CHARGER_INT, GPIO_LID_OPEN, /* LID switch detection */ + GPIO_SUSPEND_L, /* AP suspend/resume state */ /* Keyboard inputs */ GPIO_KB_IN00, GPIO_KB_IN01, @@ -66,6 +67,7 @@ enum gpio_signal { GPIO_PMIC_PWRON_L, /* 5v rail ready */ GPIO_EC_ENTERING_RW, /* EC is R/W mode for the kbc mux */ GPIO_CHARGER_EN, + GPIO_POWER_LED_L, /* Power state keyboard LED */ GPIO_EC_INT, GPIO_CODEC_INT, /* To audio codec (KB noise cancellation) */ GPIO_KB_OUT00, diff --git a/board/daisy/ec.tasklist b/board/daisy/ec.tasklist index 6656552c33..91e4d353c0 100644 --- a/board/daisy/ec.tasklist +++ b/board/daisy/ec.tasklist @@ -15,6 +15,7 @@ */ #define CONFIG_TASK_LIST \ TASK(WATCHDOG, watchdog_task, NULL) \ + TASK(POWERLED, power_led_task, NULL) \ TASK(PMU_TPS65090_CHARGER, pmu_charger_task, NULL) \ TASK(KEYSCAN, keyboard_scan_task, NULL) \ TASK(GAIAPOWER, gaia_power_task, NULL) \ diff --git a/board/snow/board.c b/board/snow/board.c index eb02ce5878..1825870ec3 100644 --- a/board/snow/board.c +++ b/board/snow/board.c @@ -19,8 +19,10 @@ /* GPIO interrupt handlers prototypes */ #ifndef CONFIG_TASK_GAIAPOWER #define gaia_power_event NULL +#define gaia_suspend_event NULL #else void gaia_power_event(enum gpio_signal signal); +void gaia_suspend_event(enum gpio_signal signal); #endif #ifndef CONFIG_TASK_KEYSCAN #define matrix_interrupt NULL @@ -34,6 +36,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"XPSHOLD", GPIO_A, (1<<3), GPIO_INT_RISING, gaia_power_event}, {"CHARGER_INT", GPIO_C, (1<<4), GPIO_INT_RISING, NULL}, {"LID_OPEN", GPIO_C, (1<<13), GPIO_INT_BOTH, NULL}, + {"SUSPEND_L", GPIO_A, (1<<7), GPIO_INT_BOTH, gaia_suspend_event}, {"KB_IN00", GPIO_C, (1<<8), GPIO_KB_INPUT, matrix_interrupt}, {"KB_IN01", GPIO_C, (1<<9), GPIO_KB_INPUT, matrix_interrupt}, {"KB_IN02", GPIO_C, (1<<10), GPIO_KB_INPUT, matrix_interrupt}, @@ -52,6 +55,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"PMIC_PWRON_L",GPIO_A, (1<<12), GPIO_OUT_HIGH, NULL}, {"ENTERING_RW", GPIO_D, (1<<0), GPIO_OUT_LOW, NULL}, {"CHARGER_EN", GPIO_B, (1<<2), GPIO_OUT_LOW, NULL}, + {"POWER_LED_L", GPIO_B, (1<<3), GPIO_OUT_HIGH, NULL}, {"EC_INT", GPIO_B, (1<<9), GPIO_HI_Z, NULL}, {"CODEC_INT", GPIO_D, (1<<1), GPIO_HI_Z, NULL}, {"KB_OUT00", GPIO_B, (1<<0), GPIO_KB_OUTPUT, NULL}, @@ -121,10 +125,9 @@ void configure_board(void) /* remap OSC_IN/OSC_OUT to PD0/PD1 */ STM32_GPIO_AFIO_MAPR |= 1 << 15; - /* SPI1 on pins PA4-7 (alt. function push-pull, 10MHz) */ - val = STM32_GPIO_CRL_OFF(GPIO_A) & ~0xffff0000; - val |= 0x99990000; - STM32_GPIO_CRL_OFF(GPIO_A) = val; + /* use PB3 as a GPIO, so disable JTAG and keep only SWD */ + STM32_GPIO_AFIO_MAPR = (STM32_GPIO_AFIO_MAPR & ~(0x7 << 24)) + | (2 << 24); /* * I2C SCL/SDA on PB10-11 and PB6-7, bi-directional, no pull-up/down, diff --git a/board/snow/board.h b/board/snow/board.h index 95efc8074e..dfefbcc55d 100644 --- a/board/snow/board.h +++ b/board/snow/board.h @@ -55,6 +55,7 @@ enum gpio_signal { GPIO_SOC1V8_XPSHOLD, /* App Processor ON */ GPIO_CHARGER_INT, GPIO_LID_OPEN, /* LID switch detection */ + GPIO_SUSPEND_L, /* AP suspend/resume state */ /* Keyboard inputs */ GPIO_KB_IN00, GPIO_KB_IN01, @@ -73,6 +74,7 @@ enum gpio_signal { GPIO_PMIC_PWRON_L, /* 5v rail ready */ GPIO_EC_ENTERING_RW, /* EC is R/W mode for the kbc mux */ GPIO_CHARGER_EN, + GPIO_POWER_LED_L, /* Power state keyboard LED */ GPIO_EC_INT, GPIO_CODEC_INT, /* To audio codec (KB noise cancellation) */ GPIO_KB_OUT00, diff --git a/board/snow/ec.tasklist b/board/snow/ec.tasklist index 24b151ba87..1e384c0890 100644 --- a/board/snow/ec.tasklist +++ b/board/snow/ec.tasklist @@ -15,6 +15,7 @@ */ #define CONFIG_TASK_LIST \ TASK(WATCHDOG, watchdog_task, NULL) \ + TASK(POWERLED, power_led_task, NULL) \ TASK(KEYSCAN, keyboard_scan_task, NULL) \ TASK(GAIAPOWER, gaia_power_task, NULL) \ TASK(CONSOLE, console_task, NULL) \ diff --git a/common/gaia_power.c b/common/gaia_power.c index 841135fc48..efbc4972fd 100644 --- a/common/gaia_power.c +++ b/common/gaia_power.c @@ -80,6 +80,7 @@ /* Application processor power state */ static int ap_on; +static int ap_suspended; /* simulated event state */ static int force_signal = -1; @@ -100,6 +101,60 @@ static timestamp_t pwron_deadline; /* force AP power on (used for recovery keypress) */ static int auto_power_on; +/*****************************************************************************/ +/* Keyboard power button LED state machine */ + +/* Suspend mode blinking duty cycle */ +#define LED_OFF_PERIOD 1500000 +#define LED_ON_PERIOD 50000 + +/* GPIO level for each LED state : it's an active low output */ +#define LED_GPIO_ON 0 +#define LED_GPIO_OFF 1 + +/* power LED FSM states */ +static enum power_led_state { + POWER_LED_OFF, + POWER_LED_ON, + POWER_LED_SUSP0, + POWER_LED_SUSP1, + + POWER_LED_STATE_COUNT +} led_state; + +/* power LED FSM parameters for each state */ +static const struct { + int gpio; + int duration; + enum power_led_state next; +} led_config[POWER_LED_STATE_COUNT] = { + [POWER_LED_OFF] = {LED_GPIO_OFF, -1, POWER_LED_OFF}, + [POWER_LED_ON] = {LED_GPIO_ON, -1, POWER_LED_ON}, + [POWER_LED_SUSP0] = {LED_GPIO_OFF, LED_OFF_PERIOD, POWER_LED_SUSP1}, + [POWER_LED_SUSP1] = {LED_GPIO_ON, LED_ON_PERIOD, POWER_LED_SUSP0}, +}; + +static void set_power_led(enum power_led_state new_state) +{ + led_state = new_state; + /* Wake up the task */ + task_wake(TASK_ID_POWERLED); +} + +void power_led_task(void) +{ + while (1) { + int state_timeout; + + gpio_set_level(GPIO_POWER_LED_L, led_config[led_state].gpio); + state_timeout = led_config[led_state].duration; + led_state = led_config[led_state].next; + task_wait_event(state_timeout); + } +} + +/*****************************************************************************/ + /* * Wait for GPIO "signal" to reach level "value". * Returns EC_ERROR_TIMEOUT if timeout before reaching the desired state. @@ -180,6 +235,16 @@ static int check_for_power_off_event(void) return 0; } +void gaia_suspend_event(enum gpio_signal signal) +{ + if (!ap_on) /* power on/off : not a real suspend / resume */ + return; + + ap_suspended = !gpio_get_level(GPIO_SUSPEND_L); + + set_power_led(ap_suspended ? POWER_LED_SUSP0 : POWER_LED_ON); +} + void gaia_power_event(enum gpio_signal signal) { /* Wake up the task */ @@ -211,10 +276,12 @@ int chipset_in_state(int state_mask) return 1; /* If AP is on, match on state */ - if ((state_mask & CHIPSET_STATE_ON) && ap_on) + if ((state_mask & CHIPSET_STATE_ON) && ap_on && !ap_suspended) return 1; - /* TODO: detect suspend state */ + /* if AP is suspended, match on state */ + if ((state_mask & CHIPSET_STATE_SUSPEND) && ap_on && ap_suspended) + return 1; /* In any other case, we don't have a match */ return 0; @@ -288,8 +355,9 @@ static int power_on(void) usleep(DELAY_RAIL_STAGGERING); /* Enable 3.3v power rail */ gpio_set_level(GPIO_EN_PP3300, 1); - CPUTS("AP running ...\n"); ap_on = 1; + set_power_led(POWER_LED_ON); + CPUTS("AP running ...\n"); return 0; } @@ -322,8 +390,9 @@ static void power_off(void) gpio_set_level(GPIO_EN_PP1350, 0); gpio_set_level(GPIO_PMIC_PWRON_L, 1); gpio_set_level(GPIO_EN_PP5000, 0); - CPUTS("Shutdown complete.\n"); ap_on = 0; + set_power_led(POWER_LED_OFF); + CPUTS("Shutdown complete.\n"); } /** |