diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-02-12 09:35:46 -0800 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-02-12 10:35:12 -0800 |
commit | c19a4db9e4935400b24bd5bb43452019ff1843b8 (patch) | |
tree | 8c2bfd65f5aa8187d6fdde100084055511d42420 | |
parent | c93378dafad7229e34719165c09f31e15b6300d8 (diff) | |
download | chrome-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.c | 56 |
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 |