]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/acpi/acpica/hwsleep.c
ACPICA: Move ACPI timer prototypes to public acpixf file
[mirror_ubuntu-bionic-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
52/* Local prototypes */
53static void acpi_hw_execute_GTS(u8 sleep_state);
54
55static void acpi_hw_execute_BFS(u8 sleep_state);
56
57static void acpi_hw_execute_WAK(u8 sleep_state);
58
59static unsigned int gts, bfs;
60module_param(gts, uint, 0644);
61module_param(bfs, uint, 0644);
62MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend.");
63MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".);
64
44f6c012 65/*******************************************************************************
1da177e4 66 *
2feec47d 67 * FUNCTION: acpi_hw_execute_GTS
1da177e4 68 *
2feec47d 69 * PARAMETERS: sleep_state - Sleep state that will be entered
1da177e4 70 *
2feec47d 71 * RETURN: None
1da177e4 72 *
2feec47d 73 * DESCRIPTION: Execute the optional _GTS method (Going To Sleep)
1da177e4
LT
74 *
75 ******************************************************************************/
f3d2e786 76
2feec47d
BM
77static void acpi_hw_execute_GTS(u8 sleep_state)
78{
79 struct acpi_object_list arg_list;
80 union acpi_object arg;
81 acpi_status status;
a6629105 82
2feec47d
BM
83 if (!gts)
84 return;
d85988fa 85
2feec47d 86 /* One argument, sleep_state */
d85988fa 87
2feec47d
BM
88 arg_list.count = 1;
89 arg_list.pointer = &arg;
90 arg.type = ACPI_TYPE_INTEGER;
91 arg.integer.value = sleep_state;
d85988fa 92
2feec47d
BM
93 status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
94 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
95 ACPI_EXCEPTION((AE_INFO, status,
96 "While executing method _GTS"));
d85988fa 97 }
1da177e4
LT
98}
99
44f6c012 100/*******************************************************************************
1da177e4 101 *
2feec47d 102 * FUNCTION: acpi_hw_execute_BFS
1da177e4 103 *
2feec47d 104 * PARAMETERS: sleep_state - Which sleep state we just exited
1da177e4 105 *
2feec47d 106 * RETURN: None
1da177e4 107 *
2feec47d 108 * DESCRIPTION: Execute the optional _BFS method (Back From Sleep)
1da177e4
LT
109 *
110 ******************************************************************************/
1da177e4 111
2feec47d
BM
112static void acpi_hw_execute_BFS(u8 sleep_state)
113{
114 struct acpi_object_list arg_list;
115 union acpi_object arg;
116 acpi_status status;
d85988fa 117
2feec47d
BM
118 if (!bfs)
119 return;
d85988fa 120
2feec47d 121 /* One argument, sleep_state */
d85988fa 122
2feec47d
BM
123 arg_list.count = 1;
124 arg_list.pointer = &arg;
125 arg.type = ACPI_TYPE_INTEGER;
126 arg.integer.value = sleep_state;
1da177e4 127
2feec47d
BM
128 status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
129 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
130 ACPI_EXCEPTION((AE_INFO, status,
131 "While executing method _BFS"));
132 }
1da177e4 133}
8313524a 134
44f6c012 135/*******************************************************************************
1da177e4 136 *
2feec47d 137 * FUNCTION: acpi_hw_execute_WAK
1da177e4 138 *
2feec47d 139 * PARAMETERS: sleep_state - Which sleep state we just exited
1da177e4 140 *
2feec47d 141 * RETURN: None
1da177e4 142 *
2feec47d 143 * DESCRIPTION: Execute the _WAK method (System Wake)
1da177e4
LT
144 *
145 ******************************************************************************/
2feec47d
BM
146
147static void acpi_hw_execute_WAK(u8 sleep_state)
1da177e4 148{
4be44fcd
LB
149 struct acpi_object_list arg_list;
150 union acpi_object arg;
2feec47d 151 acpi_status status;
1da177e4 152
2feec47d 153 /* One argument, sleep_state */
1da177e4
LT
154
155 arg_list.count = 1;
156 arg_list.pointer = &arg;
1da177e4
LT
157 arg.type = ACPI_TYPE_INTEGER;
158 arg.integer.value = sleep_state;
159
2feec47d 160 status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
4be44fcd 161 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
2feec47d
BM
162 ACPI_EXCEPTION((AE_INFO, status,
163 "While executing method _WAK"));
1da177e4 164 }
2feec47d
BM
165 /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
166}
1da177e4 167
2feec47d
BM
168/*******************************************************************************
169 *
170 * FUNCTION: acpi_hw_execute_SST
171 *
172 * PARAMETERS: indicator_id - Value to be passed to the _SST method
173 *
174 * RETURN: None
175 *
176 * DESCRIPTION: Execute the optional _SST method (System Status)
177 *
178 ******************************************************************************/
1da177e4 179
2feec47d
BM
180void acpi_hw_execute_SST(u32 indicator_id)
181{
182 struct acpi_object_list arg_list;
183 union acpi_object arg;
184 acpi_status status;
1da177e4 185
2feec47d 186 /* One argument, status indicator ID */
1da177e4 187
2feec47d
BM
188 arg_list.count = 1;
189 arg_list.pointer = &arg;
190 arg.type = ACPI_TYPE_INTEGER;
1da177e4 191
2feec47d 192 arg.integer.value = indicator_id;
4be44fcd
LB
193 status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
194 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
b8e4d893
BM
195 ACPI_EXCEPTION((AE_INFO, status,
196 "While executing method _SST"));
1da177e4 197 }
1da177e4
LT
198}
199
44f6c012 200/*******************************************************************************
1da177e4 201 *
2feec47d 202 * FUNCTION: acpi_hw_legacy_sleep
1da177e4
LT
203 *
204 * PARAMETERS: sleep_state - Which sleep state to enter
205 *
206 * RETURN: Status
207 *
2feec47d 208 * DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
1da177e4
LT
209 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
210 *
211 ******************************************************************************/
2feec47d
BM
212
213acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
1da177e4 214{
4be44fcd
LB
215 struct acpi_bit_register_info *sleep_type_reg_info;
216 struct acpi_bit_register_info *sleep_enable_reg_info;
2feec47d
BM
217 u32 pm1a_control;
218 u32 pm1b_control;
4be44fcd
LB
219 u32 in_value;
220 acpi_status status;
1da177e4 221
2feec47d 222 ACPI_FUNCTION_TRACE(hw_legacy_sleep);
1da177e4 223
4be44fcd 224 sleep_type_reg_info =
82d79b86 225 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
4be44fcd
LB
226 sleep_enable_reg_info =
227 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
1da177e4
LT
228
229 /* Clear wake status */
230
768aaaf1
BM
231 status =
232 acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
4be44fcd
LB
233 if (ACPI_FAILURE(status)) {
234 return_ACPI_STATUS(status);
1da177e4
LT
235 }
236
237 /* Clear all fixed and general purpose status bits */
238
d8c71b6d 239 status = acpi_hw_clear_acpi_status();
4be44fcd
LB
240 if (ACPI_FAILURE(status)) {
241 return_ACPI_STATUS(status);
1da177e4
LT
242 }
243
2feec47d
BM
244 if (sleep_state != ACPI_STATE_S5) {
245 /*
246 * Disable BM arbitration. This feature is contained within an
247 * optional register (PM2 Control), so ignore a BAD_ADDRESS
248 * exception.
249 */
250 status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
251 if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
252 return_ACPI_STATUS(status);
253 }
254 }
255
1da177e4 256 /*
23b168d4 257 * 1) Disable/Clear all GPEs
1da177e4
LT
258 * 2) Enable all wakeup GPEs
259 */
1d99967b
AS
260 status = acpi_hw_disable_all_gpes();
261 if (ACPI_FAILURE(status)) {
262 return_ACPI_STATUS(status);
263 }
1da177e4
LT
264 acpi_gbl_system_awake_and_running = FALSE;
265
4be44fcd
LB
266 status = acpi_hw_enable_all_wakeup_gpes();
267 if (ACPI_FAILURE(status)) {
268 return_ACPI_STATUS(status);
1da177e4
LT
269 }
270
2feec47d 271 /* Execute the _GTS method (Going To Sleep) */
c95d47a8 272
2feec47d 273 acpi_hw_execute_GTS(sleep_state);
c95d47a8 274
1da177e4
LT
275 /* Get current value of PM1A control */
276
32c9ef99
BM
277 status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
278 &pm1a_control);
4be44fcd
LB
279 if (ACPI_FAILURE(status)) {
280 return_ACPI_STATUS(status);
1da177e4 281 }
4be44fcd 282 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
b27d6597 283 "Entering sleep state [S%u]\n", sleep_state));
1da177e4 284
32c9ef99 285 /* Clear the SLP_EN and SLP_TYP fields */
1da177e4 286
32c9ef99
BM
287 pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
288 sleep_enable_reg_info->access_bit_mask);
289 pm1b_control = pm1a_control;
1da177e4 290
32c9ef99 291 /* Insert the SLP_TYP bits */
1da177e4 292
32c9ef99 293 pm1a_control |=
4be44fcd 294 (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
32c9ef99 295 pm1b_control |=
4be44fcd 296 (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
1da177e4
LT
297
298 /*
299 * We split the writes of SLP_TYP and SLP_EN to workaround
300 * poorly implemented hardware.
301 */
302
32c9ef99 303 /* Write #1: write the SLP_TYP data to the PM1 Control registers */
1da177e4 304
32c9ef99 305 status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
4be44fcd
LB
306 if (ACPI_FAILURE(status)) {
307 return_ACPI_STATUS(status);
1da177e4
LT
308 }
309
32c9ef99 310 /* Insert the sleep enable (SLP_EN) bit */
1da177e4 311
32c9ef99
BM
312 pm1a_control |= sleep_enable_reg_info->access_bit_mask;
313 pm1b_control |= sleep_enable_reg_info->access_bit_mask;
1da177e4 314
32c9ef99 315 /* Flush caches, as per ACPI specification */
1da177e4 316
4be44fcd 317 ACPI_FLUSH_CPU_CACHE();
1da177e4 318
86886e55
JC
319 tboot_sleep(sleep_state, pm1a_control, pm1b_control);
320
32c9ef99 321 /* Write #2: Write both SLP_TYP + SLP_EN */
1da177e4 322
32c9ef99 323 status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
4be44fcd
LB
324 if (ACPI_FAILURE(status)) {
325 return_ACPI_STATUS(status);
1da177e4
LT
326 }
327
328 if (sleep_state > ACPI_STATE_S3) {
329 /*
44f6c012
RM
330 * We wanted to sleep > S3, but it didn't happen (by virtue of the
331 * fact that we are still executing!)
1da177e4 332 *
44f6c012
RM
333 * Wait ten seconds, then try again. This is to get S4/S5 to work on
334 * all machines.
1da177e4 335 *
d4913dc6
BM
336 * We wait so long to allow chipsets that poll this reg very slowly
337 * to still read the right value. Ideally, this block would go
1da177e4
LT
338 * away entirely.
339 */
4be44fcd
LB
340 acpi_os_stall(10000000);
341
d30dc9ab 342 status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
4be44fcd
LB
343 sleep_enable_reg_info->
344 access_bit_mask);
345 if (ACPI_FAILURE(status)) {
346 return_ACPI_STATUS(status);
1da177e4
LT
347 }
348 }
349
2feec47d 350 /* Wait for transition back to Working State */
1da177e4
LT
351
352 do {
50ffba1b
BM
353 status =
354 acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
4be44fcd
LB
355 if (ACPI_FAILURE(status)) {
356 return_ACPI_STATUS(status);
1da177e4 357 }
2feec47d 358
1da177e4
LT
359 } while (!in_value);
360
4be44fcd 361 return_ACPI_STATUS(AE_OK);
1da177e4 362}
1da177e4 363
44f6c012 364/*******************************************************************************
1da177e4 365 *
2feec47d 366 * FUNCTION: acpi_hw_legacy_wake_prep
1da177e4 367 *
2feec47d 368 * PARAMETERS: sleep_state - Which sleep state we just exited
1da177e4
LT
369 *
370 * RETURN: Status
371 *
c95d47a8
RW
372 * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
373 * sleep.
2feec47d 374 * Called with interrupts ENABLED.
1da177e4
LT
375 *
376 ******************************************************************************/
2feec47d
BM
377
378acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state)
1da177e4 379{
4be44fcd
LB
380 acpi_status status;
381 struct acpi_bit_register_info *sleep_type_reg_info;
382 struct acpi_bit_register_info *sleep_enable_reg_info;
32c9ef99
BM
383 u32 pm1a_control;
384 u32 pm1b_control;
1da177e4 385
2feec47d 386 ACPI_FUNCTION_TRACE(hw_legacy_wake_prep);
1da177e4
LT
387
388 /*
389 * Set SLP_TYPE and SLP_EN to state S0.
390 * This is unclear from the ACPI Spec, but it is required
391 * by some machines.
392 */
4be44fcd
LB
393 status = acpi_get_sleep_type_data(ACPI_STATE_S0,
394 &acpi_gbl_sleep_type_a,
395 &acpi_gbl_sleep_type_b);
396 if (ACPI_SUCCESS(status)) {
397 sleep_type_reg_info =
82d79b86 398 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
4be44fcd
LB
399 sleep_enable_reg_info =
400 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
1da177e4
LT
401
402 /* Get current value of PM1A control */
403
d30dc9ab 404 status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
32c9ef99 405 &pm1a_control);
4be44fcd 406 if (ACPI_SUCCESS(status)) {
52fc0b02 407
32c9ef99 408 /* Clear the SLP_EN and SLP_TYP fields */
1da177e4 409
32c9ef99
BM
410 pm1a_control &= ~(sleep_type_reg_info->access_bit_mask |
411 sleep_enable_reg_info->
412 access_bit_mask);
413 pm1b_control = pm1a_control;
1da177e4 414
32c9ef99 415 /* Insert the SLP_TYP bits */
1da177e4 416
d4913dc6
BM
417 pm1a_control |= (acpi_gbl_sleep_type_a <<
418 sleep_type_reg_info->bit_position);
419 pm1b_control |= (acpi_gbl_sleep_type_b <<
420 sleep_type_reg_info->bit_position);
1da177e4 421
32c9ef99 422 /* Write the control registers and ignore any errors */
1da177e4 423
32c9ef99
BM
424 (void)acpi_hw_write_pm1_control(pm1a_control,
425 pm1b_control);
1da177e4
LT
426 }
427 }
428
2feec47d 429 acpi_hw_execute_BFS(sleep_state);
c95d47a8
RW
430 return_ACPI_STATUS(status);
431}
432
433/*******************************************************************************
434 *
2feec47d 435 * FUNCTION: acpi_hw_legacy_wake
c95d47a8
RW
436 *
437 * PARAMETERS: sleep_state - Which sleep state we just exited
438 *
439 * RETURN: Status
440 *
441 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
442 * Called with interrupts ENABLED.
443 *
444 ******************************************************************************/
2feec47d
BM
445
446acpi_status acpi_hw_legacy_wake(u8 sleep_state)
c95d47a8 447{
c95d47a8
RW
448 acpi_status status;
449
2feec47d 450 ACPI_FUNCTION_TRACE(hw_legacy_wake);
c95d47a8 451
1da177e4
LT
452 /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
453
454 acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
2feec47d 455 acpi_hw_execute_SST(ACPI_SST_WAKING);
1da177e4 456
1da177e4 457 /*
79d2dfaa
TR
458 * GPEs must be enabled before _WAK is called as GPEs
459 * might get fired there
460 *
1da177e4
LT
461 * Restore the GPEs:
462 * 1) Disable/Clear all GPEs
463 * 2) Enable all runtime GPEs
464 */
4be44fcd
LB
465 status = acpi_hw_disable_all_gpes();
466 if (ACPI_FAILURE(status)) {
467 return_ACPI_STATUS(status);
1da177e4 468 }
2feec47d 469
4be44fcd
LB
470 status = acpi_hw_enable_all_runtime_gpes();
471 if (ACPI_FAILURE(status)) {
472 return_ACPI_STATUS(status);
1da177e4
LT
473 }
474
2feec47d
BM
475 /*
476 * Now we can execute _WAK, etc. Some machines require that the GPEs
477 * are enabled before the wake methods are executed.
478 */
479 acpi_hw_execute_WAK(sleep_state);
79d2dfaa 480
a68823ee 481 /*
2feec47d
BM
482 * Some BIOS code assumes that WAK_STS will be cleared on resume
483 * and use it to determine whether the system is rebooting or
484 * resuming. Clear WAK_STS for compatibility.
a68823ee 485 */
50ffba1b 486 acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1);
79d2dfaa
TR
487 acpi_gbl_system_awake_and_running = TRUE;
488
1da177e4
LT
489 /* Enable power button */
490
4be44fcd 491 (void)
50ffba1b 492 acpi_write_bit_register(acpi_gbl_fixed_event_info
2feec47d
BM
493 [ACPI_EVENT_POWER_BUTTON].
494 enable_register_id, ACPI_ENABLE_EVENT);
44f6c012 495
4be44fcd 496 (void)
50ffba1b 497 acpi_write_bit_register(acpi_gbl_fixed_event_info
2feec47d
BM
498 [ACPI_EVENT_POWER_BUTTON].
499 status_register_id, ACPI_CLEAR_STATUS);
1da177e4 500
2feec47d
BM
501 /*
502 * Enable BM arbitration. This feature is contained within an
503 * optional register (PM2 Control), so ignore a BAD_ADDRESS
504 * exception.
505 */
506 status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
507 if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
508 return_ACPI_STATUS(status);
1da177e4
LT
509 }
510
2feec47d 511 acpi_hw_execute_SST(ACPI_SST_WORKING);
4be44fcd 512 return_ACPI_STATUS(status);
1da177e4 513}
8313524a 514
2feec47d
BM
515
516/*******************************************************************************
517 *
518 * FUNCTION: acpi_hw_extended_sleep
519 *
520 * PARAMETERS: sleep_state - Which sleep state to enter
521 *
522 * RETURN: Status
523 *
524 * DESCRIPTION: Enter a system sleep state via the extended FADT sleep
525 * registers (V5 FADT).
526 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
527 *
528 ******************************************************************************/
529
530acpi_status acpi_hw_extended_sleep(u8 sleep_state)
531{
532 acpi_status status;
533 u8 sleep_type_value;
534 u64 sleep_status;
535
536 ACPI_FUNCTION_TRACE(hw_extended_sleep);
537
538 /* Extended sleep registers must be valid */
539
540 if (!acpi_gbl_FADT.sleep_control.address ||
541 !acpi_gbl_FADT.sleep_status.address) {
542 return_ACPI_STATUS(AE_NOT_EXIST);
543 }
544
545 /* Clear wake status (WAK_STS) */
546
547 status = acpi_write(ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
548 if (ACPI_FAILURE(status)) {
549 return_ACPI_STATUS(status);
550 }
551
552 acpi_gbl_system_awake_and_running = FALSE;
553
554 /* Execute the _GTS method (Going To Sleep) */
555
556 acpi_hw_execute_GTS(sleep_state);
557
558 /* Flush caches, as per ACPI specification */
559
560 ACPI_FLUSH_CPU_CACHE();
561
562 /*
563 * Set the SLP_TYP and SLP_EN bits.
564 *
565 * Note: We only use the first value returned by the \_Sx method
566 * (acpi_gbl_sleep_type_a) - As per ACPI specification.
567 */
568 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
569 "Entering sleep state [S%u]\n", sleep_state));
570
571 sleep_type_value =
572 ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
573 ACPI_X_SLEEP_TYPE_MASK);
574
575 status = acpi_write((sleep_type_value | ACPI_X_SLEEP_ENABLE),
576 &acpi_gbl_FADT.sleep_control);
577 if (ACPI_FAILURE(status)) {
578 return_ACPI_STATUS(status);
579 }
580
581 /* Wait for transition back to Working State */
582
583 do {
584 status = acpi_read(&sleep_status, &acpi_gbl_FADT.sleep_status);
585 if (ACPI_FAILURE(status)) {
586 return_ACPI_STATUS(status);
587 }
588
589 } while (!(((u8)sleep_status) & ACPI_X_WAKE_STATUS));
590
591 return_ACPI_STATUS(AE_OK);
592}
593
594/*******************************************************************************
595 *
596 * FUNCTION: acpi_hw_extended_wake_prep
597 *
598 * PARAMETERS: sleep_state - Which sleep state we just exited
599 *
600 * RETURN: Status
601 *
602 * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
603 * a sleep. Called with interrupts ENABLED.
604 *
605 ******************************************************************************/
606
607acpi_status acpi_hw_extended_wake_prep(u8 sleep_state)
608{
609 acpi_status status;
610 u8 sleep_type_value;
611
612 ACPI_FUNCTION_TRACE(hw_extended_wake_prep);
613
614 status = acpi_get_sleep_type_data(ACPI_STATE_S0,
615 &acpi_gbl_sleep_type_a,
616 &acpi_gbl_sleep_type_b);
617 if (ACPI_SUCCESS(status)) {
618 sleep_type_value =
619 ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
620 ACPI_X_SLEEP_TYPE_MASK);
621
622 (void)acpi_write((sleep_type_value | ACPI_X_SLEEP_ENABLE),
623 &acpi_gbl_FADT.sleep_control);
624 }
625
626 acpi_hw_execute_BFS(sleep_state);
627 return_ACPI_STATUS(AE_OK);
628}
629
630/*******************************************************************************
631 *
632 * FUNCTION: acpi_hw_extended_wake
633 *
634 * PARAMETERS: sleep_state - Which sleep state we just exited
635 *
636 * RETURN: Status
637 *
638 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
639 * Called with interrupts ENABLED.
640 *
641 ******************************************************************************/
642
643acpi_status acpi_hw_extended_wake(u8 sleep_state)
644{
645 ACPI_FUNCTION_TRACE(hw_extended_wake);
646
647 /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
648
649 acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
650
651 /* Execute the wake methods */
652
653 acpi_hw_execute_SST(ACPI_SST_WAKING);
654 acpi_hw_execute_WAK(sleep_state);
655
656 /*
657 * Some BIOS code assumes that WAK_STS will be cleared on resume
658 * and use it to determine whether the system is rebooting or
659 * resuming. Clear WAK_STS for compatibility.
660 */
661 (void)acpi_write(ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
662 acpi_gbl_system_awake_and_running = TRUE;
663
664 acpi_hw_execute_SST(ACPI_SST_WORKING);
665 return_ACPI_STATUS(AE_OK);
666}