[U-Boot,11/22] x86: acpi: Resume OS if resume vector is found

Submitted by Bin Meng on March 16, 2017, 2:26 p.m.

Details

Message ID 1489674408-17498-12-git-send-email-bmeng.cn@gmail.com
State New
Delegated to: Bin Meng
Headers show

Commit Message

Bin Meng March 16, 2017, 2:26 p.m.
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>
---

 arch/x86/cpu/cpu.c             |  8 ++++++++
 arch/x86/include/asm/acpi_s3.h | 10 ++++++++++
 arch/x86/lib/Makefile          |  1 +
 arch/x86/lib/acpi_s3.c         | 26 ++++++++++++++++++++++++++
 4 files changed, 45 insertions(+)
 create mode 100644 arch/x86/lib/acpi_s3.c

Comments

Simon Glass March 21, 2017, 8:06 p.m.
Hi Bin,

On 16 March 2017 at 08:26, Bin Meng <bmeng.cn@gmail.com> wrote:
> 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>
> ---
>
>  arch/x86/cpu/cpu.c             |  8 ++++++++
>  arch/x86/include/asm/acpi_s3.h | 10 ++++++++++
>  arch/x86/lib/Makefile          |  1 +
>  arch/x86/lib/acpi_s3.c         | 26 ++++++++++++++++++++++++++
>  4 files changed, 45 insertions(+)
>  create mode 100644 arch/x86/lib/acpi_s3.c

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
> index 9dde54c..afc8645 100644
> --- a/arch/x86/cpu/cpu.c
> +++ b/arch/x86/cpu/cpu.c
> @@ -26,6 +26,7 @@
>  #include <malloc.h>
>  #include <syscon.h>
>  #include <asm/acpi_s3.h>
> +#include <asm/acpi_table.h>
>  #include <asm/control_regs.h>
>  #include <asm/coreboot_tables.h>
>  #include <asm/cpu.h>
> @@ -204,6 +205,13 @@ __weak void board_final_cleanup(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();
>
>         board_final_cleanup();
> diff --git a/arch/x86/include/asm/acpi_s3.h b/arch/x86/include/asm/acpi_s3.h
> index f9d4739..5892a8b 100644
> --- a/arch/x86/include/asm/acpi_s3.h
> +++ b/arch/x86/include/asm/acpi_s3.h
> @@ -100,6 +100,16 @@ enum acpi_sleep_state chipset_prev_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 /* __ASM_ACPI_S3_H__ */
> diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
> index 1c2c085..c61f931 100644
> --- a/arch/x86/lib/Makefile
> +++ b/arch/x86/lib/Makefile
> @@ -35,6 +35,7 @@ obj-$(CONFIG_X86_RAMTEST) += ramtest.o
>  obj-y  += sections.o
>  obj-y += sfi.o
>  obj-y  += string.o
> +obj-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.o
>  ifndef CONFIG_QEMU
>  obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
>  endif
> diff --git a/arch/x86/lib/acpi_s3.c b/arch/x86/lib/acpi_s3.c
> new file mode 100644
> index 0000000..f679c06
> --- /dev/null
> +++ b/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);

Should this be debug()?

> +       acpi_do_wakeup(vector);
> +}
> +
> +void acpi_resume(void *wake_vec)
> +{
> +       post_code(POST_OS_RESUME);
> +       acpi_jump_to_wakeup(wake_vec);
> +}
> --
> 2.9.2
>

Regards,
Simon

Patch hide | download patch | download mbox

diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index 9dde54c..afc8645 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -26,6 +26,7 @@ 
 #include <malloc.h>
 #include <syscon.h>
 #include <asm/acpi_s3.h>
+#include <asm/acpi_table.h>
 #include <asm/control_regs.h>
 #include <asm/coreboot_tables.h>
 #include <asm/cpu.h>
@@ -204,6 +205,13 @@  __weak void board_final_cleanup(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();
 
 	board_final_cleanup();
diff --git a/arch/x86/include/asm/acpi_s3.h b/arch/x86/include/asm/acpi_s3.h
index f9d4739..5892a8b 100644
--- a/arch/x86/include/asm/acpi_s3.h
+++ b/arch/x86/include/asm/acpi_s3.h
@@ -100,6 +100,16 @@  enum acpi_sleep_state chipset_prev_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 /* __ASM_ACPI_S3_H__ */
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 1c2c085..c61f931 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -35,6 +35,7 @@  obj-$(CONFIG_X86_RAMTEST) += ramtest.o
 obj-y	+= sections.o
 obj-y += sfi.o
 obj-y	+= string.o
+obj-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.o
 ifndef CONFIG_QEMU
 obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
 endif
diff --git a/arch/x86/lib/acpi_s3.c b/arch/x86/lib/acpi_s3.c
new file mode 100644
index 0000000..f679c06
--- /dev/null
+++ b/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);
+}