diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-03-15 09:27:45 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-03-15 09:27:45 -0700 |
commit | 38d1b2e8bad5b9d4698963dbb63684aacbd23ec0 (patch) | |
tree | a1071f308986a330b86f3f56e5f6309c5d94f334 | |
parent | 0cde4cfec35d34fb77c75d655d098390b70c8655 (diff) | |
download | chrome-ec-38d1b2e8bad5b9d4698963dbb63684aacbd23ec0.tar.gz |
Add ability to trigger both warm and cold resets.
Keyboard reset now triggers a cold reset.
Signed-off-by: Randall Spangler <rspangler@chromium.org>
BUG=chrome-os-partner:8397
TEST=power system on, then do 'x86reset cold' for a cold reset or
'x86reset warm' for a warm reset. Check x86 debug console to see that
coreboot detects the warm (soft) reset.
Change-Id: I00930d9f5df98365277cd5c7f2eb8f135c4e4398
-rw-r--r-- | common/keyboard.c | 7 | ||||
-rw-r--r-- | common/x86_power.c | 50 | ||||
-rw-r--r-- | include/x86_power.h | 5 |
3 files changed, 48 insertions, 14 deletions
diff --git a/common/keyboard.c b/common/keyboard.c index f1daa5db1f..54386ac2ec 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -506,8 +506,11 @@ int handle_keyboard_command(uint8_t command, uint8_t *output) { #ifdef CONFIG_TASK_X86POWER case I8042_SYSTEM_RESET: - x86_power_reset(); - break; + /* Trigger a cold reset, since that also resets the TPM. If we just + * trigger a warm reset, that doesn't assert PLTRST# and the TPM is + * not reset. See crosbug.com/p/8379. */ + x86_power_reset(1); + break; #endif default: diff --git a/common/x86_power.c b/common/x86_power.c index 8a9664932c..1b6e2a4249 100644 --- a/common/x86_power.c +++ b/common/x86_power.c @@ -174,16 +174,38 @@ void x86_power_force_shutdown(void) } -void x86_power_reset(void) +void x86_power_reset(int cold_reset) { - /* Ignore if RCINn is already low */ - if (gpio_get_level(GPIO_PCH_RCINn) == 0) - return; - - /* Pulse must be at least 16 PCI clocks long = 500ns */ - gpio_set_level(GPIO_PCH_RCINn, 0); - udelay(10); - gpio_set_level(GPIO_PCH_RCINn, 1); + if (cold_reset) { + /* Drop and restore PWROK. This causes the PCH to reboot, + * regardless of its after-G3 setting. This type of reboot + * causes the PCH to assert PLTRST#, SLP_S3#, and SLP_S5#, so + * we actually drop power to the rest of the system (hence, a + * "cold" reboot). */ + + /* Ignore if PWROK is already low */ + if (gpio_get_level(GPIO_PCH_PWROK) == 0) + return; + + /* PWROK must deassert for at least 3 RTC clocks = 91 us */ + gpio_set_level(GPIO_PCH_PWROK, 0); + udelay(100); + gpio_set_level(GPIO_PCH_PWROK, 1); + + } else { + /* Send a RCIN# pulse to the PCH. This just causes it to + * assert INIT# to the CPU without dropping power or asserting + * PLTRST# to reset the rest of the system. */ + + /* Ignore if RCINn is already low */ + if (gpio_get_level(GPIO_PCH_RCINn) == 0) + return; + + /* Pulse must be at least 16 PCI clocks long = 500 ns */ + gpio_set_level(GPIO_PCH_RCINn, 0); + udelay(10); + gpio_set_level(GPIO_PCH_RCINn, 1); + } } /*****************************************************************************/ @@ -431,8 +453,16 @@ DECLARE_CONSOLE_COMMAND(x86power, command_x86power); static int command_x86reset(int argc, char **argv) { + int is_cold = 1; + + if (argc > 1 && !strcasecmp(argv[1], "cold")) + is_cold = 1; + else if (argc > 1 && !strcasecmp(argv[1], "warm")) + is_cold = 0; + /* Force the x86 to reset */ - x86_power_reset(); + uart_printf("Issuing x86 %s reset...\n", is_cold ? "cold" : "warm"); + x86_power_reset(is_cold); return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(x86reset, command_x86reset); diff --git a/include/x86_power.h b/include/x86_power.h index a093798c50..fba3f0cc15 100644 --- a/include/x86_power.h +++ b/include/x86_power.h @@ -25,7 +25,8 @@ void x86_power_cpu_overheated(int too_hot); * intended for use when the system is too hot or battery power is critical. */ void x86_power_force_shutdown(void); -/* Pulse the reset line to the x86. */ -void x86_power_reset(void); +/* Reset the x86. If cold_reset!=0, forces a cold reset by sending + * power-not-ok; otherwise, just pulses the reset line to the x86. */ +void x86_power_reset(int cold_reset); #endif /* __CROS_EC_X86_POWER_H */ |