summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-02-12 09:35:46 -0800
committerChromeBot <chrome-bot@google.com>2013-02-12 10:35:12 -0800
commitc19a4db9e4935400b24bd5bb43452019ff1843b8 (patch)
tree8c2bfd65f5aa8187d6fdde100084055511d42420
parentc93378dafad7229e34719165c09f31e15b6300d8 (diff)
downloadchrome-ec-c19a4db9e4935400b24bd5bb43452019ff1843b8.tar.gz
link: If a required power rail drops, shut down
This protects the system from ending up in a weird state if one of the rails fails to come up, or shuts down after coming up. BUG=chrome-os-partner:17774 BRANCH=link TEST=manual - Boot system - From EC console: gpioset enable_1_5v_ddr 0 - System shuts down; EC console prints "x86 power lost input" - Press power button; system turns back on - From EC console: gpioset enable_vs 0 - System shuts down; EC console prints "x86 power lost input" - Press power button; system turns back on - Suspend system - From EC console: gpioset enable_1_5v_ddr 0 - System shuts down; EC console prints "x86 power lost input" - Press power button; system turns back on Change-Id: I8ae1630deb4001716b8dfd89d7dec7300cddb5ae Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/43097 Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
-rw-r--r--common/x86_power.c56
1 files changed, 52 insertions, 4 deletions
diff --git a/common/x86_power.c b/common/x86_power.c
index 75c2905700..74eb70fa76 100644
--- a/common/x86_power.c
+++ b/common/x86_power.c
@@ -86,6 +86,11 @@ static const char * const state_names[] = {
IN_PGOOD_1_8VS | IN_PGOOD_VCCP | IN_PGOOD_VCCSA)
/* All core power rails */
#define IN_PGOOD_ALL_CORE (IN_PGOOD_CPU_CORE | IN_PGOOD_VGFX_CORE)
+/* Rails required for S3 */
+#define IN_PGOOD_S3 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_1_5V_DDR)
+/* Rails required for S0 */
+#define IN_PGOOD_S0 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_ALL_NONCORE)
+
/* All PM_SLP signals from PCH deasserted */
#define IN_ALL_PM_SLP_DEASSERTED (IN_PCH_SLP_S3n_DEASSERTED | \
IN_PCH_SLP_S4n_DEASSERTED | \
@@ -161,6 +166,24 @@ static void update_in_signals(void)
}
/**
+ * Check for required inputs
+ *
+ * @param want Input flags which must be present (IN_*)
+ *
+ * @return Non-zero if all present; zero if a required signal is missing.
+ */
+static int have_all_in_signals(uint32_t want)
+{
+ if ((in_signals & want) == want)
+ return 1;
+
+ CPRINTF("[%T x86 power lost input; wanted 0x%04x, got 0x%04x]\n",
+ want, in_signals & want);
+
+ return 0;
+}
+
+/**
* Wait for inputs to be present
*
* @param want Input flags which must be present (IN_*)
@@ -467,7 +490,12 @@ void x86_power_task(void)
switch_get_lid_open());
/* Check for state transitions */
- if (gpio_get_level(GPIO_PCH_SLP_S3n) == 1) {
+ if (!have_all_in_signals(IN_PGOOD_S3)) {
+ /* Required rail went away */
+ chipset_force_shutdown();
+ state = X86_S3S5;
+ break;
+ } else if (gpio_get_level(GPIO_PCH_SLP_S3n) == 1) {
/* Power up to next state */
state = X86_S3S0;
break;
@@ -483,7 +511,12 @@ void x86_power_task(void)
break;
case X86_S0:
- if (gpio_get_level(GPIO_PCH_SLP_S3n) == 0) {
+ if (!have_all_in_signals(IN_PGOOD_S0)) {
+ /* Required rail went away */
+ chipset_force_shutdown();
+ state = X86_S0S3;
+ break;
+ } else if (gpio_get_level(GPIO_PCH_SLP_S3n) == 0) {
/* Power down to next state */
state = X86_S0S3;
break;
@@ -513,7 +546,10 @@ void x86_power_task(void)
case X86_S5S3:
/* Wait for the always-on rails to be good */
- wait_in_signals(IN_PGOOD_ALWAYS_ON);
+ if (wait_in_signals(IN_PGOOD_ALWAYS_ON)) {
+ chipset_force_shutdown();
+ state = X86_S5;
+ }
/*
* Take lightbar out of reset, now that +5VALW is
@@ -524,6 +560,10 @@ void x86_power_task(void)
/* Turn on power to RAM */
gpio_set_level(GPIO_ENABLE_1_5V_DDR, 1);
+ if (wait_in_signals(IN_PGOOD_S3)) {
+ chipset_force_shutdown();
+ state = X86_S5;
+ }
/*
* Enable touchpad power so it can wake the system from
@@ -554,7 +594,15 @@ void x86_power_task(void)
gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 1);
/* Wait for non-core power rails good */
- wait_in_signals(IN_PGOOD_ALL_NONCORE);
+ if (wait_in_signals(IN_PGOOD_S0)) {
+ chipset_force_shutdown();
+ gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 0);
+ gpio_set_level(GPIO_ENABLE_WLAN, 0);
+ gpio_set_level(GPIO_RADIO_ENABLE_WLAN, 0);
+ gpio_set_level(GPIO_RADIO_ENABLE_BT, 0);
+ gpio_set_level(GPIO_ENABLE_VS, 0);
+ state = X86_S3;
+ }
/*
* Enable +CPU_CORE and +VGFX_CORE regulator. The CPU