diff options
-rw-r--r-- | board/daisy/board.c | 9 | ||||
-rw-r--r-- | board/daisy/ec.tasklist | 1 | ||||
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | common/gaia_power.c | 144 |
4 files changed, 152 insertions, 3 deletions
diff --git a/board/daisy/board.c b/board/daisy/board.c index 8c5804b0a3..bbca1bd26c 100644 --- a/board/daisy/board.c +++ b/board/daisy/board.c @@ -10,12 +10,15 @@ #include "registers.h" #include "util.h" +/* GPIO interrupt handlers prototypes */ +void gaia_power_event(enum gpio_signal signal); + /* GPIO signal list. Must match order from enum gpio_signal. */ const struct gpio_info gpio_list[GPIO_COUNT] = { /* Inputs with interrupt handlers are first for efficiency */ - {"EC_PWRON", GPIO_A, (1<<0), GPIO_INT_BOTH, NULL}, - {"PP1800_LDO2", GPIO_A, (1<<1), GPIO_INT_BOTH, NULL}, - {"XPSHOLD", GPIO_A, (1<<11), GPIO_INT_RISING, NULL}, + {"EC_PWRON", GPIO_A, (1<<0), GPIO_INT_BOTH, gaia_power_event}, + {"PP1800_LDO2", GPIO_A, (1<<1), GPIO_INT_BOTH, gaia_power_event}, + {"XPSHOLD", GPIO_A, (1<<11), GPIO_INT_RISING, gaia_power_event}, {"CHARGER_INT", GPIO_B, (1<<0), GPIO_INT_RISING, NULL}, {"LID_OPEN", GPIO_C, (1<<13), GPIO_INT_BOTH, NULL}, /* Other inputs */ diff --git a/board/daisy/ec.tasklist b/board/daisy/ec.tasklist index 0e5992b96b..6c7049edae 100644 --- a/board/daisy/ec.tasklist +++ b/board/daisy/ec.tasklist @@ -15,4 +15,5 @@ */ #define CONFIG_TASK_LIST \ TASK(WATCHDOG, watchdog_task, NULL) \ + TASK(GAIAPOWER, gaia_power_task, NULL) \ TASK(CONSOLE, console_task, NULL) diff --git a/common/build.mk b/common/build.mk index 3eeae30074..48c7daa753 100644 --- a/common/build.mk +++ b/common/build.mk @@ -12,6 +12,7 @@ common-$(CONFIG_LPC)+=port80.o common-$(CONFIG_TASK_HOSTCMD)+=host_command.o common-$(CONFIG_TASK_I8042CMD)+=i8042.o keyboard.o common-$(CONFIG_TASK_X86POWER)+=x86_power.o +common-$(CONFIG_TASK_GAIAPOWER)+=gaia_power.o common-$(CONFIG_FLASH)+=flash_commands.o common-$(CONFIG_PWM)+=pwm_commands.o common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o temp_sensor_commands.o diff --git a/common/gaia_power.c b/common/gaia_power.c new file mode 100644 index 0000000000..2d10862c2e --- /dev/null +++ b/common/gaia_power.c @@ -0,0 +1,144 @@ +/* Copyright (c) 2012 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. + */ + +/* GAIA SoC power sequencing module for Chrome EC */ + +#include "board.h" +#include "console.h" +#include "gpio.h" +#include "task.h" +#include "timer.h" +#include "uart.h" +#include "util.h" + +/* Time necessary for the 5v regulator output to stabilize */ +#define DELAY_5V_SETUP 1000 /* 1ms */ + +/* Delay between 1.35v and 3.3v rails startup */ +#define DELAY_RAIL_STAGGERING 100 /* 100us */ + +/* Default timeout for input transition */ +#define FAIL_TIMEOUT 1000000 /* 5s */ + +/* Application processor power state */ +static int ap_on; + +/* simulated event state */ +static int force_signal = -1; +static int force_value; + +/* Wait for GPIO "signal" to reach level "value". + * Returns EC_ERROR_TIMEOUT if timeout before reaching the desired state. + */ +static int wait_in_signal(enum gpio_signal signal, int value, int timeout) +{ + timestamp_t deadline; + timestamp_t now = get_time(); + + if (timeout < 0) + deadline.le.hi = 0xffffffff; + else + deadline.val = now.val + timeout; + + while (((force_signal != signal) || (force_value != value)) && + gpio_get_level(signal) != value) { + now = get_time(); + if ((now.val >= deadline.val) || + (task_wait_msg(deadline.val - now.val) == + (1 << TASK_ID_TIMER))) { + uart_printf("Timeout waiting for GPIO %d\n", signal); + return EC_ERROR_TIMEOUT; + } + } + + return EC_SUCCESS; +} + + +void gaia_power_event(enum gpio_signal signal) +{ + /* Wake up the task */ + task_send_msg(TASK_ID_GAIAPOWER, TASK_ID_GAIAPOWER, 0); +} + +int gaia_power_init(void) +{ + /* Enable interrupts for our GPIOs */ + gpio_enable_interrupt(GPIO_EC_PWRON); + gpio_enable_interrupt(GPIO_PP1800_LDO2); + gpio_enable_interrupt(GPIO_SOC1V8_XPSHOLD); + + return EC_SUCCESS; +} + +/* TODO: rename this to something generic */ +int x86_power_in_S0(void) { + return ap_on; +} + +void gaia_power_task(void) +{ + gaia_power_init(); + + while (1) { + /* Power OFF state */ + ap_on = 0; + + /* wait for Power button press */ + wait_in_signal(GPIO_EC_PWRON, 1, -1); + + /* Enable 5v power rail */ + gpio_set_level(GPIO_EN_PP5000, 1); + /* wait to have stable power */ + usleep(DELAY_5V_SETUP); + + /* Startup PMIC */ + gpio_set_level(GPIO_PMIC_ACOK, 1); + /* wait for all PMIC regulators to be ready */ + wait_in_signal(GPIO_PP1800_LDO2, 1, FAIL_TIMEOUT); + + /* Enable DDR 1.35v power rail */ + gpio_set_level(GPIO_EN_PP1350, 1); + /* wait to avoid large inrush current */ + usleep(DELAY_RAIL_STAGGERING); + /* Enable 3.3v power rail */ + gpio_set_level(GPIO_EN_PP3300, 1); + + /* wait for the Application Processor to take control of the + * PMIC. + */ + wait_in_signal(GPIO_SOC1V8_XPSHOLD, 1, FAIL_TIMEOUT); + /* release PMIC startup signal */ + gpio_set_level(GPIO_PMIC_ACOK, 0); + + /* Power ON state */ + ap_on = 1; + uart_printf("AP running ...\n"); + + /* wait forever : TODO implement power OFF */ + while (1) + task_wait_msg(-1); + } +} + +/*****************************************************************************/ +/* Console debug command */ + +static int command_force_power(int argc, char **argv) +{ + /* simulate power button pressed */ + force_signal = GPIO_EC_PWRON; + force_value = 1; + /* Wake up the task */ + task_send_msg(TASK_ID_GAIAPOWER, TASK_ID_GAIAPOWER, 0); + /* wait 100 ms */ + usleep(100000); + /* release power button */ + force_signal = -1; + force_value = 0; + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(forcepower, command_force_power); |