blob: 2802bd32ab9e026e4027a86819202d41e65c1fc9 [file] [log] [blame]
Patrick Georgi11f00792020-03-04 15:10:45 +01001/* SPDX-License-Identifier: GPL-2.0-only */
Kyösti Mälkkid132c992016-06-18 09:19:18 +03002
3#include <console/console.h>
4#include <string.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07005#include <acpi/acpi.h>
Elyes HAOUASd2b9ec12018-10-27 09:41:02 +02006#include <arch/cpu.h>
Elyes HAOUASe2d152c2019-06-21 07:06:50 +02007#include <commonlib/helpers.h>
Kyösti Mälkkic5853e92020-06-16 12:45:11 +03008#include <cpu/x86/smm.h>
Kyösti Mälkki82e41d82016-12-11 13:31:17 +02009#include <fallback.h>
Kyösti Mälkkid132c992016-06-18 09:19:18 +030010#include <timestamp.h>
11#include <romstage_handoff.h>
Kyösti Mälkkid132c992016-06-18 09:19:18 +030012
Subrata Banik5d2928c2017-09-21 19:17:33 +053013#if ENV_RAMSTAGE || ENV_POSTCAR
Kyösti Mälkkicf0e60f2016-06-20 20:40:32 +030014
Kyösti Mälkkid132c992016-06-18 09:19:18 +030015/* This is filled with acpi_is_wakeup() call early in ramstage. */
Kyösti Mälkki803acfa2015-05-29 06:17:23 +030016static int acpi_slp_type = -1;
Kyösti Mälkkid132c992016-06-18 09:19:18 +030017
Kyösti Mälkkid132c992016-06-18 09:19:18 +030018static void acpi_handoff_wakeup(void)
19{
Kyösti Mälkki746241f2017-09-04 19:22:26 +030020 if (acpi_slp_type < 0) {
21 if (romstage_handoff_is_resume()) {
Paul Menzelc105d9a2019-01-10 15:03:35 +010022 printk(BIOS_DEBUG, "S3 Resume\n");
Kyösti Mälkki746241f2017-09-04 19:22:26 +030023 acpi_slp_type = ACPI_S3;
24 } else {
Paul Menzelc105d9a2019-01-10 15:03:35 +010025 printk(BIOS_DEBUG, "Normal boot\n");
Kyösti Mälkki746241f2017-09-04 19:22:26 +030026 acpi_slp_type = ACPI_S0;
27 }
28 }
Kyösti Mälkkid132c992016-06-18 09:19:18 +030029}
30
31int acpi_is_wakeup(void)
32{
33 acpi_handoff_wakeup();
34 /* Both resume from S2 and resume from S3 restart at CPU reset */
Aaron Durbin95c43442016-07-13 12:08:33 -050035 return (acpi_slp_type == ACPI_S3 || acpi_slp_type == ACPI_S2);
Kyösti Mälkkid132c992016-06-18 09:19:18 +030036}
37
38int acpi_is_wakeup_s3(void)
39{
40 acpi_handoff_wakeup();
Aaron Durbin95c43442016-07-13 12:08:33 -050041 return (acpi_slp_type == ACPI_S3);
Kyösti Mälkkid132c992016-06-18 09:19:18 +030042}
43
44int acpi_is_wakeup_s4(void)
45{
46 acpi_handoff_wakeup();
Aaron Durbin95c43442016-07-13 12:08:33 -050047 return (acpi_slp_type == ACPI_S4);
Kyösti Mälkkid132c992016-06-18 09:19:18 +030048}
Kyösti Mälkkicf0e60f2016-06-20 20:40:32 +030049#endif /* ENV_RAMSTAGE */
50
Kyösti Mälkkid132c992016-06-18 09:19:18 +030051#define WAKEUP_BASE 0x600
52
Kyösti Mälkki7cd2c072018-06-03 23:04:28 +030053asmlinkage void (*acpi_do_wakeup)(uintptr_t vector) = (void *)WAKEUP_BASE;
Kyösti Mälkkid132c992016-06-18 09:19:18 +030054
55extern unsigned char __wakeup;
56extern unsigned int __wakeup_size;
57
58static void acpi_jump_to_wakeup(void *vector)
59{
Kyösti Mälkkid132c992016-06-18 09:19:18 +030060 /* Copy wakeup trampoline in place. */
61 memcpy((void *)WAKEUP_BASE, &__wakeup, __wakeup_size);
62
Kyösti Mälkki82e41d82016-12-11 13:31:17 +020063 set_boot_successful();
64
Kyösti Mälkkid132c992016-06-18 09:19:18 +030065 timestamp_add_now(TS_ACPI_WAKE_JUMP);
66
Kyösti Mälkki7cd2c072018-06-03 23:04:28 +030067 acpi_do_wakeup((uintptr_t)vector);
Kyösti Mälkkid132c992016-06-18 09:19:18 +030068}
69
Aaron Durbin64031672018-04-21 14:45:32 -060070void __weak mainboard_suspend_resume(void)
Kyösti Mälkkid132c992016-06-18 09:19:18 +030071{
72}
73
Kyösti Mälkkia4c0e1a2020-06-18 08:28:12 +030074void __noreturn acpi_resume(void *wake_vec)
Kyösti Mälkkid132c992016-06-18 09:19:18 +030075{
Kyösti Mälkkic3c55212020-06-17 10:34:26 +030076 /* Restore GNVS pointer in SMM if found. */
77 apm_control(APM_CNT_GNVS_UPDATE);
Kyösti Mälkkid132c992016-06-18 09:19:18 +030078
79 /* Call mainboard resume handler first, if defined. */
80 mainboard_suspend_resume();
81
82 post_code(POST_OS_RESUME);
83 acpi_jump_to_wakeup(wake_vec);
Kyösti Mälkkia4c0e1a2020-06-18 08:28:12 +030084
85 die("Failed the jump to wakeup vector\n");
Kyösti Mälkkid132c992016-06-18 09:19:18 +030086}