Browse Source

x86: acpi: Resume OS if resume vector is found

In an S3 resume path, U-Boot does everything like a cold boot except
in the last_stage_init() it jumps to the OS resume vector.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Stefan Roese <sr@denx.de>
Bin Meng 8 years ago
parent
commit
3a34cae011
4 changed files with 45 additions and 0 deletions
  1. 8 0
      arch/x86/cpu/cpu.c
  2. 10 0
      arch/x86/include/asm/acpi_s3.h
  3. 1 0
      arch/x86/lib/Makefile
  4. 26 0
      arch/x86/lib/acpi_s3.c

+ 8 - 0
arch/x86/cpu/cpu.c

@@ -26,6 +26,7 @@
 #include <malloc.h>
 #include <malloc.h>
 #include <syscon.h>
 #include <syscon.h>
 #include <asm/acpi_s3.h>
 #include <asm/acpi_s3.h>
+#include <asm/acpi_table.h>
 #include <asm/control_regs.h>
 #include <asm/control_regs.h>
 #include <asm/coreboot_tables.h>
 #include <asm/coreboot_tables.h>
 #include <asm/cpu.h>
 #include <asm/cpu.h>
@@ -204,6 +205,13 @@ __weak void board_final_cleanup(void)
 
 
 int last_stage_init(void)
 int last_stage_init(void)
 {
 {
+#if CONFIG_HAVE_ACPI_RESUME
+	void *wake_vector = acpi_find_wakeup_vector();
+
+	if (wake_vector != NULL && gd->arch.prev_sleep_state == ACPI_S3)
+		acpi_resume(wake_vector);
+#endif
+
 	write_tables();
 	write_tables();
 
 
 	board_final_cleanup();
 	board_final_cleanup();

+ 10 - 0
arch/x86/include/asm/acpi_s3.h

@@ -99,6 +99,16 @@ enum acpi_sleep_state chipset_prev_sleep_state(void);
  */
  */
 void chipset_clear_sleep_state(void);
 void chipset_clear_sleep_state(void);
 
 
+/**
+ * acpi_resume() - Do ACPI S3 resume
+ *
+ * This calls U-Boot wake up assembly stub and jumps to OS's wake up vector.
+ *
+ * @wake_vec:	OS wake up vector
+ * @return:	Never returns
+ */
+void acpi_resume(void *wake_vec);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __ASSEMBLY__ */
 
 
 #endif /* __ASM_ACPI_S3_H__ */
 #endif /* __ASM_ACPI_S3_H__ */

+ 1 - 0
arch/x86/lib/Makefile

@@ -37,6 +37,7 @@ obj-$(CONFIG_INTEL_MID) += scu.o
 obj-y	+= sections.o
 obj-y	+= sections.o
 obj-y += sfi.o
 obj-y += sfi.o
 obj-y	+= string.o
 obj-y	+= string.o
+obj-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.o
 ifndef CONFIG_QEMU
 ifndef CONFIG_QEMU
 obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
 obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
 endif
 endif

+ 26 - 0
arch/x86/lib/acpi_s3.c

@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/acpi_s3.h>
+#include <asm/post.h>
+
+static void asmlinkage (*acpi_do_wakeup)(void *vector) = (void *)WAKEUP_BASE;
+
+static void acpi_jump_to_wakeup(void *vector)
+{
+	/* Copy wakeup trampoline in place */
+	memcpy((void *)WAKEUP_BASE, __wakeup, __wakeup_size);
+
+	printf("Jumping to OS waking vector %p\n", vector);
+	acpi_do_wakeup(vector);
+}
+
+void acpi_resume(void *wake_vec)
+{
+	post_code(POST_OS_RESUME);
+	acpi_jump_to_wakeup(wake_vec);
+}