18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * sleep.c - ACPI sleep support.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
68c2ecf20Sopenharmony_ci * Copyright (c) 2004 David Shaohua Li <shaohua.li@intel.com>
78c2ecf20Sopenharmony_ci * Copyright (c) 2000-2003 Patrick Mochel
88c2ecf20Sopenharmony_ci * Copyright (c) 2003 Open Source Development Lab
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/delay.h>
128c2ecf20Sopenharmony_ci#include <linux/irq.h>
138c2ecf20Sopenharmony_ci#include <linux/dmi.h>
148c2ecf20Sopenharmony_ci#include <linux/device.h>
158c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
168c2ecf20Sopenharmony_ci#include <linux/suspend.h>
178c2ecf20Sopenharmony_ci#include <linux/reboot.h>
188c2ecf20Sopenharmony_ci#include <linux/acpi.h>
198c2ecf20Sopenharmony_ci#include <linux/module.h>
208c2ecf20Sopenharmony_ci#include <linux/syscore_ops.h>
218c2ecf20Sopenharmony_ci#include <asm/io.h>
228c2ecf20Sopenharmony_ci#include <trace/events/power.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include "internal.h"
258c2ecf20Sopenharmony_ci#include "sleep.h"
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/*
288c2ecf20Sopenharmony_ci * Some HW-full platforms do not have _S5, so they may need
298c2ecf20Sopenharmony_ci * to leverage efi power off for a shutdown.
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_cibool acpi_no_s5;
328c2ecf20Sopenharmony_cistatic u8 sleep_states[ACPI_S_STATE_COUNT];
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic void acpi_sleep_tts_switch(u32 acpi_state)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	acpi_status status;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	status = acpi_execute_simple_method(NULL, "\\_TTS", acpi_state);
398c2ecf20Sopenharmony_ci	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
408c2ecf20Sopenharmony_ci		/*
418c2ecf20Sopenharmony_ci		 * OS can't evaluate the _TTS object correctly. Some warning
428c2ecf20Sopenharmony_ci		 * message will be printed. But it won't break anything.
438c2ecf20Sopenharmony_ci		 */
448c2ecf20Sopenharmony_ci		printk(KERN_NOTICE "Failure in evaluating _TTS object\n");
458c2ecf20Sopenharmony_ci	}
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic int tts_notify_reboot(struct notifier_block *this,
498c2ecf20Sopenharmony_ci			unsigned long code, void *x)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	acpi_sleep_tts_switch(ACPI_STATE_S5);
528c2ecf20Sopenharmony_ci	return NOTIFY_DONE;
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic struct notifier_block tts_notifier = {
568c2ecf20Sopenharmony_ci	.notifier_call	= tts_notify_reboot,
578c2ecf20Sopenharmony_ci	.next		= NULL,
588c2ecf20Sopenharmony_ci	.priority	= 0,
598c2ecf20Sopenharmony_ci};
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic int acpi_sleep_prepare(u32 acpi_state)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_SLEEP
648c2ecf20Sopenharmony_ci	unsigned long acpi_wakeup_address;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	/* do we have a wakeup address for S2 and S3? */
678c2ecf20Sopenharmony_ci	if (acpi_state == ACPI_STATE_S3) {
688c2ecf20Sopenharmony_ci		acpi_wakeup_address = acpi_get_wakeup_address();
698c2ecf20Sopenharmony_ci		if (!acpi_wakeup_address)
708c2ecf20Sopenharmony_ci			return -EFAULT;
718c2ecf20Sopenharmony_ci		acpi_set_waking_vector(acpi_wakeup_address);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ci	ACPI_FLUSH_CPU_CACHE();
758c2ecf20Sopenharmony_ci#endif
768c2ecf20Sopenharmony_ci	printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n",
778c2ecf20Sopenharmony_ci		acpi_state);
788c2ecf20Sopenharmony_ci	acpi_enable_wakeup_devices(acpi_state);
798c2ecf20Sopenharmony_ci	acpi_enter_sleep_state_prep(acpi_state);
808c2ecf20Sopenharmony_ci	return 0;
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cibool acpi_sleep_state_supported(u8 sleep_state)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	acpi_status status;
868c2ecf20Sopenharmony_ci	u8 type_a, type_b;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	status = acpi_get_sleep_type_data(sleep_state, &type_a, &type_b);
898c2ecf20Sopenharmony_ci	return ACPI_SUCCESS(status) && (!acpi_gbl_reduced_hardware
908c2ecf20Sopenharmony_ci		|| (acpi_gbl_FADT.sleep_control.address
918c2ecf20Sopenharmony_ci			&& acpi_gbl_FADT.sleep_status.address));
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_SLEEP
958c2ecf20Sopenharmony_cistatic bool sleep_no_lps0 __read_mostly;
968c2ecf20Sopenharmony_cimodule_param(sleep_no_lps0, bool, 0644);
978c2ecf20Sopenharmony_ciMODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface");
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic u32 acpi_target_sleep_state = ACPI_STATE_S0;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciu32 acpi_target_system_state(void)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	return acpi_target_sleep_state;
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_target_system_state);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic bool pwr_btn_event_pending;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci/*
1108c2ecf20Sopenharmony_ci * The ACPI specification wants us to save NVS memory regions during hibernation
1118c2ecf20Sopenharmony_ci * and to restore them during the subsequent resume.  Windows does that also for
1128c2ecf20Sopenharmony_ci * suspend to RAM.  However, it is known that this mechanism does not work on
1138c2ecf20Sopenharmony_ci * all machines, so we allow the user to disable it with the help of the
1148c2ecf20Sopenharmony_ci * 'acpi_sleep=nonvs' kernel command line option.
1158c2ecf20Sopenharmony_ci */
1168c2ecf20Sopenharmony_cistatic bool nvs_nosave;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_civoid __init acpi_nvs_nosave(void)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	nvs_nosave = true;
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/*
1248c2ecf20Sopenharmony_ci * The ACPI specification wants us to save NVS memory regions during hibernation
1258c2ecf20Sopenharmony_ci * but says nothing about saving NVS during S3.  Not all versions of Windows
1268c2ecf20Sopenharmony_ci * save NVS on S3 suspend either, and it is clear that not all systems need
1278c2ecf20Sopenharmony_ci * NVS to be saved at S3 time.  To improve suspend/resume time, allow the
1288c2ecf20Sopenharmony_ci * user to disable saving NVS on S3 if their system does not require it, but
1298c2ecf20Sopenharmony_ci * continue to save/restore NVS for S4 as specified.
1308c2ecf20Sopenharmony_ci */
1318c2ecf20Sopenharmony_cistatic bool nvs_nosave_s3;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_civoid __init acpi_nvs_nosave_s3(void)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	nvs_nosave_s3 = true;
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic int __init init_nvs_save_s3(const struct dmi_system_id *d)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	nvs_nosave_s3 = false;
1418c2ecf20Sopenharmony_ci	return 0;
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/*
1458c2ecf20Sopenharmony_ci * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
1468c2ecf20Sopenharmony_ci * user to request that behavior by using the 'acpi_old_suspend_ordering'
1478c2ecf20Sopenharmony_ci * kernel command line option that causes the following variable to be set.
1488c2ecf20Sopenharmony_ci */
1498c2ecf20Sopenharmony_cistatic bool old_suspend_ordering;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_civoid __init acpi_old_suspend_ordering(void)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	old_suspend_ordering = true;
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistatic int __init init_old_suspend_ordering(const struct dmi_system_id *d)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	acpi_old_suspend_ordering();
1598c2ecf20Sopenharmony_ci	return 0;
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic int __init init_nvs_nosave(const struct dmi_system_id *d)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	acpi_nvs_nosave();
1658c2ecf20Sopenharmony_ci	return 0;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic bool acpi_sleep_default_s3;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic int __init init_default_s3(const struct dmi_system_id *d)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	acpi_sleep_default_s3 = true;
1738c2ecf20Sopenharmony_ci	return 0;
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_cistatic const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
1778c2ecf20Sopenharmony_ci	{
1788c2ecf20Sopenharmony_ci	.callback = init_old_suspend_ordering,
1798c2ecf20Sopenharmony_ci	.ident = "Abit KN9 (nForce4 variant)",
1808c2ecf20Sopenharmony_ci	.matches = {
1818c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
1828c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
1838c2ecf20Sopenharmony_ci		},
1848c2ecf20Sopenharmony_ci	},
1858c2ecf20Sopenharmony_ci	{
1868c2ecf20Sopenharmony_ci	.callback = init_old_suspend_ordering,
1878c2ecf20Sopenharmony_ci	.ident = "HP xw4600 Workstation",
1888c2ecf20Sopenharmony_ci	.matches = {
1898c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1908c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
1918c2ecf20Sopenharmony_ci		},
1928c2ecf20Sopenharmony_ci	},
1938c2ecf20Sopenharmony_ci	{
1948c2ecf20Sopenharmony_ci	.callback = init_old_suspend_ordering,
1958c2ecf20Sopenharmony_ci	.ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
1968c2ecf20Sopenharmony_ci	.matches = {
1978c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."),
1988c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_NAME, "M2N8L"),
1998c2ecf20Sopenharmony_ci		},
2008c2ecf20Sopenharmony_ci	},
2018c2ecf20Sopenharmony_ci	{
2028c2ecf20Sopenharmony_ci	.callback = init_old_suspend_ordering,
2038c2ecf20Sopenharmony_ci	.ident = "Panasonic CF51-2L",
2048c2ecf20Sopenharmony_ci	.matches = {
2058c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_VENDOR,
2068c2ecf20Sopenharmony_ci				"Matsushita Electric Industrial Co.,Ltd."),
2078c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
2088c2ecf20Sopenharmony_ci		},
2098c2ecf20Sopenharmony_ci	},
2108c2ecf20Sopenharmony_ci	{
2118c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2128c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VGN-FW41E_H",
2138c2ecf20Sopenharmony_ci	.matches = {
2148c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2158c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW41E_H"),
2168c2ecf20Sopenharmony_ci		},
2178c2ecf20Sopenharmony_ci	},
2188c2ecf20Sopenharmony_ci	{
2198c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2208c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VGN-FW21E",
2218c2ecf20Sopenharmony_ci	.matches = {
2228c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2238c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
2248c2ecf20Sopenharmony_ci		},
2258c2ecf20Sopenharmony_ci	},
2268c2ecf20Sopenharmony_ci	{
2278c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2288c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VGN-FW21M",
2298c2ecf20Sopenharmony_ci	.matches = {
2308c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2318c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21M"),
2328c2ecf20Sopenharmony_ci		},
2338c2ecf20Sopenharmony_ci	},
2348c2ecf20Sopenharmony_ci	{
2358c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2368c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VPCEB17FX",
2378c2ecf20Sopenharmony_ci	.matches = {
2388c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2398c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
2408c2ecf20Sopenharmony_ci		},
2418c2ecf20Sopenharmony_ci	},
2428c2ecf20Sopenharmony_ci	{
2438c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2448c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VGN-SR11M",
2458c2ecf20Sopenharmony_ci	.matches = {
2468c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2478c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
2488c2ecf20Sopenharmony_ci		},
2498c2ecf20Sopenharmony_ci	},
2508c2ecf20Sopenharmony_ci	{
2518c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2528c2ecf20Sopenharmony_ci	.ident = "Everex StepNote Series",
2538c2ecf20Sopenharmony_ci	.matches = {
2548c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
2558c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
2568c2ecf20Sopenharmony_ci		},
2578c2ecf20Sopenharmony_ci	},
2588c2ecf20Sopenharmony_ci	{
2598c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2608c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VPCEB1Z1E",
2618c2ecf20Sopenharmony_ci	.matches = {
2628c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2638c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
2648c2ecf20Sopenharmony_ci		},
2658c2ecf20Sopenharmony_ci	},
2668c2ecf20Sopenharmony_ci	{
2678c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2688c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VGN-NW130D",
2698c2ecf20Sopenharmony_ci	.matches = {
2708c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2718c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
2728c2ecf20Sopenharmony_ci		},
2738c2ecf20Sopenharmony_ci	},
2748c2ecf20Sopenharmony_ci	{
2758c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2768c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VPCCW29FX",
2778c2ecf20Sopenharmony_ci	.matches = {
2788c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
2798c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
2808c2ecf20Sopenharmony_ci		},
2818c2ecf20Sopenharmony_ci	},
2828c2ecf20Sopenharmony_ci	{
2838c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
2848c2ecf20Sopenharmony_ci	.ident = "Averatec AV1020-ED2",
2858c2ecf20Sopenharmony_ci	.matches = {
2868c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
2878c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
2888c2ecf20Sopenharmony_ci		},
2898c2ecf20Sopenharmony_ci	},
2908c2ecf20Sopenharmony_ci	{
2918c2ecf20Sopenharmony_ci	.callback = init_old_suspend_ordering,
2928c2ecf20Sopenharmony_ci	.ident = "Asus A8N-SLI DELUXE",
2938c2ecf20Sopenharmony_ci	.matches = {
2948c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
2958c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"),
2968c2ecf20Sopenharmony_ci		},
2978c2ecf20Sopenharmony_ci	},
2988c2ecf20Sopenharmony_ci	{
2998c2ecf20Sopenharmony_ci	.callback = init_old_suspend_ordering,
3008c2ecf20Sopenharmony_ci	.ident = "Asus A8N-SLI Premium",
3018c2ecf20Sopenharmony_ci	.matches = {
3028c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
3038c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
3048c2ecf20Sopenharmony_ci		},
3058c2ecf20Sopenharmony_ci	},
3068c2ecf20Sopenharmony_ci	{
3078c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
3088c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VGN-SR26GN_P",
3098c2ecf20Sopenharmony_ci	.matches = {
3108c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
3118c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
3128c2ecf20Sopenharmony_ci		},
3138c2ecf20Sopenharmony_ci	},
3148c2ecf20Sopenharmony_ci	{
3158c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
3168c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VPCEB1S1E",
3178c2ecf20Sopenharmony_ci	.matches = {
3188c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
3198c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"),
3208c2ecf20Sopenharmony_ci		},
3218c2ecf20Sopenharmony_ci	},
3228c2ecf20Sopenharmony_ci	{
3238c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
3248c2ecf20Sopenharmony_ci	.ident = "Sony Vaio VGN-FW520F",
3258c2ecf20Sopenharmony_ci	.matches = {
3268c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
3278c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
3288c2ecf20Sopenharmony_ci		},
3298c2ecf20Sopenharmony_ci	},
3308c2ecf20Sopenharmony_ci	{
3318c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
3328c2ecf20Sopenharmony_ci	.ident = "Asus K54C",
3338c2ecf20Sopenharmony_ci	.matches = {
3348c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
3358c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "K54C"),
3368c2ecf20Sopenharmony_ci		},
3378c2ecf20Sopenharmony_ci	},
3388c2ecf20Sopenharmony_ci	{
3398c2ecf20Sopenharmony_ci	.callback = init_nvs_nosave,
3408c2ecf20Sopenharmony_ci	.ident = "Asus K54HR",
3418c2ecf20Sopenharmony_ci	.matches = {
3428c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
3438c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
3448c2ecf20Sopenharmony_ci		},
3458c2ecf20Sopenharmony_ci	},
3468c2ecf20Sopenharmony_ci	{
3478c2ecf20Sopenharmony_ci	.callback = init_nvs_save_s3,
3488c2ecf20Sopenharmony_ci	.ident = "Asus 1025C",
3498c2ecf20Sopenharmony_ci	.matches = {
3508c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
3518c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "1025C"),
3528c2ecf20Sopenharmony_ci		},
3538c2ecf20Sopenharmony_ci	},
3548c2ecf20Sopenharmony_ci	/*
3558c2ecf20Sopenharmony_ci	 * https://bugzilla.kernel.org/show_bug.cgi?id=189431
3568c2ecf20Sopenharmony_ci	 * Lenovo G50-45 is a platform later than 2012, but needs nvs memory
3578c2ecf20Sopenharmony_ci	 * saving during S3.
3588c2ecf20Sopenharmony_ci	 */
3598c2ecf20Sopenharmony_ci	{
3608c2ecf20Sopenharmony_ci	.callback = init_nvs_save_s3,
3618c2ecf20Sopenharmony_ci	.ident = "Lenovo G50-45",
3628c2ecf20Sopenharmony_ci	.matches = {
3638c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
3648c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "80E3"),
3658c2ecf20Sopenharmony_ci		},
3668c2ecf20Sopenharmony_ci	},
3678c2ecf20Sopenharmony_ci	{
3688c2ecf20Sopenharmony_ci	.callback = init_nvs_save_s3,
3698c2ecf20Sopenharmony_ci	.ident = "Lenovo G40-45",
3708c2ecf20Sopenharmony_ci	.matches = {
3718c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
3728c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "80E1"),
3738c2ecf20Sopenharmony_ci		},
3748c2ecf20Sopenharmony_ci	},
3758c2ecf20Sopenharmony_ci	/*
3768c2ecf20Sopenharmony_ci	 * ThinkPad X1 Tablet(2016) cannot do suspend-to-idle using
3778c2ecf20Sopenharmony_ci	 * the Low Power S0 Idle firmware interface (see
3788c2ecf20Sopenharmony_ci	 * https://bugzilla.kernel.org/show_bug.cgi?id=199057).
3798c2ecf20Sopenharmony_ci	 */
3808c2ecf20Sopenharmony_ci	{
3818c2ecf20Sopenharmony_ci	.callback = init_default_s3,
3828c2ecf20Sopenharmony_ci	.ident = "ThinkPad X1 Tablet(2016)",
3838c2ecf20Sopenharmony_ci	.matches = {
3848c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
3858c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "20GGA00L00"),
3868c2ecf20Sopenharmony_ci		},
3878c2ecf20Sopenharmony_ci	},
3888c2ecf20Sopenharmony_ci	/*
3898c2ecf20Sopenharmony_ci	 * ASUS B1400CEAE hangs on resume from suspend (see
3908c2ecf20Sopenharmony_ci	 * https://bugzilla.kernel.org/show_bug.cgi?id=215742).
3918c2ecf20Sopenharmony_ci	 */
3928c2ecf20Sopenharmony_ci	{
3938c2ecf20Sopenharmony_ci	.callback = init_default_s3,
3948c2ecf20Sopenharmony_ci	.ident = "ASUS B1400CEAE",
3958c2ecf20Sopenharmony_ci	.matches = {
3968c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
3978c2ecf20Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK B1400CEAE"),
3988c2ecf20Sopenharmony_ci		},
3998c2ecf20Sopenharmony_ci	},
4008c2ecf20Sopenharmony_ci	{},
4018c2ecf20Sopenharmony_ci};
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cistatic bool ignore_blacklist;
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_civoid __init acpi_sleep_no_blacklist(void)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	ignore_blacklist = true;
4088c2ecf20Sopenharmony_ci}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_cistatic void __init acpi_sleep_dmi_check(void)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	if (ignore_blacklist)
4138c2ecf20Sopenharmony_ci		return;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (dmi_get_bios_year() >= 2012)
4168c2ecf20Sopenharmony_ci		acpi_nvs_nosave_s3();
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	dmi_check_system(acpisleep_dmi_table);
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci/**
4228c2ecf20Sopenharmony_ci * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
4238c2ecf20Sopenharmony_ci */
4248c2ecf20Sopenharmony_cistatic int acpi_pm_freeze(void)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	acpi_disable_all_gpes();
4278c2ecf20Sopenharmony_ci	acpi_os_wait_events_complete();
4288c2ecf20Sopenharmony_ci	acpi_ec_block_transactions();
4298c2ecf20Sopenharmony_ci	return 0;
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci/**
4338c2ecf20Sopenharmony_ci * acpi_pre_suspend - Enable wakeup devices, "freeze" EC and save NVS.
4348c2ecf20Sopenharmony_ci */
4358c2ecf20Sopenharmony_cistatic int acpi_pm_pre_suspend(void)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	acpi_pm_freeze();
4388c2ecf20Sopenharmony_ci	return suspend_nvs_save();
4398c2ecf20Sopenharmony_ci}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci/**
4428c2ecf20Sopenharmony_ci *	__acpi_pm_prepare - Prepare the platform to enter the target state.
4438c2ecf20Sopenharmony_ci *
4448c2ecf20Sopenharmony_ci *	If necessary, set the firmware waking vector and do arch-specific
4458c2ecf20Sopenharmony_ci *	nastiness to get the wakeup code to the waking vector.
4468c2ecf20Sopenharmony_ci */
4478c2ecf20Sopenharmony_cistatic int __acpi_pm_prepare(void)
4488c2ecf20Sopenharmony_ci{
4498c2ecf20Sopenharmony_ci	int error = acpi_sleep_prepare(acpi_target_sleep_state);
4508c2ecf20Sopenharmony_ci	if (error)
4518c2ecf20Sopenharmony_ci		acpi_target_sleep_state = ACPI_STATE_S0;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	return error;
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci/**
4578c2ecf20Sopenharmony_ci *	acpi_pm_prepare - Prepare the platform to enter the target sleep
4588c2ecf20Sopenharmony_ci *		state and disable the GPEs.
4598c2ecf20Sopenharmony_ci */
4608c2ecf20Sopenharmony_cistatic int acpi_pm_prepare(void)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	int error = __acpi_pm_prepare();
4638c2ecf20Sopenharmony_ci	if (!error)
4648c2ecf20Sopenharmony_ci		error = acpi_pm_pre_suspend();
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	return error;
4678c2ecf20Sopenharmony_ci}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci/**
4708c2ecf20Sopenharmony_ci *	acpi_pm_finish - Instruct the platform to leave a sleep state.
4718c2ecf20Sopenharmony_ci *
4728c2ecf20Sopenharmony_ci *	This is called after we wake back up (or if entering the sleep state
4738c2ecf20Sopenharmony_ci *	failed).
4748c2ecf20Sopenharmony_ci */
4758c2ecf20Sopenharmony_cistatic void acpi_pm_finish(void)
4768c2ecf20Sopenharmony_ci{
4778c2ecf20Sopenharmony_ci	struct acpi_device *pwr_btn_adev;
4788c2ecf20Sopenharmony_ci	u32 acpi_state = acpi_target_sleep_state;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	acpi_ec_unblock_transactions();
4818c2ecf20Sopenharmony_ci	suspend_nvs_free();
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	if (acpi_state == ACPI_STATE_S0)
4848c2ecf20Sopenharmony_ci		return;
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n",
4878c2ecf20Sopenharmony_ci		acpi_state);
4888c2ecf20Sopenharmony_ci	acpi_disable_wakeup_devices(acpi_state);
4898c2ecf20Sopenharmony_ci	acpi_leave_sleep_state(acpi_state);
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	/* reset firmware waking vector */
4928c2ecf20Sopenharmony_ci	acpi_set_waking_vector(0);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	acpi_target_sleep_state = ACPI_STATE_S0;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	acpi_resume_power_resources();
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	/* If we were woken with the fixed power button, provide a small
4998c2ecf20Sopenharmony_ci	 * hint to userspace in the form of a wakeup event on the fixed power
5008c2ecf20Sopenharmony_ci	 * button device (if it can be found).
5018c2ecf20Sopenharmony_ci	 *
5028c2ecf20Sopenharmony_ci	 * We delay the event generation til now, as the PM layer requires
5038c2ecf20Sopenharmony_ci	 * timekeeping to be running before we generate events. */
5048c2ecf20Sopenharmony_ci	if (!pwr_btn_event_pending)
5058c2ecf20Sopenharmony_ci		return;
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	pwr_btn_event_pending = false;
5088c2ecf20Sopenharmony_ci	pwr_btn_adev = acpi_dev_get_first_match_dev(ACPI_BUTTON_HID_POWERF,
5098c2ecf20Sopenharmony_ci						    NULL, -1);
5108c2ecf20Sopenharmony_ci	if (pwr_btn_adev) {
5118c2ecf20Sopenharmony_ci		pm_wakeup_event(&pwr_btn_adev->dev, 0);
5128c2ecf20Sopenharmony_ci		acpi_dev_put(pwr_btn_adev);
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci/**
5178c2ecf20Sopenharmony_ci * acpi_pm_start - Start system PM transition.
5188c2ecf20Sopenharmony_ci */
5198c2ecf20Sopenharmony_cistatic void acpi_pm_start(u32 acpi_state)
5208c2ecf20Sopenharmony_ci{
5218c2ecf20Sopenharmony_ci	acpi_target_sleep_state = acpi_state;
5228c2ecf20Sopenharmony_ci	acpi_sleep_tts_switch(acpi_target_sleep_state);
5238c2ecf20Sopenharmony_ci	acpi_scan_lock_acquire();
5248c2ecf20Sopenharmony_ci}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci/**
5278c2ecf20Sopenharmony_ci * acpi_pm_end - Finish up system PM transition.
5288c2ecf20Sopenharmony_ci */
5298c2ecf20Sopenharmony_cistatic void acpi_pm_end(void)
5308c2ecf20Sopenharmony_ci{
5318c2ecf20Sopenharmony_ci	acpi_turn_off_unused_power_resources();
5328c2ecf20Sopenharmony_ci	acpi_scan_lock_release();
5338c2ecf20Sopenharmony_ci	/*
5348c2ecf20Sopenharmony_ci	 * This is necessary in case acpi_pm_finish() is not called during a
5358c2ecf20Sopenharmony_ci	 * failing transition to a sleep state.
5368c2ecf20Sopenharmony_ci	 */
5378c2ecf20Sopenharmony_ci	acpi_target_sleep_state = ACPI_STATE_S0;
5388c2ecf20Sopenharmony_ci	acpi_sleep_tts_switch(acpi_target_sleep_state);
5398c2ecf20Sopenharmony_ci}
5408c2ecf20Sopenharmony_ci#else /* !CONFIG_ACPI_SLEEP */
5418c2ecf20Sopenharmony_ci#define sleep_no_lps0	(1)
5428c2ecf20Sopenharmony_ci#define acpi_target_sleep_state	ACPI_STATE_S0
5438c2ecf20Sopenharmony_ci#define acpi_sleep_default_s3	(1)
5448c2ecf20Sopenharmony_cistatic inline void acpi_sleep_dmi_check(void) {}
5458c2ecf20Sopenharmony_ci#endif /* CONFIG_ACPI_SLEEP */
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci#ifdef CONFIG_SUSPEND
5488c2ecf20Sopenharmony_cistatic u32 acpi_suspend_states[] = {
5498c2ecf20Sopenharmony_ci	[PM_SUSPEND_ON] = ACPI_STATE_S0,
5508c2ecf20Sopenharmony_ci	[PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
5518c2ecf20Sopenharmony_ci	[PM_SUSPEND_MEM] = ACPI_STATE_S3,
5528c2ecf20Sopenharmony_ci	[PM_SUSPEND_MAX] = ACPI_STATE_S5
5538c2ecf20Sopenharmony_ci};
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci/**
5568c2ecf20Sopenharmony_ci *	acpi_suspend_begin - Set the target system sleep state to the state
5578c2ecf20Sopenharmony_ci *		associated with given @pm_state, if supported.
5588c2ecf20Sopenharmony_ci */
5598c2ecf20Sopenharmony_cistatic int acpi_suspend_begin(suspend_state_t pm_state)
5608c2ecf20Sopenharmony_ci{
5618c2ecf20Sopenharmony_ci	u32 acpi_state = acpi_suspend_states[pm_state];
5628c2ecf20Sopenharmony_ci	int error;
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
5658c2ecf20Sopenharmony_ci	if (error)
5668c2ecf20Sopenharmony_ci		return error;
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	if (!sleep_states[acpi_state]) {
5698c2ecf20Sopenharmony_ci		pr_err("ACPI does not support sleep state S%u\n", acpi_state);
5708c2ecf20Sopenharmony_ci		return -ENOSYS;
5718c2ecf20Sopenharmony_ci	}
5728c2ecf20Sopenharmony_ci	if (acpi_state > ACPI_STATE_S1)
5738c2ecf20Sopenharmony_ci		pm_set_suspend_via_firmware();
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	acpi_pm_start(acpi_state);
5768c2ecf20Sopenharmony_ci	return 0;
5778c2ecf20Sopenharmony_ci}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci/**
5808c2ecf20Sopenharmony_ci *	acpi_suspend_enter - Actually enter a sleep state.
5818c2ecf20Sopenharmony_ci *	@pm_state: ignored
5828c2ecf20Sopenharmony_ci *
5838c2ecf20Sopenharmony_ci *	Flush caches and go to sleep. For STR we have to call arch-specific
5848c2ecf20Sopenharmony_ci *	assembly, which in turn call acpi_enter_sleep_state().
5858c2ecf20Sopenharmony_ci *	It's unfortunate, but it works. Please fix if you're feeling frisky.
5868c2ecf20Sopenharmony_ci */
5878c2ecf20Sopenharmony_cistatic int acpi_suspend_enter(suspend_state_t pm_state)
5888c2ecf20Sopenharmony_ci{
5898c2ecf20Sopenharmony_ci	acpi_status status = AE_OK;
5908c2ecf20Sopenharmony_ci	u32 acpi_state = acpi_target_sleep_state;
5918c2ecf20Sopenharmony_ci	int error;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	ACPI_FLUSH_CPU_CACHE();
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true);
5968c2ecf20Sopenharmony_ci	switch (acpi_state) {
5978c2ecf20Sopenharmony_ci	case ACPI_STATE_S1:
5988c2ecf20Sopenharmony_ci		barrier();
5998c2ecf20Sopenharmony_ci		status = acpi_enter_sleep_state(acpi_state);
6008c2ecf20Sopenharmony_ci		break;
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	case ACPI_STATE_S3:
6038c2ecf20Sopenharmony_ci		if (!acpi_suspend_lowlevel)
6048c2ecf20Sopenharmony_ci			return -ENOSYS;
6058c2ecf20Sopenharmony_ci		error = acpi_suspend_lowlevel();
6068c2ecf20Sopenharmony_ci		if (error)
6078c2ecf20Sopenharmony_ci			return error;
6088c2ecf20Sopenharmony_ci		pr_info(PREFIX "Low-level resume complete\n");
6098c2ecf20Sopenharmony_ci		pm_set_resume_via_firmware();
6108c2ecf20Sopenharmony_ci		break;
6118c2ecf20Sopenharmony_ci	}
6128c2ecf20Sopenharmony_ci	trace_suspend_resume(TPS("acpi_suspend"), acpi_state, false);
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	/* This violates the spec but is required for bug compatibility. */
6158c2ecf20Sopenharmony_ci	acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	/* Reprogram control registers */
6188c2ecf20Sopenharmony_ci	acpi_leave_sleep_state_prep(acpi_state);
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	/* ACPI 3.0 specs (P62) says that it's the responsibility
6218c2ecf20Sopenharmony_ci	 * of the OSPM to clear the status bit [ implying that the
6228c2ecf20Sopenharmony_ci	 * POWER_BUTTON event should not reach userspace ]
6238c2ecf20Sopenharmony_ci	 *
6248c2ecf20Sopenharmony_ci	 * However, we do generate a small hint for userspace in the form of
6258c2ecf20Sopenharmony_ci	 * a wakeup event. We flag this condition for now and generate the
6268c2ecf20Sopenharmony_ci	 * event later, as we're currently too early in resume to be able to
6278c2ecf20Sopenharmony_ci	 * generate wakeup events.
6288c2ecf20Sopenharmony_ci	 */
6298c2ecf20Sopenharmony_ci	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) {
6308c2ecf20Sopenharmony_ci		acpi_event_status pwr_btn_status = ACPI_EVENT_FLAG_DISABLED;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci		acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status);
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci		if (pwr_btn_status & ACPI_EVENT_FLAG_STATUS_SET) {
6358c2ecf20Sopenharmony_ci			acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
6368c2ecf20Sopenharmony_ci			/* Flag for later */
6378c2ecf20Sopenharmony_ci			pwr_btn_event_pending = true;
6388c2ecf20Sopenharmony_ci		}
6398c2ecf20Sopenharmony_ci	}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	/*
6428c2ecf20Sopenharmony_ci	 * Disable and clear GPE status before interrupt is enabled. Some GPEs
6438c2ecf20Sopenharmony_ci	 * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
6448c2ecf20Sopenharmony_ci	 * acpi_leave_sleep_state will reenable specific GPEs later
6458c2ecf20Sopenharmony_ci	 */
6468c2ecf20Sopenharmony_ci	acpi_disable_all_gpes();
6478c2ecf20Sopenharmony_ci	/* Allow EC transactions to happen. */
6488c2ecf20Sopenharmony_ci	acpi_ec_unblock_transactions();
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	suspend_nvs_restore();
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
6538c2ecf20Sopenharmony_ci}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_cistatic int acpi_suspend_state_valid(suspend_state_t pm_state)
6568c2ecf20Sopenharmony_ci{
6578c2ecf20Sopenharmony_ci	u32 acpi_state;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	switch (pm_state) {
6608c2ecf20Sopenharmony_ci	case PM_SUSPEND_ON:
6618c2ecf20Sopenharmony_ci	case PM_SUSPEND_STANDBY:
6628c2ecf20Sopenharmony_ci	case PM_SUSPEND_MEM:
6638c2ecf20Sopenharmony_ci		acpi_state = acpi_suspend_states[pm_state];
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci		return sleep_states[acpi_state];
6668c2ecf20Sopenharmony_ci	default:
6678c2ecf20Sopenharmony_ci		return 0;
6688c2ecf20Sopenharmony_ci	}
6698c2ecf20Sopenharmony_ci}
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_cistatic const struct platform_suspend_ops acpi_suspend_ops = {
6728c2ecf20Sopenharmony_ci	.valid = acpi_suspend_state_valid,
6738c2ecf20Sopenharmony_ci	.begin = acpi_suspend_begin,
6748c2ecf20Sopenharmony_ci	.prepare_late = acpi_pm_prepare,
6758c2ecf20Sopenharmony_ci	.enter = acpi_suspend_enter,
6768c2ecf20Sopenharmony_ci	.wake = acpi_pm_finish,
6778c2ecf20Sopenharmony_ci	.end = acpi_pm_end,
6788c2ecf20Sopenharmony_ci};
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci/**
6818c2ecf20Sopenharmony_ci *	acpi_suspend_begin_old - Set the target system sleep state to the
6828c2ecf20Sopenharmony_ci *		state associated with given @pm_state, if supported, and
6838c2ecf20Sopenharmony_ci *		execute the _PTS control method.  This function is used if the
6848c2ecf20Sopenharmony_ci *		pre-ACPI 2.0 suspend ordering has been requested.
6858c2ecf20Sopenharmony_ci */
6868c2ecf20Sopenharmony_cistatic int acpi_suspend_begin_old(suspend_state_t pm_state)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	int error = acpi_suspend_begin(pm_state);
6898c2ecf20Sopenharmony_ci	if (!error)
6908c2ecf20Sopenharmony_ci		error = __acpi_pm_prepare();
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	return error;
6938c2ecf20Sopenharmony_ci}
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci/*
6968c2ecf20Sopenharmony_ci * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
6978c2ecf20Sopenharmony_ci * been requested.
6988c2ecf20Sopenharmony_ci */
6998c2ecf20Sopenharmony_cistatic const struct platform_suspend_ops acpi_suspend_ops_old = {
7008c2ecf20Sopenharmony_ci	.valid = acpi_suspend_state_valid,
7018c2ecf20Sopenharmony_ci	.begin = acpi_suspend_begin_old,
7028c2ecf20Sopenharmony_ci	.prepare_late = acpi_pm_pre_suspend,
7038c2ecf20Sopenharmony_ci	.enter = acpi_suspend_enter,
7048c2ecf20Sopenharmony_ci	.wake = acpi_pm_finish,
7058c2ecf20Sopenharmony_ci	.end = acpi_pm_end,
7068c2ecf20Sopenharmony_ci	.recover = acpi_pm_finish,
7078c2ecf20Sopenharmony_ci};
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_cistatic bool s2idle_wakeup;
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci/*
7128c2ecf20Sopenharmony_ci * On platforms supporting the Low Power S0 Idle interface there is an ACPI
7138c2ecf20Sopenharmony_ci * device object with the PNP0D80 compatible device ID (System Power Management
7148c2ecf20Sopenharmony_ci * Controller) and a specific _DSM method under it.  That method, if present,
7158c2ecf20Sopenharmony_ci * can be used to indicate to the platform that the OS is transitioning into a
7168c2ecf20Sopenharmony_ci * low-power state in which certain types of activity are not desirable or that
7178c2ecf20Sopenharmony_ci * it is leaving such a state, which allows the platform to adjust its operation
7188c2ecf20Sopenharmony_ci * mode accordingly.
7198c2ecf20Sopenharmony_ci */
7208c2ecf20Sopenharmony_cistatic const struct acpi_device_id lps0_device_ids[] = {
7218c2ecf20Sopenharmony_ci	{"PNP0D80", },
7228c2ecf20Sopenharmony_ci	{"", },
7238c2ecf20Sopenharmony_ci};
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci#define ACPI_LPS0_DSM_UUID	"c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci#define ACPI_LPS0_GET_DEVICE_CONSTRAINTS	1
7288c2ecf20Sopenharmony_ci#define ACPI_LPS0_SCREEN_OFF	3
7298c2ecf20Sopenharmony_ci#define ACPI_LPS0_SCREEN_ON	4
7308c2ecf20Sopenharmony_ci#define ACPI_LPS0_ENTRY		5
7318c2ecf20Sopenharmony_ci#define ACPI_LPS0_EXIT		6
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_cistatic acpi_handle lps0_device_handle;
7348c2ecf20Sopenharmony_cistatic guid_t lps0_dsm_guid;
7358c2ecf20Sopenharmony_cistatic char lps0_dsm_func_mask;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci/* Device constraint entry structure */
7388c2ecf20Sopenharmony_cistruct lpi_device_info {
7398c2ecf20Sopenharmony_ci	char *name;
7408c2ecf20Sopenharmony_ci	int enabled;
7418c2ecf20Sopenharmony_ci	union acpi_object *package;
7428c2ecf20Sopenharmony_ci};
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci/* Constraint package structure */
7458c2ecf20Sopenharmony_cistruct lpi_device_constraint {
7468c2ecf20Sopenharmony_ci	int uid;
7478c2ecf20Sopenharmony_ci	int min_dstate;
7488c2ecf20Sopenharmony_ci	int function_states;
7498c2ecf20Sopenharmony_ci};
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_cistruct lpi_constraints {
7528c2ecf20Sopenharmony_ci	acpi_handle handle;
7538c2ecf20Sopenharmony_ci	int min_dstate;
7548c2ecf20Sopenharmony_ci};
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_cistatic struct lpi_constraints *lpi_constraints_table;
7578c2ecf20Sopenharmony_cistatic int lpi_constraints_table_size;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_cistatic void lpi_device_get_constraints(void)
7608c2ecf20Sopenharmony_ci{
7618c2ecf20Sopenharmony_ci	union acpi_object *out_obj;
7628c2ecf20Sopenharmony_ci	int i;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
7658c2ecf20Sopenharmony_ci					  1, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
7668c2ecf20Sopenharmony_ci					  NULL, ACPI_TYPE_PACKAGE);
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
7698c2ecf20Sopenharmony_ci			  out_obj ? "successful" : "failed");
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	if (!out_obj)
7728c2ecf20Sopenharmony_ci		return;
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	lpi_constraints_table = kcalloc(out_obj->package.count,
7758c2ecf20Sopenharmony_ci					sizeof(*lpi_constraints_table),
7768c2ecf20Sopenharmony_ci					GFP_KERNEL);
7778c2ecf20Sopenharmony_ci	if (!lpi_constraints_table)
7788c2ecf20Sopenharmony_ci		goto free_acpi_buffer;
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	acpi_handle_debug(lps0_device_handle, "LPI: constraints list begin:\n");
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	for (i = 0; i < out_obj->package.count; i++) {
7838c2ecf20Sopenharmony_ci		struct lpi_constraints *constraint;
7848c2ecf20Sopenharmony_ci		acpi_status status;
7858c2ecf20Sopenharmony_ci		union acpi_object *package = &out_obj->package.elements[i];
7868c2ecf20Sopenharmony_ci		struct lpi_device_info info = { };
7878c2ecf20Sopenharmony_ci		int package_count = 0, j;
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci		if (!package)
7908c2ecf20Sopenharmony_ci			continue;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci		for (j = 0; j < package->package.count; ++j) {
7938c2ecf20Sopenharmony_ci			union acpi_object *element =
7948c2ecf20Sopenharmony_ci					&(package->package.elements[j]);
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci			switch (element->type) {
7978c2ecf20Sopenharmony_ci			case ACPI_TYPE_INTEGER:
7988c2ecf20Sopenharmony_ci				info.enabled = element->integer.value;
7998c2ecf20Sopenharmony_ci				break;
8008c2ecf20Sopenharmony_ci			case ACPI_TYPE_STRING:
8018c2ecf20Sopenharmony_ci				info.name = element->string.pointer;
8028c2ecf20Sopenharmony_ci				break;
8038c2ecf20Sopenharmony_ci			case ACPI_TYPE_PACKAGE:
8048c2ecf20Sopenharmony_ci				package_count = element->package.count;
8058c2ecf20Sopenharmony_ci				info.package = element->package.elements;
8068c2ecf20Sopenharmony_ci				break;
8078c2ecf20Sopenharmony_ci			}
8088c2ecf20Sopenharmony_ci		}
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci		if (!info.enabled || !info.package || !info.name)
8118c2ecf20Sopenharmony_ci			continue;
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci		constraint = &lpi_constraints_table[lpi_constraints_table_size];
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci		status = acpi_get_handle(NULL, info.name, &constraint->handle);
8168c2ecf20Sopenharmony_ci		if (ACPI_FAILURE(status))
8178c2ecf20Sopenharmony_ci			continue;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci		acpi_handle_debug(lps0_device_handle,
8208c2ecf20Sopenharmony_ci				  "index:%d Name:%s\n", i, info.name);
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci		constraint->min_dstate = -1;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci		for (j = 0; j < package_count; ++j) {
8258c2ecf20Sopenharmony_ci			union acpi_object *info_obj = &info.package[j];
8268c2ecf20Sopenharmony_ci			union acpi_object *cnstr_pkg;
8278c2ecf20Sopenharmony_ci			union acpi_object *obj;
8288c2ecf20Sopenharmony_ci			struct lpi_device_constraint dev_info;
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci			switch (info_obj->type) {
8318c2ecf20Sopenharmony_ci			case ACPI_TYPE_INTEGER:
8328c2ecf20Sopenharmony_ci				/* version */
8338c2ecf20Sopenharmony_ci				break;
8348c2ecf20Sopenharmony_ci			case ACPI_TYPE_PACKAGE:
8358c2ecf20Sopenharmony_ci				if (info_obj->package.count < 2)
8368c2ecf20Sopenharmony_ci					break;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci				cnstr_pkg = info_obj->package.elements;
8398c2ecf20Sopenharmony_ci				obj = &cnstr_pkg[0];
8408c2ecf20Sopenharmony_ci				dev_info.uid = obj->integer.value;
8418c2ecf20Sopenharmony_ci				obj = &cnstr_pkg[1];
8428c2ecf20Sopenharmony_ci				dev_info.min_dstate = obj->integer.value;
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci				acpi_handle_debug(lps0_device_handle,
8458c2ecf20Sopenharmony_ci					"uid:%d min_dstate:%s\n",
8468c2ecf20Sopenharmony_ci					dev_info.uid,
8478c2ecf20Sopenharmony_ci					acpi_power_state_string(dev_info.min_dstate));
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci				constraint->min_dstate = dev_info.min_dstate;
8508c2ecf20Sopenharmony_ci				break;
8518c2ecf20Sopenharmony_ci			}
8528c2ecf20Sopenharmony_ci		}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci		if (constraint->min_dstate < 0) {
8558c2ecf20Sopenharmony_ci			acpi_handle_debug(lps0_device_handle,
8568c2ecf20Sopenharmony_ci					  "Incomplete constraint defined\n");
8578c2ecf20Sopenharmony_ci			continue;
8588c2ecf20Sopenharmony_ci		}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci		lpi_constraints_table_size++;
8618c2ecf20Sopenharmony_ci	}
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	acpi_handle_debug(lps0_device_handle, "LPI: constraints list end\n");
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_cifree_acpi_buffer:
8668c2ecf20Sopenharmony_ci	ACPI_FREE(out_obj);
8678c2ecf20Sopenharmony_ci}
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_cistatic void lpi_check_constraints(void)
8708c2ecf20Sopenharmony_ci{
8718c2ecf20Sopenharmony_ci	int i;
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	for (i = 0; i < lpi_constraints_table_size; ++i) {
8748c2ecf20Sopenharmony_ci		acpi_handle handle = lpi_constraints_table[i].handle;
8758c2ecf20Sopenharmony_ci		struct acpi_device *adev;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci		if (!handle || acpi_bus_get_device(handle, &adev))
8788c2ecf20Sopenharmony_ci			continue;
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci		acpi_handle_debug(handle,
8818c2ecf20Sopenharmony_ci			"LPI: required min power state:%s current power state:%s\n",
8828c2ecf20Sopenharmony_ci			acpi_power_state_string(lpi_constraints_table[i].min_dstate),
8838c2ecf20Sopenharmony_ci			acpi_power_state_string(adev->power.state));
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci		if (!adev->flags.power_manageable) {
8868c2ecf20Sopenharmony_ci			acpi_handle_info(handle, "LPI: Device not power manageable\n");
8878c2ecf20Sopenharmony_ci			lpi_constraints_table[i].handle = NULL;
8888c2ecf20Sopenharmony_ci			continue;
8898c2ecf20Sopenharmony_ci		}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci		if (adev->power.state < lpi_constraints_table[i].min_dstate)
8928c2ecf20Sopenharmony_ci			acpi_handle_info(handle,
8938c2ecf20Sopenharmony_ci				"LPI: Constraint not met; min power state:%s current power state:%s\n",
8948c2ecf20Sopenharmony_ci				acpi_power_state_string(lpi_constraints_table[i].min_dstate),
8958c2ecf20Sopenharmony_ci				acpi_power_state_string(adev->power.state));
8968c2ecf20Sopenharmony_ci	}
8978c2ecf20Sopenharmony_ci}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_cistatic void acpi_sleep_run_lps0_dsm(unsigned int func)
9008c2ecf20Sopenharmony_ci{
9018c2ecf20Sopenharmony_ci	union acpi_object *out_obj;
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	if (!(lps0_dsm_func_mask & (1 << func)))
9048c2ecf20Sopenharmony_ci		return;
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	out_obj = acpi_evaluate_dsm(lps0_device_handle, &lps0_dsm_guid, 1, func, NULL);
9078c2ecf20Sopenharmony_ci	ACPI_FREE(out_obj);
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	acpi_handle_debug(lps0_device_handle, "_DSM function %u evaluation %s\n",
9108c2ecf20Sopenharmony_ci			  func, out_obj ? "successful" : "failed");
9118c2ecf20Sopenharmony_ci}
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_cistatic int lps0_device_attach(struct acpi_device *adev,
9148c2ecf20Sopenharmony_ci			      const struct acpi_device_id *not_used)
9158c2ecf20Sopenharmony_ci{
9168c2ecf20Sopenharmony_ci	union acpi_object *out_obj;
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	if (lps0_device_handle)
9198c2ecf20Sopenharmony_ci		return 0;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
9228c2ecf20Sopenharmony_ci		return 0;
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid);
9258c2ecf20Sopenharmony_ci	/* Check if the _DSM is present and as expected. */
9268c2ecf20Sopenharmony_ci	out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL);
9278c2ecf20Sopenharmony_ci	if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER) {
9288c2ecf20Sopenharmony_ci		acpi_handle_debug(adev->handle,
9298c2ecf20Sopenharmony_ci				  "_DSM function 0 evaluation failed\n");
9308c2ecf20Sopenharmony_ci		return 0;
9318c2ecf20Sopenharmony_ci	}
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	lps0_dsm_func_mask = *(char *)out_obj->buffer.pointer;
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	ACPI_FREE(out_obj);
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci	acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
9388c2ecf20Sopenharmony_ci			  lps0_dsm_func_mask);
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	lps0_device_handle = adev->handle;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	lpi_device_get_constraints();
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	/*
9458c2ecf20Sopenharmony_ci	 * Use suspend-to-idle by default if the default suspend mode was not
9468c2ecf20Sopenharmony_ci	 * set from the command line.
9478c2ecf20Sopenharmony_ci	 */
9488c2ecf20Sopenharmony_ci	if (mem_sleep_default > PM_SUSPEND_MEM && !acpi_sleep_default_s3)
9498c2ecf20Sopenharmony_ci		mem_sleep_current = PM_SUSPEND_TO_IDLE;
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	/*
9528c2ecf20Sopenharmony_ci	 * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
9538c2ecf20Sopenharmony_ci	 * EC GPE to be enabled while suspended for certain wakeup devices to
9548c2ecf20Sopenharmony_ci	 * work, so mark it as wakeup-capable.
9558c2ecf20Sopenharmony_ci	 */
9568c2ecf20Sopenharmony_ci	acpi_ec_mark_gpe_for_wake();
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	return 0;
9598c2ecf20Sopenharmony_ci}
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_cistatic struct acpi_scan_handler lps0_handler = {
9628c2ecf20Sopenharmony_ci	.ids = lps0_device_ids,
9638c2ecf20Sopenharmony_ci	.attach = lps0_device_attach,
9648c2ecf20Sopenharmony_ci};
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_cistatic int acpi_s2idle_begin(void)
9678c2ecf20Sopenharmony_ci{
9688c2ecf20Sopenharmony_ci	acpi_scan_lock_acquire();
9698c2ecf20Sopenharmony_ci	return 0;
9708c2ecf20Sopenharmony_ci}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_cistatic int acpi_s2idle_prepare(void)
9738c2ecf20Sopenharmony_ci{
9748c2ecf20Sopenharmony_ci	if (acpi_sci_irq_valid()) {
9758c2ecf20Sopenharmony_ci		enable_irq_wake(acpi_sci_irq);
9768c2ecf20Sopenharmony_ci		acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE);
9778c2ecf20Sopenharmony_ci	}
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	acpi_enable_wakeup_devices(ACPI_STATE_S0);
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	/* Change the configuration of GPEs to avoid spurious wakeup. */
9828c2ecf20Sopenharmony_ci	acpi_enable_all_wakeup_gpes();
9838c2ecf20Sopenharmony_ci	acpi_os_wait_events_complete();
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ci	s2idle_wakeup = true;
9868c2ecf20Sopenharmony_ci	return 0;
9878c2ecf20Sopenharmony_ci}
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_cistatic int acpi_s2idle_prepare_late(void)
9908c2ecf20Sopenharmony_ci{
9918c2ecf20Sopenharmony_ci	if (!lps0_device_handle || sleep_no_lps0)
9928c2ecf20Sopenharmony_ci		return 0;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	if (pm_debug_messages_on)
9958c2ecf20Sopenharmony_ci		lpi_check_constraints();
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
9988c2ecf20Sopenharmony_ci	acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	return 0;
10018c2ecf20Sopenharmony_ci}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_cistatic bool acpi_s2idle_wake(void)
10048c2ecf20Sopenharmony_ci{
10058c2ecf20Sopenharmony_ci	if (!acpi_sci_irq_valid())
10068c2ecf20Sopenharmony_ci		return pm_wakeup_pending();
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	while (pm_wakeup_pending()) {
10098c2ecf20Sopenharmony_ci		/*
10108c2ecf20Sopenharmony_ci		 * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the
10118c2ecf20Sopenharmony_ci		 * SCI has not triggered while suspended, so bail out (the
10128c2ecf20Sopenharmony_ci		 * wakeup is pending anyway and the SCI is not the source of
10138c2ecf20Sopenharmony_ci		 * it).
10148c2ecf20Sopenharmony_ci		 */
10158c2ecf20Sopenharmony_ci		if (irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) {
10168c2ecf20Sopenharmony_ci			pm_pr_dbg("Wakeup unrelated to ACPI SCI\n");
10178c2ecf20Sopenharmony_ci			return true;
10188c2ecf20Sopenharmony_ci		}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci		/*
10218c2ecf20Sopenharmony_ci		 * If the status bit of any enabled fixed event is set, the
10228c2ecf20Sopenharmony_ci		 * wakeup is regarded as valid.
10238c2ecf20Sopenharmony_ci		 */
10248c2ecf20Sopenharmony_ci		if (acpi_any_fixed_event_status_set()) {
10258c2ecf20Sopenharmony_ci			pm_pr_dbg("ACPI fixed event wakeup\n");
10268c2ecf20Sopenharmony_ci			return true;
10278c2ecf20Sopenharmony_ci		}
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci		/* Check wakeups from drivers sharing the SCI. */
10308c2ecf20Sopenharmony_ci		if (acpi_check_wakeup_handlers()) {
10318c2ecf20Sopenharmony_ci			pm_pr_dbg("ACPI custom handler wakeup\n");
10328c2ecf20Sopenharmony_ci			return true;
10338c2ecf20Sopenharmony_ci		}
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci		/* Check non-EC GPE wakeups and dispatch the EC GPE. */
10368c2ecf20Sopenharmony_ci		if (acpi_ec_dispatch_gpe()) {
10378c2ecf20Sopenharmony_ci			pm_pr_dbg("ACPI non-EC GPE wakeup\n");
10388c2ecf20Sopenharmony_ci			return true;
10398c2ecf20Sopenharmony_ci		}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci		/*
10428c2ecf20Sopenharmony_ci		 * Cancel the SCI wakeup and process all pending events in case
10438c2ecf20Sopenharmony_ci		 * there are any wakeup ones in there.
10448c2ecf20Sopenharmony_ci		 *
10458c2ecf20Sopenharmony_ci		 * Note that if any non-EC GPEs are active at this point, the
10468c2ecf20Sopenharmony_ci		 * SCI will retrigger after the rearming below, so no events
10478c2ecf20Sopenharmony_ci		 * should be missed by canceling the wakeup here.
10488c2ecf20Sopenharmony_ci		 */
10498c2ecf20Sopenharmony_ci		pm_system_cancel_wakeup();
10508c2ecf20Sopenharmony_ci		acpi_os_wait_events_complete();
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci		/*
10538c2ecf20Sopenharmony_ci		 * The SCI is in the "suspended" state now and it cannot produce
10548c2ecf20Sopenharmony_ci		 * new wakeup events till the rearming below, so if any of them
10558c2ecf20Sopenharmony_ci		 * are pending here, they must be resulting from the processing
10568c2ecf20Sopenharmony_ci		 * of EC events above or coming from somewhere else.
10578c2ecf20Sopenharmony_ci		 */
10588c2ecf20Sopenharmony_ci		if (pm_wakeup_pending()) {
10598c2ecf20Sopenharmony_ci			pm_pr_dbg("Wakeup after ACPI Notify sync\n");
10608c2ecf20Sopenharmony_ci			return true;
10618c2ecf20Sopenharmony_ci		}
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci		pm_wakeup_clear(acpi_sci_irq);
10648c2ecf20Sopenharmony_ci		rearm_wake_irq(acpi_sci_irq);
10658c2ecf20Sopenharmony_ci	}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	return false;
10688c2ecf20Sopenharmony_ci}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_cistatic void acpi_s2idle_restore_early(void)
10718c2ecf20Sopenharmony_ci{
10728c2ecf20Sopenharmony_ci	if (!lps0_device_handle || sleep_no_lps0)
10738c2ecf20Sopenharmony_ci		return;
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
10768c2ecf20Sopenharmony_ci	acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
10778c2ecf20Sopenharmony_ci}
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_cistatic void acpi_s2idle_restore(void)
10808c2ecf20Sopenharmony_ci{
10818c2ecf20Sopenharmony_ci	/*
10828c2ecf20Sopenharmony_ci	 * Drain pending events before restoring the working-state configuration
10838c2ecf20Sopenharmony_ci	 * of GPEs.
10848c2ecf20Sopenharmony_ci	 */
10858c2ecf20Sopenharmony_ci	acpi_os_wait_events_complete(); /* synchronize GPE processing */
10868c2ecf20Sopenharmony_ci	acpi_ec_flush_work(); /* flush the EC driver's workqueues */
10878c2ecf20Sopenharmony_ci	acpi_os_wait_events_complete(); /* synchronize Notify handling */
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	s2idle_wakeup = false;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	acpi_enable_all_runtime_gpes();
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	acpi_disable_wakeup_devices(ACPI_STATE_S0);
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	if (acpi_sci_irq_valid()) {
10968c2ecf20Sopenharmony_ci		acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE);
10978c2ecf20Sopenharmony_ci		disable_irq_wake(acpi_sci_irq);
10988c2ecf20Sopenharmony_ci	}
10998c2ecf20Sopenharmony_ci}
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_cistatic void acpi_s2idle_end(void)
11028c2ecf20Sopenharmony_ci{
11038c2ecf20Sopenharmony_ci	acpi_scan_lock_release();
11048c2ecf20Sopenharmony_ci}
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_cistatic const struct platform_s2idle_ops acpi_s2idle_ops = {
11078c2ecf20Sopenharmony_ci	.begin = acpi_s2idle_begin,
11088c2ecf20Sopenharmony_ci	.prepare = acpi_s2idle_prepare,
11098c2ecf20Sopenharmony_ci	.prepare_late = acpi_s2idle_prepare_late,
11108c2ecf20Sopenharmony_ci	.wake = acpi_s2idle_wake,
11118c2ecf20Sopenharmony_ci	.restore_early = acpi_s2idle_restore_early,
11128c2ecf20Sopenharmony_ci	.restore = acpi_s2idle_restore,
11138c2ecf20Sopenharmony_ci	.end = acpi_s2idle_end,
11148c2ecf20Sopenharmony_ci};
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_cistatic void acpi_sleep_suspend_setup(void)
11178c2ecf20Sopenharmony_ci{
11188c2ecf20Sopenharmony_ci	int i;
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++)
11218c2ecf20Sopenharmony_ci		if (acpi_sleep_state_supported(i))
11228c2ecf20Sopenharmony_ci			sleep_states[i] = 1;
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	suspend_set_ops(old_suspend_ordering ?
11258c2ecf20Sopenharmony_ci		&acpi_suspend_ops_old : &acpi_suspend_ops);
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	acpi_scan_add_handler(&lps0_handler);
11288c2ecf20Sopenharmony_ci	s2idle_set_ops(&acpi_s2idle_ops);
11298c2ecf20Sopenharmony_ci}
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci#else /* !CONFIG_SUSPEND */
11328c2ecf20Sopenharmony_ci#define s2idle_wakeup		(false)
11338c2ecf20Sopenharmony_ci#define lps0_device_handle	(NULL)
11348c2ecf20Sopenharmony_cistatic inline void acpi_sleep_suspend_setup(void) {}
11358c2ecf20Sopenharmony_ci#endif /* !CONFIG_SUSPEND */
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_cibool acpi_s2idle_wakeup(void)
11388c2ecf20Sopenharmony_ci{
11398c2ecf20Sopenharmony_ci	return s2idle_wakeup;
11408c2ecf20Sopenharmony_ci}
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
11438c2ecf20Sopenharmony_cistatic u32 saved_bm_rld;
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_cistatic int  acpi_save_bm_rld(void)
11468c2ecf20Sopenharmony_ci{
11478c2ecf20Sopenharmony_ci	acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld);
11488c2ecf20Sopenharmony_ci	return 0;
11498c2ecf20Sopenharmony_ci}
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_cistatic void  acpi_restore_bm_rld(void)
11528c2ecf20Sopenharmony_ci{
11538c2ecf20Sopenharmony_ci	u32 resumed_bm_rld = 0;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld);
11568c2ecf20Sopenharmony_ci	if (resumed_bm_rld == saved_bm_rld)
11578c2ecf20Sopenharmony_ci		return;
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
11608c2ecf20Sopenharmony_ci}
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_cistatic struct syscore_ops acpi_sleep_syscore_ops = {
11638c2ecf20Sopenharmony_ci	.suspend = acpi_save_bm_rld,
11648c2ecf20Sopenharmony_ci	.resume = acpi_restore_bm_rld,
11658c2ecf20Sopenharmony_ci};
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_cistatic void acpi_sleep_syscore_init(void)
11688c2ecf20Sopenharmony_ci{
11698c2ecf20Sopenharmony_ci	register_syscore_ops(&acpi_sleep_syscore_ops);
11708c2ecf20Sopenharmony_ci}
11718c2ecf20Sopenharmony_ci#else
11728c2ecf20Sopenharmony_cistatic inline void acpi_sleep_syscore_init(void) {}
11738c2ecf20Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci#ifdef CONFIG_HIBERNATION
11768c2ecf20Sopenharmony_cistatic unsigned long s4_hardware_signature;
11778c2ecf20Sopenharmony_cistatic struct acpi_table_facs *facs;
11788c2ecf20Sopenharmony_cistatic bool nosigcheck;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_civoid __init acpi_no_s4_hw_signature(void)
11818c2ecf20Sopenharmony_ci{
11828c2ecf20Sopenharmony_ci	nosigcheck = true;
11838c2ecf20Sopenharmony_ci}
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_cistatic int acpi_hibernation_begin(pm_message_t stage)
11868c2ecf20Sopenharmony_ci{
11878c2ecf20Sopenharmony_ci	if (!nvs_nosave) {
11888c2ecf20Sopenharmony_ci		int error = suspend_nvs_alloc();
11898c2ecf20Sopenharmony_ci		if (error)
11908c2ecf20Sopenharmony_ci			return error;
11918c2ecf20Sopenharmony_ci	}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	if (stage.event == PM_EVENT_HIBERNATE)
11948c2ecf20Sopenharmony_ci		pm_set_suspend_via_firmware();
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	acpi_pm_start(ACPI_STATE_S4);
11978c2ecf20Sopenharmony_ci	return 0;
11988c2ecf20Sopenharmony_ci}
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_cistatic int acpi_hibernation_enter(void)
12018c2ecf20Sopenharmony_ci{
12028c2ecf20Sopenharmony_ci	acpi_status status = AE_OK;
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	ACPI_FLUSH_CPU_CACHE();
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	/* This shouldn't return.  If it returns, we have a problem */
12078c2ecf20Sopenharmony_ci	status = acpi_enter_sleep_state(ACPI_STATE_S4);
12088c2ecf20Sopenharmony_ci	/* Reprogram control registers */
12098c2ecf20Sopenharmony_ci	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
12128c2ecf20Sopenharmony_ci}
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_cistatic void acpi_hibernation_leave(void)
12158c2ecf20Sopenharmony_ci{
12168c2ecf20Sopenharmony_ci	pm_set_resume_via_firmware();
12178c2ecf20Sopenharmony_ci	/*
12188c2ecf20Sopenharmony_ci	 * If ACPI is not enabled by the BIOS and the boot kernel, we need to
12198c2ecf20Sopenharmony_ci	 * enable it here.
12208c2ecf20Sopenharmony_ci	 */
12218c2ecf20Sopenharmony_ci	acpi_enable();
12228c2ecf20Sopenharmony_ci	/* Reprogram control registers */
12238c2ecf20Sopenharmony_ci	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
12248c2ecf20Sopenharmony_ci	/* Check the hardware signature */
12258c2ecf20Sopenharmony_ci	if (facs && s4_hardware_signature != facs->hardware_signature)
12268c2ecf20Sopenharmony_ci		pr_crit("ACPI: Hardware changed while hibernated, success doubtful!\n");
12278c2ecf20Sopenharmony_ci	/* Restore the NVS memory area */
12288c2ecf20Sopenharmony_ci	suspend_nvs_restore();
12298c2ecf20Sopenharmony_ci	/* Allow EC transactions to happen. */
12308c2ecf20Sopenharmony_ci	acpi_ec_unblock_transactions();
12318c2ecf20Sopenharmony_ci}
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_cistatic void acpi_pm_thaw(void)
12348c2ecf20Sopenharmony_ci{
12358c2ecf20Sopenharmony_ci	acpi_ec_unblock_transactions();
12368c2ecf20Sopenharmony_ci	acpi_enable_all_runtime_gpes();
12378c2ecf20Sopenharmony_ci}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_cistatic const struct platform_hibernation_ops acpi_hibernation_ops = {
12408c2ecf20Sopenharmony_ci	.begin = acpi_hibernation_begin,
12418c2ecf20Sopenharmony_ci	.end = acpi_pm_end,
12428c2ecf20Sopenharmony_ci	.pre_snapshot = acpi_pm_prepare,
12438c2ecf20Sopenharmony_ci	.finish = acpi_pm_finish,
12448c2ecf20Sopenharmony_ci	.prepare = acpi_pm_prepare,
12458c2ecf20Sopenharmony_ci	.enter = acpi_hibernation_enter,
12468c2ecf20Sopenharmony_ci	.leave = acpi_hibernation_leave,
12478c2ecf20Sopenharmony_ci	.pre_restore = acpi_pm_freeze,
12488c2ecf20Sopenharmony_ci	.restore_cleanup = acpi_pm_thaw,
12498c2ecf20Sopenharmony_ci};
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci/**
12528c2ecf20Sopenharmony_ci *	acpi_hibernation_begin_old - Set the target system sleep state to
12538c2ecf20Sopenharmony_ci *		ACPI_STATE_S4 and execute the _PTS control method.  This
12548c2ecf20Sopenharmony_ci *		function is used if the pre-ACPI 2.0 suspend ordering has been
12558c2ecf20Sopenharmony_ci *		requested.
12568c2ecf20Sopenharmony_ci */
12578c2ecf20Sopenharmony_cistatic int acpi_hibernation_begin_old(pm_message_t stage)
12588c2ecf20Sopenharmony_ci{
12598c2ecf20Sopenharmony_ci	int error;
12608c2ecf20Sopenharmony_ci	/*
12618c2ecf20Sopenharmony_ci	 * The _TTS object should always be evaluated before the _PTS object.
12628c2ecf20Sopenharmony_ci	 * When the old_suspended_ordering is true, the _PTS object is
12638c2ecf20Sopenharmony_ci	 * evaluated in the acpi_sleep_prepare.
12648c2ecf20Sopenharmony_ci	 */
12658c2ecf20Sopenharmony_ci	acpi_sleep_tts_switch(ACPI_STATE_S4);
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	error = acpi_sleep_prepare(ACPI_STATE_S4);
12688c2ecf20Sopenharmony_ci	if (error)
12698c2ecf20Sopenharmony_ci		return error;
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	if (!nvs_nosave) {
12728c2ecf20Sopenharmony_ci		error = suspend_nvs_alloc();
12738c2ecf20Sopenharmony_ci		if (error)
12748c2ecf20Sopenharmony_ci			return error;
12758c2ecf20Sopenharmony_ci	}
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	if (stage.event == PM_EVENT_HIBERNATE)
12788c2ecf20Sopenharmony_ci		pm_set_suspend_via_firmware();
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	acpi_target_sleep_state = ACPI_STATE_S4;
12818c2ecf20Sopenharmony_ci	acpi_scan_lock_acquire();
12828c2ecf20Sopenharmony_ci	return 0;
12838c2ecf20Sopenharmony_ci}
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci/*
12868c2ecf20Sopenharmony_ci * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
12878c2ecf20Sopenharmony_ci * been requested.
12888c2ecf20Sopenharmony_ci */
12898c2ecf20Sopenharmony_cistatic const struct platform_hibernation_ops acpi_hibernation_ops_old = {
12908c2ecf20Sopenharmony_ci	.begin = acpi_hibernation_begin_old,
12918c2ecf20Sopenharmony_ci	.end = acpi_pm_end,
12928c2ecf20Sopenharmony_ci	.pre_snapshot = acpi_pm_pre_suspend,
12938c2ecf20Sopenharmony_ci	.prepare = acpi_pm_freeze,
12948c2ecf20Sopenharmony_ci	.finish = acpi_pm_finish,
12958c2ecf20Sopenharmony_ci	.enter = acpi_hibernation_enter,
12968c2ecf20Sopenharmony_ci	.leave = acpi_hibernation_leave,
12978c2ecf20Sopenharmony_ci	.pre_restore = acpi_pm_freeze,
12988c2ecf20Sopenharmony_ci	.restore_cleanup = acpi_pm_thaw,
12998c2ecf20Sopenharmony_ci	.recover = acpi_pm_finish,
13008c2ecf20Sopenharmony_ci};
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_cistatic void acpi_sleep_hibernate_setup(void)
13038c2ecf20Sopenharmony_ci{
13048c2ecf20Sopenharmony_ci	if (!acpi_sleep_state_supported(ACPI_STATE_S4))
13058c2ecf20Sopenharmony_ci		return;
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	hibernation_set_ops(old_suspend_ordering ?
13088c2ecf20Sopenharmony_ci			&acpi_hibernation_ops_old : &acpi_hibernation_ops);
13098c2ecf20Sopenharmony_ci	sleep_states[ACPI_STATE_S4] = 1;
13108c2ecf20Sopenharmony_ci	if (nosigcheck)
13118c2ecf20Sopenharmony_ci		return;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	acpi_get_table(ACPI_SIG_FACS, 1, (struct acpi_table_header **)&facs);
13148c2ecf20Sopenharmony_ci	if (facs)
13158c2ecf20Sopenharmony_ci		s4_hardware_signature = facs->hardware_signature;
13168c2ecf20Sopenharmony_ci}
13178c2ecf20Sopenharmony_ci#else /* !CONFIG_HIBERNATION */
13188c2ecf20Sopenharmony_cistatic inline void acpi_sleep_hibernate_setup(void) {}
13198c2ecf20Sopenharmony_ci#endif /* !CONFIG_HIBERNATION */
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_cistatic void acpi_power_off_prepare(void)
13228c2ecf20Sopenharmony_ci{
13238c2ecf20Sopenharmony_ci	/* Prepare to power off the system */
13248c2ecf20Sopenharmony_ci	acpi_sleep_prepare(ACPI_STATE_S5);
13258c2ecf20Sopenharmony_ci	acpi_disable_all_gpes();
13268c2ecf20Sopenharmony_ci	acpi_os_wait_events_complete();
13278c2ecf20Sopenharmony_ci}
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_cistatic void acpi_power_off(void)
13308c2ecf20Sopenharmony_ci{
13318c2ecf20Sopenharmony_ci	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
13328c2ecf20Sopenharmony_ci	printk(KERN_DEBUG "%s called\n", __func__);
13338c2ecf20Sopenharmony_ci	local_irq_disable();
13348c2ecf20Sopenharmony_ci	acpi_enter_sleep_state(ACPI_STATE_S5);
13358c2ecf20Sopenharmony_ci}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ciint __init acpi_sleep_init(void)
13388c2ecf20Sopenharmony_ci{
13398c2ecf20Sopenharmony_ci	char supported[ACPI_S_STATE_COUNT * 3 + 1];
13408c2ecf20Sopenharmony_ci	char *pos = supported;
13418c2ecf20Sopenharmony_ci	int i;
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	acpi_sleep_dmi_check();
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	sleep_states[ACPI_STATE_S0] = 1;
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	acpi_sleep_syscore_init();
13488c2ecf20Sopenharmony_ci	acpi_sleep_suspend_setup();
13498c2ecf20Sopenharmony_ci	acpi_sleep_hibernate_setup();
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	if (acpi_sleep_state_supported(ACPI_STATE_S5)) {
13528c2ecf20Sopenharmony_ci		sleep_states[ACPI_STATE_S5] = 1;
13538c2ecf20Sopenharmony_ci		pm_power_off_prepare = acpi_power_off_prepare;
13548c2ecf20Sopenharmony_ci		pm_power_off = acpi_power_off;
13558c2ecf20Sopenharmony_ci	} else {
13568c2ecf20Sopenharmony_ci		acpi_no_s5 = true;
13578c2ecf20Sopenharmony_ci	}
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	supported[0] = 0;
13608c2ecf20Sopenharmony_ci	for (i = 0; i < ACPI_S_STATE_COUNT; i++) {
13618c2ecf20Sopenharmony_ci		if (sleep_states[i])
13628c2ecf20Sopenharmony_ci			pos += sprintf(pos, " S%d", i);
13638c2ecf20Sopenharmony_ci	}
13648c2ecf20Sopenharmony_ci	pr_info(PREFIX "(supports%s)\n", supported);
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	/*
13678c2ecf20Sopenharmony_ci	 * Register the tts_notifier to reboot notifier list so that the _TTS
13688c2ecf20Sopenharmony_ci	 * object can also be evaluated when the system enters S5.
13698c2ecf20Sopenharmony_ci	 */
13708c2ecf20Sopenharmony_ci	register_reboot_notifier(&tts_notifier);
13718c2ecf20Sopenharmony_ci	return 0;
13728c2ecf20Sopenharmony_ci}
1373