summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/daisy/board.c9
-rw-r--r--board/daisy/ec.tasklist1
-rw-r--r--common/build.mk1
-rw-r--r--common/gaia_power.c144
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);