From c19a4db9e4935400b24bd5bb43452019ff1843b8 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Tue, 12 Feb 2013 09:35:46 -0800 Subject: 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 Reviewed-on: https://gerrit.chromium.org/gerrit/43097 Reviewed-by: Duncan Laurie --- common/x86_power.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file 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 | \ @@ -160,6 +165,24 @@ static void update_in_signals(void) in_signals = inew; } +/** + * 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 * @@ -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 -- cgit v1.2.1