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 <s...@chromium.org>
---

Changes in v2:
- Update reset comments to indicate the datasheet section
- Correct full reset code

 arch/x86/cpu/cpu.c               | 22 +++++++++-------------
 arch/x86/include/asm/processor.h | 19 +++++++++++++++++++
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index c9614f1..02e66d8 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)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 3e26202..3575d34 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -25,8 +25,27 @@
 
 #ifndef __ASSEMBLY__
 
+/*
+ * This register is documented in (for example) the Intel Atom Processor E3800
+ * Product Family Datasheet in "PCU - Power Management Controller (PMC)".
+ *
+ * RST_CNT: Reset Control Register (RST_CNT) Offset cf9.
+ *
+ * The naming follows Intel's naming.
+ */
 #define PORT_RESET             0xcf9
 
+enum {
+       SYS_RST         = 1 << 1,       /* 0 for soft reset, 1 for hard reset */
+       RST_CPU         = 1 << 2,       /* initiate reset */
+       FULL_RST        = 1 << 3,       /* full power cycle */
+};
+
+/**
+ * x86_full_reset() - reset everything: perform a full power cycle
+ */
+void x86_full_reset(void);
+
 static inline __attribute__((always_inline)) void cpu_hlt(void)
 {
        asm("hlt");
-- 
2.2.0.rc0.207.ga3a616c

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to