summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2012-06-20 23:50:35 +0000
committerGerrit <chrome-bot@google.com>2012-06-22 11:34:17 -0700
commitb84ef3b1f2e8f266435030654976b409889a0344 (patch)
tree07e0618b3d617c86d0012493052fd5fffd87c9bd
parent232363bac25dc6af5d2ff580fded6baff9546398 (diff)
downloadchrome-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.c4
-rw-r--r--board/daisy/board.h2
-rw-r--r--board/daisy/ec.tasklist1
-rw-r--r--board/snow/board.c11
-rw-r--r--board/snow/board.h2
-rw-r--r--board/snow/ec.tasklist1
-rw-r--r--common/gaia_power.c77
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");
}
/**