summaryrefslogtreecommitdiff
path: root/arch/x86/cpu
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2015-04-28 20:11:29 -0600
committerSimon Glass <sjg@chromium.org>2015-04-29 21:02:31 -0600
commitff6a8f3c06eab0f0afb65d5e5925eee9860f0add (patch)
tree365c5606944eb9a1c9ae4bfd8e1f79e138257241 /arch/x86/cpu
parent87f4cd3a308b0bcffd8f9b5e7121fdb086c080f5 (diff)
x86: Implement reset_cpu() correctly for modern CPUs
The existing code is pretty ancient and is unreliable on modern hardware. Generally it will hang. We can use port 0xcf9 to initiate reset on more modern hardware (say in the last 10 years). Update the reset_cpu() function to do this, and add a new 'full reset' function to perform a full power cycle. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'arch/x86/cpu')
-rw-r--r--arch/x86/cpu/cpu.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index c9614f122f..02e66d80db 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -380,21 +380,17 @@ void flush_cache(unsigned long dummy1, unsigned long dummy2)
asm("wbinvd\n");
}
-void __attribute__ ((regparm(0))) generate_gpf(void);
-
-/* segment 0x70 is an arbitrary segment which does not exist */
-asm(".globl generate_gpf\n"
- ".hidden generate_gpf\n"
- ".type generate_gpf, @function\n"
- "generate_gpf:\n"
- "ljmp $0x70, $0x47114711\n");
-
__weak void reset_cpu(ulong addr)
{
- printf("Resetting using x86 Triple Fault\n");
- set_vector(13, generate_gpf); /* general protection fault handler */
- set_vector(8, generate_gpf); /* double fault handler */
- generate_gpf(); /* start the show */
+ /* Do a hard reset through the chipset's reset control register */
+ outb(SYS_RST | RST_CPU, PORT_RESET);
+ for (;;)
+ cpu_hlt();
+}
+
+void x86_full_reset(void)
+{
+ outb(FULL_RST | SYS_RST | RST_CPU, PORT_RESET);
}
int dcache_status(void)