]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/acpi/acpica/hwsleep.c
ACPICA: Distill multiple sleep method functions to a single function
[mirror_ubuntu-hirsute-kernel.git] / drivers / acpi / acpica / hwsleep.c
CommitLineData
1da177e4
LT
1/******************************************************************************
2 *
2feec47d 3 * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support Functions
1da177e4
LT
4 *
5 *****************************************************************************/
6
7/*
77848130 8 * Copyright (C) 2000 - 2012, Intel Corp.
1da177e4
LT
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
1da177e4 44#include <acpi/acpi.h>
e2f7a777 45#include "accommon.h"
69575d38 46#include <linux/tboot.h>
cc4b859c 47#include <linux/module.h>
1da177e4
LT
48
49#define _COMPONENT ACPI_HARDWARE
4be44fcd 50ACPI_MODULE_NAME("hwsleep")
1da177e4 51
2feec47d
BM
52static unsigned int gts, bfs;
53module_param(gts, uint, 0644);
54module_param(bfs, uint, 0644);
55MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend.");
56MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".);
57
44f6c012 58/*******************************************************************************
1da177e4 59 *
f99648b1 60 * FUNCTION: acpi_hw_execute_sleep_method
1da177e4 61 *
f99648b1
BM
62 * PARAMETERS: method_name - Pathname of method to execute
63 * integer_argument - Argument to pass to the method
1da177e4 64 *
2feec47d 65 * RETURN: None
1da177e4 66 *
f99648b1
BM
67 * DESCRIPTION: Execute a sleep/wake related method, with one integer argument
68 * and no return value.
1da177e4
LT
69 *
70 ******************************************************************************/
f99648b1 71void acpi_hw_execute_sleep_method(char *method_name, u32 integer_argument)
2feec47d
BM
72{
73 struct acpi_object_list arg_list;
74 union acpi_object arg;
75 acpi_status status;
a6629105 76
f99648b1 77 ACPI_FUNCTION_TRACE(hw_execute_sleep_method);
d85988fa 78
f99648b1
BM
79 if (!ACPI_STRCMP(METHOD_NAME__GTS, method_name) && !gts)
80 return_VOID;
d85988fa 81
f99648b1
BM
82 if (!ACPI_STRCMP(METHOD_NAME__BFS, method_name) && !bfs)
83 return_VOID;
d85988fa 84
f99648b1 85 /* One argument, integer_argument */
d85988fa 86
2feec47d
BM
87 arg_list.count = 1;
88 arg_list.pointer = &arg;
89 arg.type = ACPI_TYPE_INTEGER;
f99648b1 90 arg.integer.value = (u64)integer_argument;
1da177e4 91
f99648b1 92 status = acpi_evaluate_object(NULL, method_name, &arg_list, NULL);
2feec47d 93 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
f99648b1
BM
94 ACPI_EXCEPTION((AE_INFO, status, "While executing method %s",
95 method_name));
2feec47d 96 }
8313524a 97
f99648b1 98 return_VOID;
1da177e4
LT
99}
100
33620c54 101#if (!ACPI_REDUCED_HARDWARE)
44f6c012 102/*******************************************************************************
1da177e4 103 *
2feec47d 104 * FUNCTION: acpi_hw_legacy_sleep
1da177e4
LT
105 *
106 * PARAMETERS: sleep_state - Which sleep state to enter
107 *
108 * RETURN: Status
109 *
2feec47d 110 * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
1da177e4
LT
111 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
112 *
113 ******************************************************************************/
2feec47d
BM
114
115acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
1da177e4 116{
4be44fcd
LB
117 struct acpi_bit_register_info *sleep_type_reg_info;
118 struct acpi_bit_register_info *sleep_enable_reg_info;
2feec47d
BM
119 u32 pm1a_control;
120 u32 pm1b_control;
4be44fcd
LB
121 u32 in_value;
122 acpi_status status;
1da177e4 123
2feec47d 124 ACPI_FUNCTION_TRACE(hw_legacy_sleep);
1da177e4 125
4be44fcd 126 sleep_type_reg_info =
82d79b86 127 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
4be44fcd
LB
128 sleep_enable_reg_info =
129 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
1da177e4
LT
130
131 /* Clear wake status */
132
768aaaf1
BM
133 status =
134 acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
4be44fcd
LB
135 if (ACPI_FAILURE(status)) {
136 return_ACPI_STATUS(status);
1da177e4
LT
137 }
138
139 /* Clear all fixed and general purpose status bits */
140
d8c71b6d 141 status = acpi_hw_clear_acpi_status();
4be44fcd
LB
142 if (ACPI_FAILURE(status)) {
143 return_ACPI_STATUS(status);
1da177e4
LT
144 }
145
2feec47d
BM
146 if (sleep_state != ACPI_STATE_S5) {
147 /*
148 * Disable BM arbitration. This feature is contained within an
149 * optional register (PM2 Control), so ignore a BAD_ADDRESS
150 * exception.
151 */
152 status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
153 if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
154 return_ACPI_STATUS(status);
155 }
156 }
157
1da177e4 158 /*
23b168d4 159 * 1) Disable/Clear all GPEs
1da177e4
LT
160 * 2) Enable all wakeup GPEs
161 */
1d99967b
AS
162 status = acpi_hw_disable_all_gpes();
163 if (ACPI_FAILURE(status)) {
164 return_ACPI_STATUS(status);
165 }
1da177e4
LT
166 acpi_gbl_system_awake_and_running = FALSE;
167
4be44fcd
LB
168 status = acpi_hw_enable_all_wakeup_gpes();
169 if (ACPI_FAILURE(status)) {
170 return_ACPI_STATUS(status);
1da177e4
LT
171 }
172
2feec47d 173 /* Execute the _GTS method (Going To Sleep) */
c95d47a8 174
f99648b1 175 acpi_hw_execute_sleep_method(METHOD_NAME__GTS, sleep_state);
c95d47a8 176
1da177e4
LT
177 /* Get current value of PM1A control */
178
32c9ef99
BM
179 status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
180 &pm1a_control);
4be44fcd
LB
181 if (ACPI_FAILURE(status)) {
182 return_ACPI_STATUS(status);
1da177e4 183 }
4be44fcd 184 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
b27d6597 185 "Entering sleep state [S%u]\n", sleep_state));
1da177e4 186
32c9ef99 187 /* Clear the SLP_EN and SLP_TYP fields */
1da177e4 188
32c9ef99
BM
189 pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
190 sleep_enable_reg_info->access_bit_mask);
191 pm1b_control = pm1a_control;
1da177e4 192
32c9ef99 193 /* Insert the SLP_TYP bits */
1da177e4 194
32c9ef99 195 pm1a_control |=
4be44fcd 196 (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
32c9ef99 197 pm1b_control |=
4be44fcd 198 (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
1da177e4
LT
199
200 /*
201 * We split the writes of SLP_TYP and SLP_EN to workaround
202 * poorly implemented hardware.
203 */
204
32c9ef99 205 /* Write #1: write the SLP_TYP data to the PM1 Control registers */
1da177e4 206
32c9ef99 207 status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
4be44fcd
LB
208 if (ACPI_FAILURE(status)) {
209 return_ACPI_STATUS(status);
1da177e4
LT
210 }
211
32c9ef99 212 /* Insert the sleep enable (SLP_EN) bit */
1da177e4 213
32c9ef99
BM
214 pm1a_control |= sleep_enable_reg_info->access_bit_mask;
215 pm1b_control |= sleep_enable_reg_info->access_bit_mask;
1da177e4 216
32c9ef99 217 /* Flush caches, as per ACPI specification */
1da177e4 218
4be44fcd 219 ACPI_FLUSH_CPU_CACHE();
1da177e4 220
86886e55
JC
221 tboot_sleep(sleep_state, pm1a_control, pm1b_control);
222
32c9ef99 223 /* Write #2: Write both SLP_TYP + SLP_EN */
1da177e4 224
32c9ef99 225 status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
4be44fcd
LB
226 if (ACPI_FAILURE(status)) {
227 return_ACPI_STATUS(status);
1da177e4
LT
228 }
229
230 if (sleep_state > ACPI_STATE_S3) {
231 /*
44f6c012
RM
232 * We wanted to sleep > S3, but it didn't happen (by virtue of the
233 * fact that we are still executing!)
1da177e4 234 *
44f6c012
RM
235 * Wait ten seconds, then try again. This is to get S4/S5 to work on
236 * all machines.
1da177e4 237 *
d4913dc6
BM
238 * We wait so long to allow chipsets that poll this reg very slowly
239 * to still read the right value. Ideally, this block would go
1da177e4
LT
240 * away entirely.
241 */
4be44fcd
LB
242 acpi_os_stall(10000000);
243
d30dc9ab 244 status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
4be44fcd
LB
245 sleep_enable_reg_info->
246 access_bit_mask);
247 if (ACPI_FAILURE(status)) {
248 return_ACPI_STATUS(status);
1da177e4
LT
249 }
250 }
251
2feec47d 252 /* Wait for transition back to Working State */
1da177e4
LT
253
254 do {
50ffba1b
BM
255 status =
256 acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
4be44fcd
LB
257 if (ACPI_FAILURE(status)) {
258 return_ACPI_STATUS(status);
1da177e4 259 }
2feec47d 260
1da177e4
LT
261 } while (!in_value);
262
4be44fcd 263 return_ACPI_STATUS(AE_OK);
1da177e4 264}
1da177e4 265
44f6c012 266/*******************************************************************************
1da177e4 267 *
2feec47d 268 * FUNCTION: acpi_hw_legacy_wake_prep
1da177e4 269 *
2feec47d 270 * PARAMETERS: sleep_state - Which sleep state we just exited
1da177e4
LT
271 *
272 * RETURN: Status
273 *
c95d47a8
RW
274 * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
275 * sleep.
2feec47d 276 * Called with interrupts ENABLED.
1da177e4
LT
277 *
278 ******************************************************************************/
2feec47d
BM
279
280acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state)
1da177e4 281{
4be44fcd
LB
282 acpi_status status;
283 struct acpi_bit_register_info *sleep_type_reg_info;
284 struct acpi_bit_register_info *sleep_enable_reg_info;
32c9ef99
BM
285 u32 pm1a_control;
286 u32 pm1b_control;
1da177e4 287
2feec47d 288 ACPI_FUNCTION_TRACE(hw_legacy_wake_prep);
1da177e4
LT
289
290 /*
291 * Set SLP_TYPE and SLP_EN to state S0.
292 * This is unclear from the ACPI Spec, but it is required
293 * by some machines.
294 */
4be44fcd
LB
295 status = acpi_get_sleep_type_data(ACPI_STATE_S0,
296 &acpi_gbl_sleep_type_a,
297 &acpi_gbl_sleep_type_b);
298 if (ACPI_SUCCESS(status)) {
299 sleep_type_reg_info =
82d79b86 300 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
4be44fcd
LB
301 sleep_enable_reg_info =
302 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
1da177e4
LT
303
304 /* Get current value of PM1A control */
305
d30dc9ab 306 status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
32c9ef99 307 &pm1a_control);
4be44fcd 308 if (ACPI_SUCCESS(status)) {
52fc0b02 309
32c9ef99 310 /* Clear the SLP_EN and SLP_TYP fields */
1da177e4 311
32c9ef99
BM
312 pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
313 sleep_enable_reg_info->
314 access_bit_mask);
315 pm1b_control = pm1a_control;
1da177e4 316
32c9ef99 317 /* Insert the SLP_TYP bits */
1da177e4 318
d4913dc6
BM
319 pm1a_control |= (acpi_gbl_sleep_type_a <<
320 sleep_type_reg_info->bit_position);
321 pm1b_control |= (acpi_gbl_sleep_type_b <<
322 sleep_type_reg_info->bit_position);
1da177e4 323
32c9ef99 324 /* Write the control registers and ignore any errors */
1da177e4 325
32c9ef99
BM
326 (void)acpi_hw_write_pm1_control(pm1a_control,
327 pm1b_control);
1da177e4
LT
328 }
329 }
330
f99648b1 331 acpi_hw_execute_sleep_method(METHOD_NAME__BFS, sleep_state);
c95d47a8
RW
332 return_ACPI_STATUS(status);
333}
334
335/*******************************************************************************
336 *
2feec47d 337 * FUNCTION: acpi_hw_legacy_wake
c95d47a8
RW
338 *
339 * PARAMETERS: sleep_state - Which sleep state we just exited
340 *
341 * RETURN: Status
342 *
343 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
344 * Called with interrupts ENABLED.
345 *
346 ******************************************************************************/
2feec47d
BM
347
348acpi_status acpi_hw_legacy_wake(u8 sleep_state)
c95d47a8 349{
c95d47a8
RW
350 acpi_status status;
351
2feec47d 352 ACPI_FUNCTION_TRACE(hw_legacy_wake);
c95d47a8 353
1da177e4
LT
354 /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
355
356 acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
f99648b1 357 acpi_hw_execute_sleep_method(METHOD_NAME__SST, ACPI_SST_WAKING);
1da177e4 358
1da177e4 359 /*
79d2dfaa
TR
360 * GPEs must be enabled before _WAK is called as GPEs
361 * might get fired there
362 *
1da177e4
LT
363 * Restore the GPEs:
364 * 1) Disable/Clear all GPEs
365 * 2) Enable all runtime GPEs
366 */
4be44fcd
LB
367 status = acpi_hw_disable_all_gpes();
368 if (ACPI_FAILURE(status)) {
369 return_ACPI_STATUS(status);
1da177e4 370 }
2feec47d 371
4be44fcd
LB
372 status = acpi_hw_enable_all_runtime_gpes();
373 if (ACPI_FAILURE(status)) {
374 return_ACPI_STATUS(status);
1da177e4
LT
375 }
376
2feec47d
BM
377 /*
378 * Now we can execute _WAK, etc. Some machines require that the GPEs
379 * are enabled before the wake methods are executed.
380 */
f99648b1 381 acpi_hw_execute_sleep_method(METHOD_NAME__WAK, sleep_state);
79d2dfaa 382
a68823ee 383 /*
2feec47d
BM
384 * Some BIOS code assumes that WAK_STS will be cleared on resume
385 * and use it to determine whether the system is rebooting or
386 * resuming. Clear WAK_STS for compatibility.
a68823ee 387 */
50ffba1b 388 acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1);
79d2dfaa
TR
389 acpi_gbl_system_awake_and_running = TRUE;
390
1da177e4
LT
391 /* Enable power button */
392
4be44fcd 393 (void)
50ffba1b 394 acpi_write_bit_register(acpi_gbl_fixed_event_info
2feec47d
BM
395 [ACPI_EVENT_POWER_BUTTON].
396 enable_register_id, ACPI_ENABLE_EVENT);
44f6c012 397
4be44fcd 398 (void)
50ffba1b 399 acpi_write_bit_register(acpi_gbl_fixed_event_info
2feec47d
BM
400 [ACPI_EVENT_POWER_BUTTON].
401 status_register_id, ACPI_CLEAR_STATUS);
1da177e4 402
2feec47d
BM
403 /*
404 * Enable BM arbitration. This feature is contained within an
405 * optional register (PM2 Control), so ignore a BAD_ADDRESS
406 * exception.
407 */
408 status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
409 if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
410 return_ACPI_STATUS(status);
1da177e4
LT
411 }
412
f99648b1 413 acpi_hw_execute_sleep_method(METHOD_NAME__SST, ACPI_SST_WORKING);
4be44fcd 414 return_ACPI_STATUS(status);
1da177e4 415}
8313524a 416
33620c54 417#endif /* !ACPI_REDUCED_HARDWARE */
2feec47d
BM
418
419/*******************************************************************************
420 *
421 * FUNCTION: acpi_hw_extended_sleep
422 *
423 * PARAMETERS: sleep_state - Which sleep state to enter
424 *
425 * RETURN: Status
426 *
427 * DESCRIPTION: Enter a system sleep state via the extended FADT sleep
428 * registers (V5 FADT).
429 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
430 *
431 ******************************************************************************/
432
433acpi_status acpi_hw_extended_sleep(u8 sleep_state)
434{
435 acpi_status status;
436 u8 sleep_type_value;
437 u64 sleep_status;
438
439 ACPI_FUNCTION_TRACE(hw_extended_sleep);
440
441 /* Extended sleep registers must be valid */
442
443 if (!acpi_gbl_FADT.sleep_control.address ||
444 !acpi_gbl_FADT.sleep_status.address) {
445 return_ACPI_STATUS(AE_NOT_EXIST);
446 }
447
448 /* Clear wake status (WAK_STS) */
449
450 status = acpi_write(ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
451 if (ACPI_FAILURE(status)) {
452 return_ACPI_STATUS(status);
453 }
454
455 acpi_gbl_system_awake_and_running = FALSE;
456
457 /* Execute the _GTS method (Going To Sleep) */
458
f99648b1 459 acpi_hw_execute_sleep_method(METHOD_NAME__GTS, sleep_state);
2feec47d
BM
460
461 /* Flush caches, as per ACPI specification */
462
463 ACPI_FLUSH_CPU_CACHE();
464
465 /*
466 * Set the SLP_TYP and SLP_EN bits.
467 *
468 * Note: We only use the first value returned by the \_Sx method
469 * (acpi_gbl_sleep_type_a) - As per ACPI specification.
470 */
471 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
472 "Entering sleep state [S%u]\n", sleep_state));
473
474 sleep_type_value =
475 ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
476 ACPI_X_SLEEP_TYPE_MASK);
477
478 status = acpi_write((sleep_type_value | ACPI_X_SLEEP_ENABLE),
479 &acpi_gbl_FADT.sleep_control);
480 if (ACPI_FAILURE(status)) {
481 return_ACPI_STATUS(status);
482 }
483
484 /* Wait for transition back to Working State */
485
486 do {
487 status = acpi_read(&sleep_status, &acpi_gbl_FADT.sleep_status);
488 if (ACPI_FAILURE(status)) {
489 return_ACPI_STATUS(status);
490 }
491
492 } while (!(((u8)sleep_status) & ACPI_X_WAKE_STATUS));
493
494 return_ACPI_STATUS(AE_OK);
495}
496
497/*******************************************************************************
498 *
499 * FUNCTION: acpi_hw_extended_wake_prep
500 *
501 * PARAMETERS: sleep_state - Which sleep state we just exited
502 *
503 * RETURN: Status
504 *
505 * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
506 * a sleep. Called with interrupts ENABLED.
507 *
508 ******************************************************************************/
509
510acpi_status acpi_hw_extended_wake_prep(u8 sleep_state)
511{
512 acpi_status status;
513 u8 sleep_type_value;
514
515 ACPI_FUNCTION_TRACE(hw_extended_wake_prep);
516
517 status = acpi_get_sleep_type_data(ACPI_STATE_S0,
518 &acpi_gbl_sleep_type_a,
519 &acpi_gbl_sleep_type_b);
520 if (ACPI_SUCCESS(status)) {
521 sleep_type_value =
522 ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
523 ACPI_X_SLEEP_TYPE_MASK);
524
525 (void)acpi_write((sleep_type_value | ACPI_X_SLEEP_ENABLE),
526 &acpi_gbl_FADT.sleep_control);
527 }
528
f99648b1 529 acpi_hw_execute_sleep_method(METHOD_NAME__BFS, sleep_state);
2feec47d
BM
530 return_ACPI_STATUS(AE_OK);
531}
532
533/*******************************************************************************
534 *
535 * FUNCTION: acpi_hw_extended_wake
536 *
537 * PARAMETERS: sleep_state - Which sleep state we just exited
538 *
539 * RETURN: Status
540 *
541 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
542 * Called with interrupts ENABLED.
543 *
544 ******************************************************************************/
545
546acpi_status acpi_hw_extended_wake(u8 sleep_state)
547{
548 ACPI_FUNCTION_TRACE(hw_extended_wake);
549
550 /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
551
552 acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
553
554 /* Execute the wake methods */
555
f99648b1
BM
556 acpi_hw_execute_sleep_method(METHOD_NAME__SST, ACPI_SST_WAKING);
557 acpi_hw_execute_sleep_method(METHOD_NAME__WAK, sleep_state);
2feec47d
BM
558
559 /*
560 * Some BIOS code assumes that WAK_STS will be cleared on resume
561 * and use it to determine whether the system is rebooting or
562 * resuming. Clear WAK_STS for compatibility.
563 */
564 (void)acpi_write(ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
565 acpi_gbl_system_awake_and_running = TRUE;
566
f99648b1 567 acpi_hw_execute_sleep_method(METHOD_NAME__SST, ACPI_SST_WORKING);
2feec47d
BM
568 return_ACPI_STATUS(AE_OK);
569}