summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-03-15 09:27:45 -0700
committerRandall Spangler <rspangler@chromium.org>2012-03-15 09:27:45 -0700
commit38d1b2e8bad5b9d4698963dbb63684aacbd23ec0 (patch)
treea1071f308986a330b86f3f56e5f6309c5d94f334
parent0cde4cfec35d34fb77c75d655d098390b70c8655 (diff)
downloadchrome-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.c7
-rw-r--r--common/x86_power.c50
-rw-r--r--include/x86_power.h5
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 */