xref: /OK3568_Linux_fs/kernel/drivers/acpi/sleep.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * sleep.c - ACPI sleep support.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
6*4882a593Smuzhiyun  * Copyright (c) 2004 David Shaohua Li <shaohua.li@intel.com>
7*4882a593Smuzhiyun  * Copyright (c) 2000-2003 Patrick Mochel
8*4882a593Smuzhiyun  * Copyright (c) 2003 Open Source Development Lab
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/delay.h>
12*4882a593Smuzhiyun #include <linux/irq.h>
13*4882a593Smuzhiyun #include <linux/dmi.h>
14*4882a593Smuzhiyun #include <linux/device.h>
15*4882a593Smuzhiyun #include <linux/interrupt.h>
16*4882a593Smuzhiyun #include <linux/suspend.h>
17*4882a593Smuzhiyun #include <linux/reboot.h>
18*4882a593Smuzhiyun #include <linux/acpi.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/syscore_ops.h>
21*4882a593Smuzhiyun #include <asm/io.h>
22*4882a593Smuzhiyun #include <trace/events/power.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include "internal.h"
25*4882a593Smuzhiyun #include "sleep.h"
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /*
28*4882a593Smuzhiyun  * Some HW-full platforms do not have _S5, so they may need
29*4882a593Smuzhiyun  * to leverage efi power off for a shutdown.
30*4882a593Smuzhiyun  */
31*4882a593Smuzhiyun bool acpi_no_s5;
32*4882a593Smuzhiyun static u8 sleep_states[ACPI_S_STATE_COUNT];
33*4882a593Smuzhiyun 
acpi_sleep_tts_switch(u32 acpi_state)34*4882a593Smuzhiyun static void acpi_sleep_tts_switch(u32 acpi_state)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	acpi_status status;
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	status = acpi_execute_simple_method(NULL, "\\_TTS", acpi_state);
39*4882a593Smuzhiyun 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
40*4882a593Smuzhiyun 		/*
41*4882a593Smuzhiyun 		 * OS can't evaluate the _TTS object correctly. Some warning
42*4882a593Smuzhiyun 		 * message will be printed. But it won't break anything.
43*4882a593Smuzhiyun 		 */
44*4882a593Smuzhiyun 		printk(KERN_NOTICE "Failure in evaluating _TTS object\n");
45*4882a593Smuzhiyun 	}
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
tts_notify_reboot(struct notifier_block * this,unsigned long code,void * x)48*4882a593Smuzhiyun static int tts_notify_reboot(struct notifier_block *this,
49*4882a593Smuzhiyun 			unsigned long code, void *x)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	acpi_sleep_tts_switch(ACPI_STATE_S5);
52*4882a593Smuzhiyun 	return NOTIFY_DONE;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun static struct notifier_block tts_notifier = {
56*4882a593Smuzhiyun 	.notifier_call	= tts_notify_reboot,
57*4882a593Smuzhiyun 	.next		= NULL,
58*4882a593Smuzhiyun 	.priority	= 0,
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
acpi_sleep_prepare(u32 acpi_state)61*4882a593Smuzhiyun static int acpi_sleep_prepare(u32 acpi_state)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun #ifdef CONFIG_ACPI_SLEEP
64*4882a593Smuzhiyun 	unsigned long acpi_wakeup_address;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	/* do we have a wakeup address for S2 and S3? */
67*4882a593Smuzhiyun 	if (acpi_state == ACPI_STATE_S3) {
68*4882a593Smuzhiyun 		acpi_wakeup_address = acpi_get_wakeup_address();
69*4882a593Smuzhiyun 		if (!acpi_wakeup_address)
70*4882a593Smuzhiyun 			return -EFAULT;
71*4882a593Smuzhiyun 		acpi_set_waking_vector(acpi_wakeup_address);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	}
74*4882a593Smuzhiyun 	ACPI_FLUSH_CPU_CACHE();
75*4882a593Smuzhiyun #endif
76*4882a593Smuzhiyun 	printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n",
77*4882a593Smuzhiyun 		acpi_state);
78*4882a593Smuzhiyun 	acpi_enable_wakeup_devices(acpi_state);
79*4882a593Smuzhiyun 	acpi_enter_sleep_state_prep(acpi_state);
80*4882a593Smuzhiyun 	return 0;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
acpi_sleep_state_supported(u8 sleep_state)83*4882a593Smuzhiyun bool acpi_sleep_state_supported(u8 sleep_state)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	acpi_status status;
86*4882a593Smuzhiyun 	u8 type_a, type_b;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	status = acpi_get_sleep_type_data(sleep_state, &type_a, &type_b);
89*4882a593Smuzhiyun 	return ACPI_SUCCESS(status) && (!acpi_gbl_reduced_hardware
90*4882a593Smuzhiyun 		|| (acpi_gbl_FADT.sleep_control.address
91*4882a593Smuzhiyun 			&& acpi_gbl_FADT.sleep_status.address));
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun #ifdef CONFIG_ACPI_SLEEP
95*4882a593Smuzhiyun static bool sleep_no_lps0 __read_mostly;
96*4882a593Smuzhiyun module_param(sleep_no_lps0, bool, 0644);
97*4882a593Smuzhiyun MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface");
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun static u32 acpi_target_sleep_state = ACPI_STATE_S0;
100*4882a593Smuzhiyun 
acpi_target_system_state(void)101*4882a593Smuzhiyun u32 acpi_target_system_state(void)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	return acpi_target_sleep_state;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(acpi_target_system_state);
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun static bool pwr_btn_event_pending;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun /*
110*4882a593Smuzhiyun  * The ACPI specification wants us to save NVS memory regions during hibernation
111*4882a593Smuzhiyun  * and to restore them during the subsequent resume.  Windows does that also for
112*4882a593Smuzhiyun  * suspend to RAM.  However, it is known that this mechanism does not work on
113*4882a593Smuzhiyun  * all machines, so we allow the user to disable it with the help of the
114*4882a593Smuzhiyun  * 'acpi_sleep=nonvs' kernel command line option.
115*4882a593Smuzhiyun  */
116*4882a593Smuzhiyun static bool nvs_nosave;
117*4882a593Smuzhiyun 
acpi_nvs_nosave(void)118*4882a593Smuzhiyun void __init acpi_nvs_nosave(void)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	nvs_nosave = true;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun /*
124*4882a593Smuzhiyun  * The ACPI specification wants us to save NVS memory regions during hibernation
125*4882a593Smuzhiyun  * but says nothing about saving NVS during S3.  Not all versions of Windows
126*4882a593Smuzhiyun  * save NVS on S3 suspend either, and it is clear that not all systems need
127*4882a593Smuzhiyun  * NVS to be saved at S3 time.  To improve suspend/resume time, allow the
128*4882a593Smuzhiyun  * user to disable saving NVS on S3 if their system does not require it, but
129*4882a593Smuzhiyun  * continue to save/restore NVS for S4 as specified.
130*4882a593Smuzhiyun  */
131*4882a593Smuzhiyun static bool nvs_nosave_s3;
132*4882a593Smuzhiyun 
acpi_nvs_nosave_s3(void)133*4882a593Smuzhiyun void __init acpi_nvs_nosave_s3(void)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	nvs_nosave_s3 = true;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
init_nvs_save_s3(const struct dmi_system_id * d)138*4882a593Smuzhiyun static int __init init_nvs_save_s3(const struct dmi_system_id *d)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	nvs_nosave_s3 = false;
141*4882a593Smuzhiyun 	return 0;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun /*
145*4882a593Smuzhiyun  * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
146*4882a593Smuzhiyun  * user to request that behavior by using the 'acpi_old_suspend_ordering'
147*4882a593Smuzhiyun  * kernel command line option that causes the following variable to be set.
148*4882a593Smuzhiyun  */
149*4882a593Smuzhiyun static bool old_suspend_ordering;
150*4882a593Smuzhiyun 
acpi_old_suspend_ordering(void)151*4882a593Smuzhiyun void __init acpi_old_suspend_ordering(void)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun 	old_suspend_ordering = true;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
init_old_suspend_ordering(const struct dmi_system_id * d)156*4882a593Smuzhiyun static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	acpi_old_suspend_ordering();
159*4882a593Smuzhiyun 	return 0;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
init_nvs_nosave(const struct dmi_system_id * d)162*4882a593Smuzhiyun static int __init init_nvs_nosave(const struct dmi_system_id *d)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun 	acpi_nvs_nosave();
165*4882a593Smuzhiyun 	return 0;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun static bool acpi_sleep_default_s3;
169*4882a593Smuzhiyun 
init_default_s3(const struct dmi_system_id * d)170*4882a593Smuzhiyun static int __init init_default_s3(const struct dmi_system_id *d)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	acpi_sleep_default_s3 = true;
173*4882a593Smuzhiyun 	return 0;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
177*4882a593Smuzhiyun 	{
178*4882a593Smuzhiyun 	.callback = init_old_suspend_ordering,
179*4882a593Smuzhiyun 	.ident = "Abit KN9 (nForce4 variant)",
180*4882a593Smuzhiyun 	.matches = {
181*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
182*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
183*4882a593Smuzhiyun 		},
184*4882a593Smuzhiyun 	},
185*4882a593Smuzhiyun 	{
186*4882a593Smuzhiyun 	.callback = init_old_suspend_ordering,
187*4882a593Smuzhiyun 	.ident = "HP xw4600 Workstation",
188*4882a593Smuzhiyun 	.matches = {
189*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
190*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
191*4882a593Smuzhiyun 		},
192*4882a593Smuzhiyun 	},
193*4882a593Smuzhiyun 	{
194*4882a593Smuzhiyun 	.callback = init_old_suspend_ordering,
195*4882a593Smuzhiyun 	.ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
196*4882a593Smuzhiyun 	.matches = {
197*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."),
198*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_NAME, "M2N8L"),
199*4882a593Smuzhiyun 		},
200*4882a593Smuzhiyun 	},
201*4882a593Smuzhiyun 	{
202*4882a593Smuzhiyun 	.callback = init_old_suspend_ordering,
203*4882a593Smuzhiyun 	.ident = "Panasonic CF51-2L",
204*4882a593Smuzhiyun 	.matches = {
205*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_VENDOR,
206*4882a593Smuzhiyun 				"Matsushita Electric Industrial Co.,Ltd."),
207*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
208*4882a593Smuzhiyun 		},
209*4882a593Smuzhiyun 	},
210*4882a593Smuzhiyun 	{
211*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
212*4882a593Smuzhiyun 	.ident = "Sony Vaio VGN-FW41E_H",
213*4882a593Smuzhiyun 	.matches = {
214*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
215*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW41E_H"),
216*4882a593Smuzhiyun 		},
217*4882a593Smuzhiyun 	},
218*4882a593Smuzhiyun 	{
219*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
220*4882a593Smuzhiyun 	.ident = "Sony Vaio VGN-FW21E",
221*4882a593Smuzhiyun 	.matches = {
222*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
223*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
224*4882a593Smuzhiyun 		},
225*4882a593Smuzhiyun 	},
226*4882a593Smuzhiyun 	{
227*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
228*4882a593Smuzhiyun 	.ident = "Sony Vaio VGN-FW21M",
229*4882a593Smuzhiyun 	.matches = {
230*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
231*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21M"),
232*4882a593Smuzhiyun 		},
233*4882a593Smuzhiyun 	},
234*4882a593Smuzhiyun 	{
235*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
236*4882a593Smuzhiyun 	.ident = "Sony Vaio VPCEB17FX",
237*4882a593Smuzhiyun 	.matches = {
238*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
239*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
240*4882a593Smuzhiyun 		},
241*4882a593Smuzhiyun 	},
242*4882a593Smuzhiyun 	{
243*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
244*4882a593Smuzhiyun 	.ident = "Sony Vaio VGN-SR11M",
245*4882a593Smuzhiyun 	.matches = {
246*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
247*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
248*4882a593Smuzhiyun 		},
249*4882a593Smuzhiyun 	},
250*4882a593Smuzhiyun 	{
251*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
252*4882a593Smuzhiyun 	.ident = "Everex StepNote Series",
253*4882a593Smuzhiyun 	.matches = {
254*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
255*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
256*4882a593Smuzhiyun 		},
257*4882a593Smuzhiyun 	},
258*4882a593Smuzhiyun 	{
259*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
260*4882a593Smuzhiyun 	.ident = "Sony Vaio VPCEB1Z1E",
261*4882a593Smuzhiyun 	.matches = {
262*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
263*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
264*4882a593Smuzhiyun 		},
265*4882a593Smuzhiyun 	},
266*4882a593Smuzhiyun 	{
267*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
268*4882a593Smuzhiyun 	.ident = "Sony Vaio VGN-NW130D",
269*4882a593Smuzhiyun 	.matches = {
270*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
271*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
272*4882a593Smuzhiyun 		},
273*4882a593Smuzhiyun 	},
274*4882a593Smuzhiyun 	{
275*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
276*4882a593Smuzhiyun 	.ident = "Sony Vaio VPCCW29FX",
277*4882a593Smuzhiyun 	.matches = {
278*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
279*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
280*4882a593Smuzhiyun 		},
281*4882a593Smuzhiyun 	},
282*4882a593Smuzhiyun 	{
283*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
284*4882a593Smuzhiyun 	.ident = "Averatec AV1020-ED2",
285*4882a593Smuzhiyun 	.matches = {
286*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
287*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
288*4882a593Smuzhiyun 		},
289*4882a593Smuzhiyun 	},
290*4882a593Smuzhiyun 	{
291*4882a593Smuzhiyun 	.callback = init_old_suspend_ordering,
292*4882a593Smuzhiyun 	.ident = "Asus A8N-SLI DELUXE",
293*4882a593Smuzhiyun 	.matches = {
294*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
295*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"),
296*4882a593Smuzhiyun 		},
297*4882a593Smuzhiyun 	},
298*4882a593Smuzhiyun 	{
299*4882a593Smuzhiyun 	.callback = init_old_suspend_ordering,
300*4882a593Smuzhiyun 	.ident = "Asus A8N-SLI Premium",
301*4882a593Smuzhiyun 	.matches = {
302*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
303*4882a593Smuzhiyun 		DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
304*4882a593Smuzhiyun 		},
305*4882a593Smuzhiyun 	},
306*4882a593Smuzhiyun 	{
307*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
308*4882a593Smuzhiyun 	.ident = "Sony Vaio VGN-SR26GN_P",
309*4882a593Smuzhiyun 	.matches = {
310*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
311*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
312*4882a593Smuzhiyun 		},
313*4882a593Smuzhiyun 	},
314*4882a593Smuzhiyun 	{
315*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
316*4882a593Smuzhiyun 	.ident = "Sony Vaio VPCEB1S1E",
317*4882a593Smuzhiyun 	.matches = {
318*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
319*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"),
320*4882a593Smuzhiyun 		},
321*4882a593Smuzhiyun 	},
322*4882a593Smuzhiyun 	{
323*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
324*4882a593Smuzhiyun 	.ident = "Sony Vaio VGN-FW520F",
325*4882a593Smuzhiyun 	.matches = {
326*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
327*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
328*4882a593Smuzhiyun 		},
329*4882a593Smuzhiyun 	},
330*4882a593Smuzhiyun 	{
331*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
332*4882a593Smuzhiyun 	.ident = "Asus K54C",
333*4882a593Smuzhiyun 	.matches = {
334*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
335*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "K54C"),
336*4882a593Smuzhiyun 		},
337*4882a593Smuzhiyun 	},
338*4882a593Smuzhiyun 	{
339*4882a593Smuzhiyun 	.callback = init_nvs_nosave,
340*4882a593Smuzhiyun 	.ident = "Asus K54HR",
341*4882a593Smuzhiyun 	.matches = {
342*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
343*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
344*4882a593Smuzhiyun 		},
345*4882a593Smuzhiyun 	},
346*4882a593Smuzhiyun 	{
347*4882a593Smuzhiyun 	.callback = init_nvs_save_s3,
348*4882a593Smuzhiyun 	.ident = "Asus 1025C",
349*4882a593Smuzhiyun 	.matches = {
350*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
351*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "1025C"),
352*4882a593Smuzhiyun 		},
353*4882a593Smuzhiyun 	},
354*4882a593Smuzhiyun 	/*
355*4882a593Smuzhiyun 	 * https://bugzilla.kernel.org/show_bug.cgi?id=189431
356*4882a593Smuzhiyun 	 * Lenovo G50-45 is a platform later than 2012, but needs nvs memory
357*4882a593Smuzhiyun 	 * saving during S3.
358*4882a593Smuzhiyun 	 */
359*4882a593Smuzhiyun 	{
360*4882a593Smuzhiyun 	.callback = init_nvs_save_s3,
361*4882a593Smuzhiyun 	.ident = "Lenovo G50-45",
362*4882a593Smuzhiyun 	.matches = {
363*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
364*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "80E3"),
365*4882a593Smuzhiyun 		},
366*4882a593Smuzhiyun 	},
367*4882a593Smuzhiyun 	{
368*4882a593Smuzhiyun 	.callback = init_nvs_save_s3,
369*4882a593Smuzhiyun 	.ident = "Lenovo G40-45",
370*4882a593Smuzhiyun 	.matches = {
371*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
372*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "80E1"),
373*4882a593Smuzhiyun 		},
374*4882a593Smuzhiyun 	},
375*4882a593Smuzhiyun 	/*
376*4882a593Smuzhiyun 	 * ThinkPad X1 Tablet(2016) cannot do suspend-to-idle using
377*4882a593Smuzhiyun 	 * the Low Power S0 Idle firmware interface (see
378*4882a593Smuzhiyun 	 * https://bugzilla.kernel.org/show_bug.cgi?id=199057).
379*4882a593Smuzhiyun 	 */
380*4882a593Smuzhiyun 	{
381*4882a593Smuzhiyun 	.callback = init_default_s3,
382*4882a593Smuzhiyun 	.ident = "ThinkPad X1 Tablet(2016)",
383*4882a593Smuzhiyun 	.matches = {
384*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
385*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "20GGA00L00"),
386*4882a593Smuzhiyun 		},
387*4882a593Smuzhiyun 	},
388*4882a593Smuzhiyun 	/*
389*4882a593Smuzhiyun 	 * ASUS B1400CEAE hangs on resume from suspend (see
390*4882a593Smuzhiyun 	 * https://bugzilla.kernel.org/show_bug.cgi?id=215742).
391*4882a593Smuzhiyun 	 */
392*4882a593Smuzhiyun 	{
393*4882a593Smuzhiyun 	.callback = init_default_s3,
394*4882a593Smuzhiyun 	.ident = "ASUS B1400CEAE",
395*4882a593Smuzhiyun 	.matches = {
396*4882a593Smuzhiyun 		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
397*4882a593Smuzhiyun 		DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK B1400CEAE"),
398*4882a593Smuzhiyun 		},
399*4882a593Smuzhiyun 	},
400*4882a593Smuzhiyun 	{},
401*4882a593Smuzhiyun };
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun static bool ignore_blacklist;
404*4882a593Smuzhiyun 
acpi_sleep_no_blacklist(void)405*4882a593Smuzhiyun void __init acpi_sleep_no_blacklist(void)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	ignore_blacklist = true;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
acpi_sleep_dmi_check(void)410*4882a593Smuzhiyun static void __init acpi_sleep_dmi_check(void)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	if (ignore_blacklist)
413*4882a593Smuzhiyun 		return;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	if (dmi_get_bios_year() >= 2012)
416*4882a593Smuzhiyun 		acpi_nvs_nosave_s3();
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	dmi_check_system(acpisleep_dmi_table);
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun /**
422*4882a593Smuzhiyun  * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
423*4882a593Smuzhiyun  */
acpi_pm_freeze(void)424*4882a593Smuzhiyun static int acpi_pm_freeze(void)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun 	acpi_disable_all_gpes();
427*4882a593Smuzhiyun 	acpi_os_wait_events_complete();
428*4882a593Smuzhiyun 	acpi_ec_block_transactions();
429*4882a593Smuzhiyun 	return 0;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun /**
433*4882a593Smuzhiyun  * acpi_pre_suspend - Enable wakeup devices, "freeze" EC and save NVS.
434*4882a593Smuzhiyun  */
acpi_pm_pre_suspend(void)435*4882a593Smuzhiyun static int acpi_pm_pre_suspend(void)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun 	acpi_pm_freeze();
438*4882a593Smuzhiyun 	return suspend_nvs_save();
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun /**
442*4882a593Smuzhiyun  *	__acpi_pm_prepare - Prepare the platform to enter the target state.
443*4882a593Smuzhiyun  *
444*4882a593Smuzhiyun  *	If necessary, set the firmware waking vector and do arch-specific
445*4882a593Smuzhiyun  *	nastiness to get the wakeup code to the waking vector.
446*4882a593Smuzhiyun  */
__acpi_pm_prepare(void)447*4882a593Smuzhiyun static int __acpi_pm_prepare(void)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	int error = acpi_sleep_prepare(acpi_target_sleep_state);
450*4882a593Smuzhiyun 	if (error)
451*4882a593Smuzhiyun 		acpi_target_sleep_state = ACPI_STATE_S0;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	return error;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun /**
457*4882a593Smuzhiyun  *	acpi_pm_prepare - Prepare the platform to enter the target sleep
458*4882a593Smuzhiyun  *		state and disable the GPEs.
459*4882a593Smuzhiyun  */
acpi_pm_prepare(void)460*4882a593Smuzhiyun static int acpi_pm_prepare(void)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun 	int error = __acpi_pm_prepare();
463*4882a593Smuzhiyun 	if (!error)
464*4882a593Smuzhiyun 		error = acpi_pm_pre_suspend();
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	return error;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun /**
470*4882a593Smuzhiyun  *	acpi_pm_finish - Instruct the platform to leave a sleep state.
471*4882a593Smuzhiyun  *
472*4882a593Smuzhiyun  *	This is called after we wake back up (or if entering the sleep state
473*4882a593Smuzhiyun  *	failed).
474*4882a593Smuzhiyun  */
acpi_pm_finish(void)475*4882a593Smuzhiyun static void acpi_pm_finish(void)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun 	struct acpi_device *pwr_btn_adev;
478*4882a593Smuzhiyun 	u32 acpi_state = acpi_target_sleep_state;
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	acpi_ec_unblock_transactions();
481*4882a593Smuzhiyun 	suspend_nvs_free();
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	if (acpi_state == ACPI_STATE_S0)
484*4882a593Smuzhiyun 		return;
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n",
487*4882a593Smuzhiyun 		acpi_state);
488*4882a593Smuzhiyun 	acpi_disable_wakeup_devices(acpi_state);
489*4882a593Smuzhiyun 	acpi_leave_sleep_state(acpi_state);
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	/* reset firmware waking vector */
492*4882a593Smuzhiyun 	acpi_set_waking_vector(0);
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	acpi_target_sleep_state = ACPI_STATE_S0;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	acpi_resume_power_resources();
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	/* If we were woken with the fixed power button, provide a small
499*4882a593Smuzhiyun 	 * hint to userspace in the form of a wakeup event on the fixed power
500*4882a593Smuzhiyun 	 * button device (if it can be found).
501*4882a593Smuzhiyun 	 *
502*4882a593Smuzhiyun 	 * We delay the event generation til now, as the PM layer requires
503*4882a593Smuzhiyun 	 * timekeeping to be running before we generate events. */
504*4882a593Smuzhiyun 	if (!pwr_btn_event_pending)
505*4882a593Smuzhiyun 		return;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	pwr_btn_event_pending = false;
508*4882a593Smuzhiyun 	pwr_btn_adev = acpi_dev_get_first_match_dev(ACPI_BUTTON_HID_POWERF,
509*4882a593Smuzhiyun 						    NULL, -1);
510*4882a593Smuzhiyun 	if (pwr_btn_adev) {
511*4882a593Smuzhiyun 		pm_wakeup_event(&pwr_btn_adev->dev, 0);
512*4882a593Smuzhiyun 		acpi_dev_put(pwr_btn_adev);
513*4882a593Smuzhiyun 	}
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun /**
517*4882a593Smuzhiyun  * acpi_pm_start - Start system PM transition.
518*4882a593Smuzhiyun  */
acpi_pm_start(u32 acpi_state)519*4882a593Smuzhiyun static void acpi_pm_start(u32 acpi_state)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun 	acpi_target_sleep_state = acpi_state;
522*4882a593Smuzhiyun 	acpi_sleep_tts_switch(acpi_target_sleep_state);
523*4882a593Smuzhiyun 	acpi_scan_lock_acquire();
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun /**
527*4882a593Smuzhiyun  * acpi_pm_end - Finish up system PM transition.
528*4882a593Smuzhiyun  */
acpi_pm_end(void)529*4882a593Smuzhiyun static void acpi_pm_end(void)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun 	acpi_turn_off_unused_power_resources();
532*4882a593Smuzhiyun 	acpi_scan_lock_release();
533*4882a593Smuzhiyun 	/*
534*4882a593Smuzhiyun 	 * This is necessary in case acpi_pm_finish() is not called during a
535*4882a593Smuzhiyun 	 * failing transition to a sleep state.
536*4882a593Smuzhiyun 	 */
537*4882a593Smuzhiyun 	acpi_target_sleep_state = ACPI_STATE_S0;
538*4882a593Smuzhiyun 	acpi_sleep_tts_switch(acpi_target_sleep_state);
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun #else /* !CONFIG_ACPI_SLEEP */
541*4882a593Smuzhiyun #define sleep_no_lps0	(1)
542*4882a593Smuzhiyun #define acpi_target_sleep_state	ACPI_STATE_S0
543*4882a593Smuzhiyun #define acpi_sleep_default_s3	(1)
acpi_sleep_dmi_check(void)544*4882a593Smuzhiyun static inline void acpi_sleep_dmi_check(void) {}
545*4882a593Smuzhiyun #endif /* CONFIG_ACPI_SLEEP */
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun #ifdef CONFIG_SUSPEND
548*4882a593Smuzhiyun static u32 acpi_suspend_states[] = {
549*4882a593Smuzhiyun 	[PM_SUSPEND_ON] = ACPI_STATE_S0,
550*4882a593Smuzhiyun 	[PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
551*4882a593Smuzhiyun 	[PM_SUSPEND_MEM] = ACPI_STATE_S3,
552*4882a593Smuzhiyun 	[PM_SUSPEND_MAX] = ACPI_STATE_S5
553*4882a593Smuzhiyun };
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun /**
556*4882a593Smuzhiyun  *	acpi_suspend_begin - Set the target system sleep state to the state
557*4882a593Smuzhiyun  *		associated with given @pm_state, if supported.
558*4882a593Smuzhiyun  */
acpi_suspend_begin(suspend_state_t pm_state)559*4882a593Smuzhiyun static int acpi_suspend_begin(suspend_state_t pm_state)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun 	u32 acpi_state = acpi_suspend_states[pm_state];
562*4882a593Smuzhiyun 	int error;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
565*4882a593Smuzhiyun 	if (error)
566*4882a593Smuzhiyun 		return error;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	if (!sleep_states[acpi_state]) {
569*4882a593Smuzhiyun 		pr_err("ACPI does not support sleep state S%u\n", acpi_state);
570*4882a593Smuzhiyun 		return -ENOSYS;
571*4882a593Smuzhiyun 	}
572*4882a593Smuzhiyun 	if (acpi_state > ACPI_STATE_S1)
573*4882a593Smuzhiyun 		pm_set_suspend_via_firmware();
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	acpi_pm_start(acpi_state);
576*4882a593Smuzhiyun 	return 0;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun /**
580*4882a593Smuzhiyun  *	acpi_suspend_enter - Actually enter a sleep state.
581*4882a593Smuzhiyun  *	@pm_state: ignored
582*4882a593Smuzhiyun  *
583*4882a593Smuzhiyun  *	Flush caches and go to sleep. For STR we have to call arch-specific
584*4882a593Smuzhiyun  *	assembly, which in turn call acpi_enter_sleep_state().
585*4882a593Smuzhiyun  *	It's unfortunate, but it works. Please fix if you're feeling frisky.
586*4882a593Smuzhiyun  */
acpi_suspend_enter(suspend_state_t pm_state)587*4882a593Smuzhiyun static int acpi_suspend_enter(suspend_state_t pm_state)
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun 	acpi_status status = AE_OK;
590*4882a593Smuzhiyun 	u32 acpi_state = acpi_target_sleep_state;
591*4882a593Smuzhiyun 	int error;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	ACPI_FLUSH_CPU_CACHE();
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true);
596*4882a593Smuzhiyun 	switch (acpi_state) {
597*4882a593Smuzhiyun 	case ACPI_STATE_S1:
598*4882a593Smuzhiyun 		barrier();
599*4882a593Smuzhiyun 		status = acpi_enter_sleep_state(acpi_state);
600*4882a593Smuzhiyun 		break;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	case ACPI_STATE_S3:
603*4882a593Smuzhiyun 		if (!acpi_suspend_lowlevel)
604*4882a593Smuzhiyun 			return -ENOSYS;
605*4882a593Smuzhiyun 		error = acpi_suspend_lowlevel();
606*4882a593Smuzhiyun 		if (error)
607*4882a593Smuzhiyun 			return error;
608*4882a593Smuzhiyun 		pr_info(PREFIX "Low-level resume complete\n");
609*4882a593Smuzhiyun 		pm_set_resume_via_firmware();
610*4882a593Smuzhiyun 		break;
611*4882a593Smuzhiyun 	}
612*4882a593Smuzhiyun 	trace_suspend_resume(TPS("acpi_suspend"), acpi_state, false);
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 	/* This violates the spec but is required for bug compatibility. */
615*4882a593Smuzhiyun 	acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	/* Reprogram control registers */
618*4882a593Smuzhiyun 	acpi_leave_sleep_state_prep(acpi_state);
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	/* ACPI 3.0 specs (P62) says that it's the responsibility
621*4882a593Smuzhiyun 	 * of the OSPM to clear the status bit [ implying that the
622*4882a593Smuzhiyun 	 * POWER_BUTTON event should not reach userspace ]
623*4882a593Smuzhiyun 	 *
624*4882a593Smuzhiyun 	 * However, we do generate a small hint for userspace in the form of
625*4882a593Smuzhiyun 	 * a wakeup event. We flag this condition for now and generate the
626*4882a593Smuzhiyun 	 * event later, as we're currently too early in resume to be able to
627*4882a593Smuzhiyun 	 * generate wakeup events.
628*4882a593Smuzhiyun 	 */
629*4882a593Smuzhiyun 	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) {
630*4882a593Smuzhiyun 		acpi_event_status pwr_btn_status = ACPI_EVENT_FLAG_DISABLED;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 		acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 		if (pwr_btn_status & ACPI_EVENT_FLAG_STATUS_SET) {
635*4882a593Smuzhiyun 			acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
636*4882a593Smuzhiyun 			/* Flag for later */
637*4882a593Smuzhiyun 			pwr_btn_event_pending = true;
638*4882a593Smuzhiyun 		}
639*4882a593Smuzhiyun 	}
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	/*
642*4882a593Smuzhiyun 	 * Disable and clear GPE status before interrupt is enabled. Some GPEs
643*4882a593Smuzhiyun 	 * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
644*4882a593Smuzhiyun 	 * acpi_leave_sleep_state will reenable specific GPEs later
645*4882a593Smuzhiyun 	 */
646*4882a593Smuzhiyun 	acpi_disable_all_gpes();
647*4882a593Smuzhiyun 	/* Allow EC transactions to happen. */
648*4882a593Smuzhiyun 	acpi_ec_unblock_transactions();
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	suspend_nvs_restore();
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun 
acpi_suspend_state_valid(suspend_state_t pm_state)655*4882a593Smuzhiyun static int acpi_suspend_state_valid(suspend_state_t pm_state)
656*4882a593Smuzhiyun {
657*4882a593Smuzhiyun 	u32 acpi_state;
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	switch (pm_state) {
660*4882a593Smuzhiyun 	case PM_SUSPEND_ON:
661*4882a593Smuzhiyun 	case PM_SUSPEND_STANDBY:
662*4882a593Smuzhiyun 	case PM_SUSPEND_MEM:
663*4882a593Smuzhiyun 		acpi_state = acpi_suspend_states[pm_state];
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 		return sleep_states[acpi_state];
666*4882a593Smuzhiyun 	default:
667*4882a593Smuzhiyun 		return 0;
668*4882a593Smuzhiyun 	}
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun static const struct platform_suspend_ops acpi_suspend_ops = {
672*4882a593Smuzhiyun 	.valid = acpi_suspend_state_valid,
673*4882a593Smuzhiyun 	.begin = acpi_suspend_begin,
674*4882a593Smuzhiyun 	.prepare_late = acpi_pm_prepare,
675*4882a593Smuzhiyun 	.enter = acpi_suspend_enter,
676*4882a593Smuzhiyun 	.wake = acpi_pm_finish,
677*4882a593Smuzhiyun 	.end = acpi_pm_end,
678*4882a593Smuzhiyun };
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun /**
681*4882a593Smuzhiyun  *	acpi_suspend_begin_old - Set the target system sleep state to the
682*4882a593Smuzhiyun  *		state associated with given @pm_state, if supported, and
683*4882a593Smuzhiyun  *		execute the _PTS control method.  This function is used if the
684*4882a593Smuzhiyun  *		pre-ACPI 2.0 suspend ordering has been requested.
685*4882a593Smuzhiyun  */
acpi_suspend_begin_old(suspend_state_t pm_state)686*4882a593Smuzhiyun static int acpi_suspend_begin_old(suspend_state_t pm_state)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun 	int error = acpi_suspend_begin(pm_state);
689*4882a593Smuzhiyun 	if (!error)
690*4882a593Smuzhiyun 		error = __acpi_pm_prepare();
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	return error;
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun /*
696*4882a593Smuzhiyun  * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
697*4882a593Smuzhiyun  * been requested.
698*4882a593Smuzhiyun  */
699*4882a593Smuzhiyun static const struct platform_suspend_ops acpi_suspend_ops_old = {
700*4882a593Smuzhiyun 	.valid = acpi_suspend_state_valid,
701*4882a593Smuzhiyun 	.begin = acpi_suspend_begin_old,
702*4882a593Smuzhiyun 	.prepare_late = acpi_pm_pre_suspend,
703*4882a593Smuzhiyun 	.enter = acpi_suspend_enter,
704*4882a593Smuzhiyun 	.wake = acpi_pm_finish,
705*4882a593Smuzhiyun 	.end = acpi_pm_end,
706*4882a593Smuzhiyun 	.recover = acpi_pm_finish,
707*4882a593Smuzhiyun };
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun static bool s2idle_wakeup;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun /*
712*4882a593Smuzhiyun  * On platforms supporting the Low Power S0 Idle interface there is an ACPI
713*4882a593Smuzhiyun  * device object with the PNP0D80 compatible device ID (System Power Management
714*4882a593Smuzhiyun  * Controller) and a specific _DSM method under it.  That method, if present,
715*4882a593Smuzhiyun  * can be used to indicate to the platform that the OS is transitioning into a
716*4882a593Smuzhiyun  * low-power state in which certain types of activity are not desirable or that
717*4882a593Smuzhiyun  * it is leaving such a state, which allows the platform to adjust its operation
718*4882a593Smuzhiyun  * mode accordingly.
719*4882a593Smuzhiyun  */
720*4882a593Smuzhiyun static const struct acpi_device_id lps0_device_ids[] = {
721*4882a593Smuzhiyun 	{"PNP0D80", },
722*4882a593Smuzhiyun 	{"", },
723*4882a593Smuzhiyun };
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun #define ACPI_LPS0_DSM_UUID	"c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun #define ACPI_LPS0_GET_DEVICE_CONSTRAINTS	1
728*4882a593Smuzhiyun #define ACPI_LPS0_SCREEN_OFF	3
729*4882a593Smuzhiyun #define ACPI_LPS0_SCREEN_ON	4
730*4882a593Smuzhiyun #define ACPI_LPS0_ENTRY		5
731*4882a593Smuzhiyun #define ACPI_LPS0_EXIT		6
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun static acpi_handle lps0_device_handle;
734*4882a593Smuzhiyun static guid_t lps0_dsm_guid;
735*4882a593Smuzhiyun static char lps0_dsm_func_mask;
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun /* Device constraint entry structure */
738*4882a593Smuzhiyun struct lpi_device_info {
739*4882a593Smuzhiyun 	char *name;
740*4882a593Smuzhiyun 	int enabled;
741*4882a593Smuzhiyun 	union acpi_object *package;
742*4882a593Smuzhiyun };
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun /* Constraint package structure */
745*4882a593Smuzhiyun struct lpi_device_constraint {
746*4882a593Smuzhiyun 	int uid;
747*4882a593Smuzhiyun 	int min_dstate;
748*4882a593Smuzhiyun 	int function_states;
749*4882a593Smuzhiyun };
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun struct lpi_constraints {
752*4882a593Smuzhiyun 	acpi_handle handle;
753*4882a593Smuzhiyun 	int min_dstate;
754*4882a593Smuzhiyun };
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun static struct lpi_constraints *lpi_constraints_table;
757*4882a593Smuzhiyun static int lpi_constraints_table_size;
758*4882a593Smuzhiyun 
lpi_device_get_constraints(void)759*4882a593Smuzhiyun static void lpi_device_get_constraints(void)
760*4882a593Smuzhiyun {
761*4882a593Smuzhiyun 	union acpi_object *out_obj;
762*4882a593Smuzhiyun 	int i;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
765*4882a593Smuzhiyun 					  1, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
766*4882a593Smuzhiyun 					  NULL, ACPI_TYPE_PACKAGE);
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
769*4882a593Smuzhiyun 			  out_obj ? "successful" : "failed");
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 	if (!out_obj)
772*4882a593Smuzhiyun 		return;
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	lpi_constraints_table = kcalloc(out_obj->package.count,
775*4882a593Smuzhiyun 					sizeof(*lpi_constraints_table),
776*4882a593Smuzhiyun 					GFP_KERNEL);
777*4882a593Smuzhiyun 	if (!lpi_constraints_table)
778*4882a593Smuzhiyun 		goto free_acpi_buffer;
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	acpi_handle_debug(lps0_device_handle, "LPI: constraints list begin:\n");
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 	for (i = 0; i < out_obj->package.count; i++) {
783*4882a593Smuzhiyun 		struct lpi_constraints *constraint;
784*4882a593Smuzhiyun 		acpi_status status;
785*4882a593Smuzhiyun 		union acpi_object *package = &out_obj->package.elements[i];
786*4882a593Smuzhiyun 		struct lpi_device_info info = { };
787*4882a593Smuzhiyun 		int package_count = 0, j;
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 		if (!package)
790*4882a593Smuzhiyun 			continue;
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 		for (j = 0; j < package->package.count; ++j) {
793*4882a593Smuzhiyun 			union acpi_object *element =
794*4882a593Smuzhiyun 					&(package->package.elements[j]);
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun 			switch (element->type) {
797*4882a593Smuzhiyun 			case ACPI_TYPE_INTEGER:
798*4882a593Smuzhiyun 				info.enabled = element->integer.value;
799*4882a593Smuzhiyun 				break;
800*4882a593Smuzhiyun 			case ACPI_TYPE_STRING:
801*4882a593Smuzhiyun 				info.name = element->string.pointer;
802*4882a593Smuzhiyun 				break;
803*4882a593Smuzhiyun 			case ACPI_TYPE_PACKAGE:
804*4882a593Smuzhiyun 				package_count = element->package.count;
805*4882a593Smuzhiyun 				info.package = element->package.elements;
806*4882a593Smuzhiyun 				break;
807*4882a593Smuzhiyun 			}
808*4882a593Smuzhiyun 		}
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 		if (!info.enabled || !info.package || !info.name)
811*4882a593Smuzhiyun 			continue;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 		constraint = &lpi_constraints_table[lpi_constraints_table_size];
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 		status = acpi_get_handle(NULL, info.name, &constraint->handle);
816*4882a593Smuzhiyun 		if (ACPI_FAILURE(status))
817*4882a593Smuzhiyun 			continue;
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 		acpi_handle_debug(lps0_device_handle,
820*4882a593Smuzhiyun 				  "index:%d Name:%s\n", i, info.name);
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 		constraint->min_dstate = -1;
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun 		for (j = 0; j < package_count; ++j) {
825*4882a593Smuzhiyun 			union acpi_object *info_obj = &info.package[j];
826*4882a593Smuzhiyun 			union acpi_object *cnstr_pkg;
827*4882a593Smuzhiyun 			union acpi_object *obj;
828*4882a593Smuzhiyun 			struct lpi_device_constraint dev_info;
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 			switch (info_obj->type) {
831*4882a593Smuzhiyun 			case ACPI_TYPE_INTEGER:
832*4882a593Smuzhiyun 				/* version */
833*4882a593Smuzhiyun 				break;
834*4882a593Smuzhiyun 			case ACPI_TYPE_PACKAGE:
835*4882a593Smuzhiyun 				if (info_obj->package.count < 2)
836*4882a593Smuzhiyun 					break;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 				cnstr_pkg = info_obj->package.elements;
839*4882a593Smuzhiyun 				obj = &cnstr_pkg[0];
840*4882a593Smuzhiyun 				dev_info.uid = obj->integer.value;
841*4882a593Smuzhiyun 				obj = &cnstr_pkg[1];
842*4882a593Smuzhiyun 				dev_info.min_dstate = obj->integer.value;
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 				acpi_handle_debug(lps0_device_handle,
845*4882a593Smuzhiyun 					"uid:%d min_dstate:%s\n",
846*4882a593Smuzhiyun 					dev_info.uid,
847*4882a593Smuzhiyun 					acpi_power_state_string(dev_info.min_dstate));
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 				constraint->min_dstate = dev_info.min_dstate;
850*4882a593Smuzhiyun 				break;
851*4882a593Smuzhiyun 			}
852*4882a593Smuzhiyun 		}
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 		if (constraint->min_dstate < 0) {
855*4882a593Smuzhiyun 			acpi_handle_debug(lps0_device_handle,
856*4882a593Smuzhiyun 					  "Incomplete constraint defined\n");
857*4882a593Smuzhiyun 			continue;
858*4882a593Smuzhiyun 		}
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 		lpi_constraints_table_size++;
861*4882a593Smuzhiyun 	}
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	acpi_handle_debug(lps0_device_handle, "LPI: constraints list end\n");
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun free_acpi_buffer:
866*4882a593Smuzhiyun 	ACPI_FREE(out_obj);
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun 
lpi_check_constraints(void)869*4882a593Smuzhiyun static void lpi_check_constraints(void)
870*4882a593Smuzhiyun {
871*4882a593Smuzhiyun 	int i;
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	for (i = 0; i < lpi_constraints_table_size; ++i) {
874*4882a593Smuzhiyun 		acpi_handle handle = lpi_constraints_table[i].handle;
875*4882a593Smuzhiyun 		struct acpi_device *adev;
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 		if (!handle || acpi_bus_get_device(handle, &adev))
878*4882a593Smuzhiyun 			continue;
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 		acpi_handle_debug(handle,
881*4882a593Smuzhiyun 			"LPI: required min power state:%s current power state:%s\n",
882*4882a593Smuzhiyun 			acpi_power_state_string(lpi_constraints_table[i].min_dstate),
883*4882a593Smuzhiyun 			acpi_power_state_string(adev->power.state));
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun 		if (!adev->flags.power_manageable) {
886*4882a593Smuzhiyun 			acpi_handle_info(handle, "LPI: Device not power manageable\n");
887*4882a593Smuzhiyun 			lpi_constraints_table[i].handle = NULL;
888*4882a593Smuzhiyun 			continue;
889*4882a593Smuzhiyun 		}
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun 		if (adev->power.state < lpi_constraints_table[i].min_dstate)
892*4882a593Smuzhiyun 			acpi_handle_info(handle,
893*4882a593Smuzhiyun 				"LPI: Constraint not met; min power state:%s current power state:%s\n",
894*4882a593Smuzhiyun 				acpi_power_state_string(lpi_constraints_table[i].min_dstate),
895*4882a593Smuzhiyun 				acpi_power_state_string(adev->power.state));
896*4882a593Smuzhiyun 	}
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun 
acpi_sleep_run_lps0_dsm(unsigned int func)899*4882a593Smuzhiyun static void acpi_sleep_run_lps0_dsm(unsigned int func)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun 	union acpi_object *out_obj;
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun 	if (!(lps0_dsm_func_mask & (1 << func)))
904*4882a593Smuzhiyun 		return;
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	out_obj = acpi_evaluate_dsm(lps0_device_handle, &lps0_dsm_guid, 1, func, NULL);
907*4882a593Smuzhiyun 	ACPI_FREE(out_obj);
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	acpi_handle_debug(lps0_device_handle, "_DSM function %u evaluation %s\n",
910*4882a593Smuzhiyun 			  func, out_obj ? "successful" : "failed");
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun 
lps0_device_attach(struct acpi_device * adev,const struct acpi_device_id * not_used)913*4882a593Smuzhiyun static int lps0_device_attach(struct acpi_device *adev,
914*4882a593Smuzhiyun 			      const struct acpi_device_id *not_used)
915*4882a593Smuzhiyun {
916*4882a593Smuzhiyun 	union acpi_object *out_obj;
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	if (lps0_device_handle)
919*4882a593Smuzhiyun 		return 0;
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun 	if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
922*4882a593Smuzhiyun 		return 0;
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid);
925*4882a593Smuzhiyun 	/* Check if the _DSM is present and as expected. */
926*4882a593Smuzhiyun 	out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL);
927*4882a593Smuzhiyun 	if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER) {
928*4882a593Smuzhiyun 		acpi_handle_debug(adev->handle,
929*4882a593Smuzhiyun 				  "_DSM function 0 evaluation failed\n");
930*4882a593Smuzhiyun 		return 0;
931*4882a593Smuzhiyun 	}
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	lps0_dsm_func_mask = *(char *)out_obj->buffer.pointer;
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun 	ACPI_FREE(out_obj);
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
938*4882a593Smuzhiyun 			  lps0_dsm_func_mask);
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 	lps0_device_handle = adev->handle;
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 	lpi_device_get_constraints();
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun 	/*
945*4882a593Smuzhiyun 	 * Use suspend-to-idle by default if the default suspend mode was not
946*4882a593Smuzhiyun 	 * set from the command line.
947*4882a593Smuzhiyun 	 */
948*4882a593Smuzhiyun 	if (mem_sleep_default > PM_SUSPEND_MEM && !acpi_sleep_default_s3)
949*4882a593Smuzhiyun 		mem_sleep_current = PM_SUSPEND_TO_IDLE;
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun 	/*
952*4882a593Smuzhiyun 	 * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
953*4882a593Smuzhiyun 	 * EC GPE to be enabled while suspended for certain wakeup devices to
954*4882a593Smuzhiyun 	 * work, so mark it as wakeup-capable.
955*4882a593Smuzhiyun 	 */
956*4882a593Smuzhiyun 	acpi_ec_mark_gpe_for_wake();
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	return 0;
959*4882a593Smuzhiyun }
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun static struct acpi_scan_handler lps0_handler = {
962*4882a593Smuzhiyun 	.ids = lps0_device_ids,
963*4882a593Smuzhiyun 	.attach = lps0_device_attach,
964*4882a593Smuzhiyun };
965*4882a593Smuzhiyun 
acpi_s2idle_begin(void)966*4882a593Smuzhiyun static int acpi_s2idle_begin(void)
967*4882a593Smuzhiyun {
968*4882a593Smuzhiyun 	acpi_scan_lock_acquire();
969*4882a593Smuzhiyun 	return 0;
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun 
acpi_s2idle_prepare(void)972*4882a593Smuzhiyun static int acpi_s2idle_prepare(void)
973*4882a593Smuzhiyun {
974*4882a593Smuzhiyun 	if (acpi_sci_irq_valid()) {
975*4882a593Smuzhiyun 		enable_irq_wake(acpi_sci_irq);
976*4882a593Smuzhiyun 		acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE);
977*4882a593Smuzhiyun 	}
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun 	acpi_enable_wakeup_devices(ACPI_STATE_S0);
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun 	/* Change the configuration of GPEs to avoid spurious wakeup. */
982*4882a593Smuzhiyun 	acpi_enable_all_wakeup_gpes();
983*4882a593Smuzhiyun 	acpi_os_wait_events_complete();
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	s2idle_wakeup = true;
986*4882a593Smuzhiyun 	return 0;
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun 
acpi_s2idle_prepare_late(void)989*4882a593Smuzhiyun static int acpi_s2idle_prepare_late(void)
990*4882a593Smuzhiyun {
991*4882a593Smuzhiyun 	if (!lps0_device_handle || sleep_no_lps0)
992*4882a593Smuzhiyun 		return 0;
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun 	if (pm_debug_messages_on)
995*4882a593Smuzhiyun 		lpi_check_constraints();
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 	acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
998*4882a593Smuzhiyun 	acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun 	return 0;
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun 
acpi_s2idle_wake(void)1003*4882a593Smuzhiyun static bool acpi_s2idle_wake(void)
1004*4882a593Smuzhiyun {
1005*4882a593Smuzhiyun 	if (!acpi_sci_irq_valid())
1006*4882a593Smuzhiyun 		return pm_wakeup_pending();
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun 	while (pm_wakeup_pending()) {
1009*4882a593Smuzhiyun 		/*
1010*4882a593Smuzhiyun 		 * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the
1011*4882a593Smuzhiyun 		 * SCI has not triggered while suspended, so bail out (the
1012*4882a593Smuzhiyun 		 * wakeup is pending anyway and the SCI is not the source of
1013*4882a593Smuzhiyun 		 * it).
1014*4882a593Smuzhiyun 		 */
1015*4882a593Smuzhiyun 		if (irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq))) {
1016*4882a593Smuzhiyun 			pm_pr_dbg("Wakeup unrelated to ACPI SCI\n");
1017*4882a593Smuzhiyun 			return true;
1018*4882a593Smuzhiyun 		}
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun 		/*
1021*4882a593Smuzhiyun 		 * If the status bit of any enabled fixed event is set, the
1022*4882a593Smuzhiyun 		 * wakeup is regarded as valid.
1023*4882a593Smuzhiyun 		 */
1024*4882a593Smuzhiyun 		if (acpi_any_fixed_event_status_set()) {
1025*4882a593Smuzhiyun 			pm_pr_dbg("ACPI fixed event wakeup\n");
1026*4882a593Smuzhiyun 			return true;
1027*4882a593Smuzhiyun 		}
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 		/* Check wakeups from drivers sharing the SCI. */
1030*4882a593Smuzhiyun 		if (acpi_check_wakeup_handlers()) {
1031*4882a593Smuzhiyun 			pm_pr_dbg("ACPI custom handler wakeup\n");
1032*4882a593Smuzhiyun 			return true;
1033*4882a593Smuzhiyun 		}
1034*4882a593Smuzhiyun 
1035*4882a593Smuzhiyun 		/* Check non-EC GPE wakeups and dispatch the EC GPE. */
1036*4882a593Smuzhiyun 		if (acpi_ec_dispatch_gpe()) {
1037*4882a593Smuzhiyun 			pm_pr_dbg("ACPI non-EC GPE wakeup\n");
1038*4882a593Smuzhiyun 			return true;
1039*4882a593Smuzhiyun 		}
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun 		/*
1042*4882a593Smuzhiyun 		 * Cancel the SCI wakeup and process all pending events in case
1043*4882a593Smuzhiyun 		 * there are any wakeup ones in there.
1044*4882a593Smuzhiyun 		 *
1045*4882a593Smuzhiyun 		 * Note that if any non-EC GPEs are active at this point, the
1046*4882a593Smuzhiyun 		 * SCI will retrigger after the rearming below, so no events
1047*4882a593Smuzhiyun 		 * should be missed by canceling the wakeup here.
1048*4882a593Smuzhiyun 		 */
1049*4882a593Smuzhiyun 		pm_system_cancel_wakeup();
1050*4882a593Smuzhiyun 		acpi_os_wait_events_complete();
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun 		/*
1053*4882a593Smuzhiyun 		 * The SCI is in the "suspended" state now and it cannot produce
1054*4882a593Smuzhiyun 		 * new wakeup events till the rearming below, so if any of them
1055*4882a593Smuzhiyun 		 * are pending here, they must be resulting from the processing
1056*4882a593Smuzhiyun 		 * of EC events above or coming from somewhere else.
1057*4882a593Smuzhiyun 		 */
1058*4882a593Smuzhiyun 		if (pm_wakeup_pending()) {
1059*4882a593Smuzhiyun 			pm_pr_dbg("Wakeup after ACPI Notify sync\n");
1060*4882a593Smuzhiyun 			return true;
1061*4882a593Smuzhiyun 		}
1062*4882a593Smuzhiyun 
1063*4882a593Smuzhiyun 		pm_wakeup_clear(acpi_sci_irq);
1064*4882a593Smuzhiyun 		rearm_wake_irq(acpi_sci_irq);
1065*4882a593Smuzhiyun 	}
1066*4882a593Smuzhiyun 
1067*4882a593Smuzhiyun 	return false;
1068*4882a593Smuzhiyun }
1069*4882a593Smuzhiyun 
acpi_s2idle_restore_early(void)1070*4882a593Smuzhiyun static void acpi_s2idle_restore_early(void)
1071*4882a593Smuzhiyun {
1072*4882a593Smuzhiyun 	if (!lps0_device_handle || sleep_no_lps0)
1073*4882a593Smuzhiyun 		return;
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 	acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
1076*4882a593Smuzhiyun 	acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
1077*4882a593Smuzhiyun }
1078*4882a593Smuzhiyun 
acpi_s2idle_restore(void)1079*4882a593Smuzhiyun static void acpi_s2idle_restore(void)
1080*4882a593Smuzhiyun {
1081*4882a593Smuzhiyun 	/*
1082*4882a593Smuzhiyun 	 * Drain pending events before restoring the working-state configuration
1083*4882a593Smuzhiyun 	 * of GPEs.
1084*4882a593Smuzhiyun 	 */
1085*4882a593Smuzhiyun 	acpi_os_wait_events_complete(); /* synchronize GPE processing */
1086*4882a593Smuzhiyun 	acpi_ec_flush_work(); /* flush the EC driver's workqueues */
1087*4882a593Smuzhiyun 	acpi_os_wait_events_complete(); /* synchronize Notify handling */
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun 	s2idle_wakeup = false;
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	acpi_enable_all_runtime_gpes();
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 	acpi_disable_wakeup_devices(ACPI_STATE_S0);
1094*4882a593Smuzhiyun 
1095*4882a593Smuzhiyun 	if (acpi_sci_irq_valid()) {
1096*4882a593Smuzhiyun 		acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE);
1097*4882a593Smuzhiyun 		disable_irq_wake(acpi_sci_irq);
1098*4882a593Smuzhiyun 	}
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun 
acpi_s2idle_end(void)1101*4882a593Smuzhiyun static void acpi_s2idle_end(void)
1102*4882a593Smuzhiyun {
1103*4882a593Smuzhiyun 	acpi_scan_lock_release();
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun static const struct platform_s2idle_ops acpi_s2idle_ops = {
1107*4882a593Smuzhiyun 	.begin = acpi_s2idle_begin,
1108*4882a593Smuzhiyun 	.prepare = acpi_s2idle_prepare,
1109*4882a593Smuzhiyun 	.prepare_late = acpi_s2idle_prepare_late,
1110*4882a593Smuzhiyun 	.wake = acpi_s2idle_wake,
1111*4882a593Smuzhiyun 	.restore_early = acpi_s2idle_restore_early,
1112*4882a593Smuzhiyun 	.restore = acpi_s2idle_restore,
1113*4882a593Smuzhiyun 	.end = acpi_s2idle_end,
1114*4882a593Smuzhiyun };
1115*4882a593Smuzhiyun 
acpi_sleep_suspend_setup(void)1116*4882a593Smuzhiyun static void acpi_sleep_suspend_setup(void)
1117*4882a593Smuzhiyun {
1118*4882a593Smuzhiyun 	int i;
1119*4882a593Smuzhiyun 
1120*4882a593Smuzhiyun 	for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++)
1121*4882a593Smuzhiyun 		if (acpi_sleep_state_supported(i))
1122*4882a593Smuzhiyun 			sleep_states[i] = 1;
1123*4882a593Smuzhiyun 
1124*4882a593Smuzhiyun 	suspend_set_ops(old_suspend_ordering ?
1125*4882a593Smuzhiyun 		&acpi_suspend_ops_old : &acpi_suspend_ops);
1126*4882a593Smuzhiyun 
1127*4882a593Smuzhiyun 	acpi_scan_add_handler(&lps0_handler);
1128*4882a593Smuzhiyun 	s2idle_set_ops(&acpi_s2idle_ops);
1129*4882a593Smuzhiyun }
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun #else /* !CONFIG_SUSPEND */
1132*4882a593Smuzhiyun #define s2idle_wakeup		(false)
1133*4882a593Smuzhiyun #define lps0_device_handle	(NULL)
acpi_sleep_suspend_setup(void)1134*4882a593Smuzhiyun static inline void acpi_sleep_suspend_setup(void) {}
1135*4882a593Smuzhiyun #endif /* !CONFIG_SUSPEND */
1136*4882a593Smuzhiyun 
acpi_s2idle_wakeup(void)1137*4882a593Smuzhiyun bool acpi_s2idle_wakeup(void)
1138*4882a593Smuzhiyun {
1139*4882a593Smuzhiyun 	return s2idle_wakeup;
1140*4882a593Smuzhiyun }
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
1143*4882a593Smuzhiyun static u32 saved_bm_rld;
1144*4882a593Smuzhiyun 
acpi_save_bm_rld(void)1145*4882a593Smuzhiyun static int  acpi_save_bm_rld(void)
1146*4882a593Smuzhiyun {
1147*4882a593Smuzhiyun 	acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld);
1148*4882a593Smuzhiyun 	return 0;
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun 
acpi_restore_bm_rld(void)1151*4882a593Smuzhiyun static void  acpi_restore_bm_rld(void)
1152*4882a593Smuzhiyun {
1153*4882a593Smuzhiyun 	u32 resumed_bm_rld = 0;
1154*4882a593Smuzhiyun 
1155*4882a593Smuzhiyun 	acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld);
1156*4882a593Smuzhiyun 	if (resumed_bm_rld == saved_bm_rld)
1157*4882a593Smuzhiyun 		return;
1158*4882a593Smuzhiyun 
1159*4882a593Smuzhiyun 	acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
1160*4882a593Smuzhiyun }
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun static struct syscore_ops acpi_sleep_syscore_ops = {
1163*4882a593Smuzhiyun 	.suspend = acpi_save_bm_rld,
1164*4882a593Smuzhiyun 	.resume = acpi_restore_bm_rld,
1165*4882a593Smuzhiyun };
1166*4882a593Smuzhiyun 
acpi_sleep_syscore_init(void)1167*4882a593Smuzhiyun static void acpi_sleep_syscore_init(void)
1168*4882a593Smuzhiyun {
1169*4882a593Smuzhiyun 	register_syscore_ops(&acpi_sleep_syscore_ops);
1170*4882a593Smuzhiyun }
1171*4882a593Smuzhiyun #else
acpi_sleep_syscore_init(void)1172*4882a593Smuzhiyun static inline void acpi_sleep_syscore_init(void) {}
1173*4882a593Smuzhiyun #endif /* CONFIG_PM_SLEEP */
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun #ifdef CONFIG_HIBERNATION
1176*4882a593Smuzhiyun static unsigned long s4_hardware_signature;
1177*4882a593Smuzhiyun static struct acpi_table_facs *facs;
1178*4882a593Smuzhiyun static bool nosigcheck;
1179*4882a593Smuzhiyun 
acpi_no_s4_hw_signature(void)1180*4882a593Smuzhiyun void __init acpi_no_s4_hw_signature(void)
1181*4882a593Smuzhiyun {
1182*4882a593Smuzhiyun 	nosigcheck = true;
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun 
acpi_hibernation_begin(pm_message_t stage)1185*4882a593Smuzhiyun static int acpi_hibernation_begin(pm_message_t stage)
1186*4882a593Smuzhiyun {
1187*4882a593Smuzhiyun 	if (!nvs_nosave) {
1188*4882a593Smuzhiyun 		int error = suspend_nvs_alloc();
1189*4882a593Smuzhiyun 		if (error)
1190*4882a593Smuzhiyun 			return error;
1191*4882a593Smuzhiyun 	}
1192*4882a593Smuzhiyun 
1193*4882a593Smuzhiyun 	if (stage.event == PM_EVENT_HIBERNATE)
1194*4882a593Smuzhiyun 		pm_set_suspend_via_firmware();
1195*4882a593Smuzhiyun 
1196*4882a593Smuzhiyun 	acpi_pm_start(ACPI_STATE_S4);
1197*4882a593Smuzhiyun 	return 0;
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun 
acpi_hibernation_enter(void)1200*4882a593Smuzhiyun static int acpi_hibernation_enter(void)
1201*4882a593Smuzhiyun {
1202*4882a593Smuzhiyun 	acpi_status status = AE_OK;
1203*4882a593Smuzhiyun 
1204*4882a593Smuzhiyun 	ACPI_FLUSH_CPU_CACHE();
1205*4882a593Smuzhiyun 
1206*4882a593Smuzhiyun 	/* This shouldn't return.  If it returns, we have a problem */
1207*4882a593Smuzhiyun 	status = acpi_enter_sleep_state(ACPI_STATE_S4);
1208*4882a593Smuzhiyun 	/* Reprogram control registers */
1209*4882a593Smuzhiyun 	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
1212*4882a593Smuzhiyun }
1213*4882a593Smuzhiyun 
acpi_hibernation_leave(void)1214*4882a593Smuzhiyun static void acpi_hibernation_leave(void)
1215*4882a593Smuzhiyun {
1216*4882a593Smuzhiyun 	pm_set_resume_via_firmware();
1217*4882a593Smuzhiyun 	/*
1218*4882a593Smuzhiyun 	 * If ACPI is not enabled by the BIOS and the boot kernel, we need to
1219*4882a593Smuzhiyun 	 * enable it here.
1220*4882a593Smuzhiyun 	 */
1221*4882a593Smuzhiyun 	acpi_enable();
1222*4882a593Smuzhiyun 	/* Reprogram control registers */
1223*4882a593Smuzhiyun 	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
1224*4882a593Smuzhiyun 	/* Check the hardware signature */
1225*4882a593Smuzhiyun 	if (facs && s4_hardware_signature != facs->hardware_signature)
1226*4882a593Smuzhiyun 		pr_crit("ACPI: Hardware changed while hibernated, success doubtful!\n");
1227*4882a593Smuzhiyun 	/* Restore the NVS memory area */
1228*4882a593Smuzhiyun 	suspend_nvs_restore();
1229*4882a593Smuzhiyun 	/* Allow EC transactions to happen. */
1230*4882a593Smuzhiyun 	acpi_ec_unblock_transactions();
1231*4882a593Smuzhiyun }
1232*4882a593Smuzhiyun 
acpi_pm_thaw(void)1233*4882a593Smuzhiyun static void acpi_pm_thaw(void)
1234*4882a593Smuzhiyun {
1235*4882a593Smuzhiyun 	acpi_ec_unblock_transactions();
1236*4882a593Smuzhiyun 	acpi_enable_all_runtime_gpes();
1237*4882a593Smuzhiyun }
1238*4882a593Smuzhiyun 
1239*4882a593Smuzhiyun static const struct platform_hibernation_ops acpi_hibernation_ops = {
1240*4882a593Smuzhiyun 	.begin = acpi_hibernation_begin,
1241*4882a593Smuzhiyun 	.end = acpi_pm_end,
1242*4882a593Smuzhiyun 	.pre_snapshot = acpi_pm_prepare,
1243*4882a593Smuzhiyun 	.finish = acpi_pm_finish,
1244*4882a593Smuzhiyun 	.prepare = acpi_pm_prepare,
1245*4882a593Smuzhiyun 	.enter = acpi_hibernation_enter,
1246*4882a593Smuzhiyun 	.leave = acpi_hibernation_leave,
1247*4882a593Smuzhiyun 	.pre_restore = acpi_pm_freeze,
1248*4882a593Smuzhiyun 	.restore_cleanup = acpi_pm_thaw,
1249*4882a593Smuzhiyun };
1250*4882a593Smuzhiyun 
1251*4882a593Smuzhiyun /**
1252*4882a593Smuzhiyun  *	acpi_hibernation_begin_old - Set the target system sleep state to
1253*4882a593Smuzhiyun  *		ACPI_STATE_S4 and execute the _PTS control method.  This
1254*4882a593Smuzhiyun  *		function is used if the pre-ACPI 2.0 suspend ordering has been
1255*4882a593Smuzhiyun  *		requested.
1256*4882a593Smuzhiyun  */
acpi_hibernation_begin_old(pm_message_t stage)1257*4882a593Smuzhiyun static int acpi_hibernation_begin_old(pm_message_t stage)
1258*4882a593Smuzhiyun {
1259*4882a593Smuzhiyun 	int error;
1260*4882a593Smuzhiyun 	/*
1261*4882a593Smuzhiyun 	 * The _TTS object should always be evaluated before the _PTS object.
1262*4882a593Smuzhiyun 	 * When the old_suspended_ordering is true, the _PTS object is
1263*4882a593Smuzhiyun 	 * evaluated in the acpi_sleep_prepare.
1264*4882a593Smuzhiyun 	 */
1265*4882a593Smuzhiyun 	acpi_sleep_tts_switch(ACPI_STATE_S4);
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun 	error = acpi_sleep_prepare(ACPI_STATE_S4);
1268*4882a593Smuzhiyun 	if (error)
1269*4882a593Smuzhiyun 		return error;
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun 	if (!nvs_nosave) {
1272*4882a593Smuzhiyun 		error = suspend_nvs_alloc();
1273*4882a593Smuzhiyun 		if (error)
1274*4882a593Smuzhiyun 			return error;
1275*4882a593Smuzhiyun 	}
1276*4882a593Smuzhiyun 
1277*4882a593Smuzhiyun 	if (stage.event == PM_EVENT_HIBERNATE)
1278*4882a593Smuzhiyun 		pm_set_suspend_via_firmware();
1279*4882a593Smuzhiyun 
1280*4882a593Smuzhiyun 	acpi_target_sleep_state = ACPI_STATE_S4;
1281*4882a593Smuzhiyun 	acpi_scan_lock_acquire();
1282*4882a593Smuzhiyun 	return 0;
1283*4882a593Smuzhiyun }
1284*4882a593Smuzhiyun 
1285*4882a593Smuzhiyun /*
1286*4882a593Smuzhiyun  * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has
1287*4882a593Smuzhiyun  * been requested.
1288*4882a593Smuzhiyun  */
1289*4882a593Smuzhiyun static const struct platform_hibernation_ops acpi_hibernation_ops_old = {
1290*4882a593Smuzhiyun 	.begin = acpi_hibernation_begin_old,
1291*4882a593Smuzhiyun 	.end = acpi_pm_end,
1292*4882a593Smuzhiyun 	.pre_snapshot = acpi_pm_pre_suspend,
1293*4882a593Smuzhiyun 	.prepare = acpi_pm_freeze,
1294*4882a593Smuzhiyun 	.finish = acpi_pm_finish,
1295*4882a593Smuzhiyun 	.enter = acpi_hibernation_enter,
1296*4882a593Smuzhiyun 	.leave = acpi_hibernation_leave,
1297*4882a593Smuzhiyun 	.pre_restore = acpi_pm_freeze,
1298*4882a593Smuzhiyun 	.restore_cleanup = acpi_pm_thaw,
1299*4882a593Smuzhiyun 	.recover = acpi_pm_finish,
1300*4882a593Smuzhiyun };
1301*4882a593Smuzhiyun 
acpi_sleep_hibernate_setup(void)1302*4882a593Smuzhiyun static void acpi_sleep_hibernate_setup(void)
1303*4882a593Smuzhiyun {
1304*4882a593Smuzhiyun 	if (!acpi_sleep_state_supported(ACPI_STATE_S4))
1305*4882a593Smuzhiyun 		return;
1306*4882a593Smuzhiyun 
1307*4882a593Smuzhiyun 	hibernation_set_ops(old_suspend_ordering ?
1308*4882a593Smuzhiyun 			&acpi_hibernation_ops_old : &acpi_hibernation_ops);
1309*4882a593Smuzhiyun 	sleep_states[ACPI_STATE_S4] = 1;
1310*4882a593Smuzhiyun 	if (nosigcheck)
1311*4882a593Smuzhiyun 		return;
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun 	acpi_get_table(ACPI_SIG_FACS, 1, (struct acpi_table_header **)&facs);
1314*4882a593Smuzhiyun 	if (facs)
1315*4882a593Smuzhiyun 		s4_hardware_signature = facs->hardware_signature;
1316*4882a593Smuzhiyun }
1317*4882a593Smuzhiyun #else /* !CONFIG_HIBERNATION */
acpi_sleep_hibernate_setup(void)1318*4882a593Smuzhiyun static inline void acpi_sleep_hibernate_setup(void) {}
1319*4882a593Smuzhiyun #endif /* !CONFIG_HIBERNATION */
1320*4882a593Smuzhiyun 
acpi_power_off_prepare(void)1321*4882a593Smuzhiyun static void acpi_power_off_prepare(void)
1322*4882a593Smuzhiyun {
1323*4882a593Smuzhiyun 	/* Prepare to power off the system */
1324*4882a593Smuzhiyun 	acpi_sleep_prepare(ACPI_STATE_S5);
1325*4882a593Smuzhiyun 	acpi_disable_all_gpes();
1326*4882a593Smuzhiyun 	acpi_os_wait_events_complete();
1327*4882a593Smuzhiyun }
1328*4882a593Smuzhiyun 
acpi_power_off(void)1329*4882a593Smuzhiyun static void acpi_power_off(void)
1330*4882a593Smuzhiyun {
1331*4882a593Smuzhiyun 	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
1332*4882a593Smuzhiyun 	printk(KERN_DEBUG "%s called\n", __func__);
1333*4882a593Smuzhiyun 	local_irq_disable();
1334*4882a593Smuzhiyun 	acpi_enter_sleep_state(ACPI_STATE_S5);
1335*4882a593Smuzhiyun }
1336*4882a593Smuzhiyun 
acpi_sleep_init(void)1337*4882a593Smuzhiyun int __init acpi_sleep_init(void)
1338*4882a593Smuzhiyun {
1339*4882a593Smuzhiyun 	char supported[ACPI_S_STATE_COUNT * 3 + 1];
1340*4882a593Smuzhiyun 	char *pos = supported;
1341*4882a593Smuzhiyun 	int i;
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun 	acpi_sleep_dmi_check();
1344*4882a593Smuzhiyun 
1345*4882a593Smuzhiyun 	sleep_states[ACPI_STATE_S0] = 1;
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun 	acpi_sleep_syscore_init();
1348*4882a593Smuzhiyun 	acpi_sleep_suspend_setup();
1349*4882a593Smuzhiyun 	acpi_sleep_hibernate_setup();
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun 	if (acpi_sleep_state_supported(ACPI_STATE_S5)) {
1352*4882a593Smuzhiyun 		sleep_states[ACPI_STATE_S5] = 1;
1353*4882a593Smuzhiyun 		pm_power_off_prepare = acpi_power_off_prepare;
1354*4882a593Smuzhiyun 		pm_power_off = acpi_power_off;
1355*4882a593Smuzhiyun 	} else {
1356*4882a593Smuzhiyun 		acpi_no_s5 = true;
1357*4882a593Smuzhiyun 	}
1358*4882a593Smuzhiyun 
1359*4882a593Smuzhiyun 	supported[0] = 0;
1360*4882a593Smuzhiyun 	for (i = 0; i < ACPI_S_STATE_COUNT; i++) {
1361*4882a593Smuzhiyun 		if (sleep_states[i])
1362*4882a593Smuzhiyun 			pos += sprintf(pos, " S%d", i);
1363*4882a593Smuzhiyun 	}
1364*4882a593Smuzhiyun 	pr_info(PREFIX "(supports%s)\n", supported);
1365*4882a593Smuzhiyun 
1366*4882a593Smuzhiyun 	/*
1367*4882a593Smuzhiyun 	 * Register the tts_notifier to reboot notifier list so that the _TTS
1368*4882a593Smuzhiyun 	 * object can also be evaluated when the system enters S5.
1369*4882a593Smuzhiyun 	 */
1370*4882a593Smuzhiyun 	register_reboot_notifier(&tts_notifier);
1371*4882a593Smuzhiyun 	return 0;
1372*4882a593Smuzhiyun }
1373