1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces
6 * Copyright (C) 2000 - 2020, Intel Corp.
8 *****************************************************************************/
10 #define EXPORT_ACPI_INTERFACES
12 #include <acpi/acpi.h>
15 #define _COMPONENT ACPI_HARDWARE
16 ACPI_MODULE_NAME("hwxfsleep")
18 /* Local prototypes */
19 #if (!ACPI_REDUCED_HARDWARE)
21 acpi_hw_set_firmware_waking_vector(struct acpi_table_facs
*facs
,
22 acpi_physical_address physical_address
,
23 acpi_physical_address physical_address64
);
27 * These functions are removed for the ACPI_REDUCED_HARDWARE case:
28 * acpi_set_firmware_waking_vector
29 * acpi_enter_sleep_state_s4bios
32 #if (!ACPI_REDUCED_HARDWARE)
33 /*******************************************************************************
35 * FUNCTION: acpi_hw_set_firmware_waking_vector
37 * PARAMETERS: facs - Pointer to FACS table
38 * physical_address - 32-bit physical address of ACPI real mode
40 * physical_address64 - 64-bit physical address of ACPI protected
45 * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS
47 ******************************************************************************/
50 acpi_hw_set_firmware_waking_vector(struct acpi_table_facs
*facs
,
51 acpi_physical_address physical_address
,
52 acpi_physical_address physical_address64
)
54 ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vector
);
58 * According to the ACPI specification 2.0c and later, the 64-bit
59 * waking vector should be cleared and the 32-bit waking vector should
60 * be used, unless we want the wake-up code to be called by the BIOS in
61 * Protected Mode. Some systems (for example HP dv5-1004nr) are known
62 * to fail to resume if the 64-bit vector is used.
65 /* Set the 32-bit vector */
67 facs
->firmware_waking_vector
= (u32
)physical_address
;
69 if (facs
->length
> 32) {
70 if (facs
->version
>= 1) {
72 /* Set the 64-bit vector */
74 facs
->xfirmware_waking_vector
= physical_address64
;
76 /* Clear the 64-bit vector if it exists */
78 facs
->xfirmware_waking_vector
= 0;
82 return_ACPI_STATUS(AE_OK
);
85 /*******************************************************************************
87 * FUNCTION: acpi_set_firmware_waking_vector
89 * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode
91 * physical_address64 - 64-bit physical address of ACPI protected
96 * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS
98 ******************************************************************************/
101 acpi_set_firmware_waking_vector(acpi_physical_address physical_address
,
102 acpi_physical_address physical_address64
)
105 ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector
);
108 (void)acpi_hw_set_firmware_waking_vector(acpi_gbl_FACS
,
113 return_ACPI_STATUS(AE_OK
);
116 ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector
)
118 /*******************************************************************************
120 * FUNCTION: acpi_enter_sleep_state_s4bios
126 * DESCRIPTION: Perform a S4 bios request.
127 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
129 ******************************************************************************/
130 acpi_status
acpi_enter_sleep_state_s4bios(void)
135 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios
);
137 /* Clear the wake status bit (PM1) */
140 acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS
, ACPI_CLEAR_STATUS
);
141 if (ACPI_FAILURE(status
)) {
142 return_ACPI_STATUS(status
);
145 status
= acpi_hw_clear_acpi_status();
146 if (ACPI_FAILURE(status
)) {
147 return_ACPI_STATUS(status
);
151 * 1) Disable all GPEs
152 * 2) Enable all wakeup GPEs
154 status
= acpi_hw_disable_all_gpes();
155 if (ACPI_FAILURE(status
)) {
156 return_ACPI_STATUS(status
);
158 acpi_gbl_system_awake_and_running
= FALSE
;
160 status
= acpi_hw_enable_all_wakeup_gpes();
161 if (ACPI_FAILURE(status
)) {
162 return_ACPI_STATUS(status
);
165 ACPI_FLUSH_CPU_CACHE();
167 status
= acpi_hw_write_port(acpi_gbl_FADT
.smi_command
,
168 (u32
)acpi_gbl_FADT
.s4_bios_request
, 8);
169 if (ACPI_FAILURE(status
)) {
170 return_ACPI_STATUS(status
);
174 acpi_os_stall(ACPI_USEC_PER_MSEC
);
176 acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS
, &in_value
);
177 if (ACPI_FAILURE(status
)) {
178 return_ACPI_STATUS(status
);
183 return_ACPI_STATUS(AE_OK
);
186 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios
)
187 #endif /* !ACPI_REDUCED_HARDWARE */
189 /*******************************************************************************
191 * FUNCTION: acpi_enter_sleep_state_prep
193 * PARAMETERS: sleep_state - Which sleep state to enter
197 * DESCRIPTION: Prepare to enter a system sleep state.
198 * This function must execute with interrupts enabled.
199 * We break sleeping into 2 stages so that OSPM can handle
200 * various OS-specific tasks between the two steps.
202 ******************************************************************************/
204 acpi_status
acpi_enter_sleep_state_prep(u8 sleep_state
)
207 struct acpi_object_list arg_list
;
208 union acpi_object arg
;
211 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep
);
213 status
= acpi_get_sleep_type_data(sleep_state
,
214 &acpi_gbl_sleep_type_a
,
215 &acpi_gbl_sleep_type_b
);
216 if (ACPI_FAILURE(status
)) {
217 return_ACPI_STATUS(status
);
220 /* Execute the _PTS method (Prepare To Sleep) */
223 arg_list
.pointer
= &arg
;
224 arg
.type
= ACPI_TYPE_INTEGER
;
225 arg
.integer
.value
= sleep_state
;
228 acpi_evaluate_object(NULL
, METHOD_PATHNAME__PTS
, &arg_list
, NULL
);
229 if (ACPI_FAILURE(status
) && status
!= AE_NOT_FOUND
) {
230 return_ACPI_STATUS(status
);
233 /* Setup the argument to the _SST method (System STatus) */
235 switch (sleep_state
) {
238 sst_value
= ACPI_SST_WORKING
;
245 sst_value
= ACPI_SST_SLEEPING
;
250 sst_value
= ACPI_SST_SLEEP_CONTEXT
;
255 sst_value
= ACPI_SST_INDICATOR_OFF
; /* Default is off */
260 * Set the system indicators to show the desired sleep state.
261 * _SST is an optional method (return no error if not found)
263 acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST
, sst_value
);
264 return_ACPI_STATUS(AE_OK
);
267 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep
)
269 /*******************************************************************************
271 * FUNCTION: acpi_enter_sleep_state
273 * PARAMETERS: sleep_state - Which sleep state to enter
277 * DESCRIPTION: Enter a system sleep state
278 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
280 ******************************************************************************/
281 acpi_status
acpi_enter_sleep_state(u8 sleep_state
)
285 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state
);
287 if ((acpi_gbl_sleep_type_a
> ACPI_SLEEP_TYPE_MAX
) ||
288 (acpi_gbl_sleep_type_b
> ACPI_SLEEP_TYPE_MAX
)) {
289 ACPI_ERROR((AE_INFO
, "Sleep values out of range: A=0x%X B=0x%X",
290 acpi_gbl_sleep_type_a
, acpi_gbl_sleep_type_b
));
291 return_ACPI_STATUS(AE_AML_OPERAND_VALUE
);
294 #if !ACPI_REDUCED_HARDWARE
295 if (!acpi_gbl_reduced_hardware
)
296 status
= acpi_hw_legacy_sleep(sleep_state
);
299 status
= acpi_hw_extended_sleep(sleep_state
);
300 return_ACPI_STATUS(status
);
303 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state
)
305 /*******************************************************************************
307 * FUNCTION: acpi_leave_sleep_state_prep
309 * PARAMETERS: sleep_state - Which sleep state we are exiting
313 * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
314 * sleep. Called with interrupts DISABLED.
315 * We break wake/resume into 2 stages so that OSPM can handle
316 * various OS-specific tasks between the two steps.
318 ******************************************************************************/
319 acpi_status
acpi_leave_sleep_state_prep(u8 sleep_state
)
323 ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep
);
325 #if !ACPI_REDUCED_HARDWARE
326 if (!acpi_gbl_reduced_hardware
)
327 status
= acpi_hw_legacy_wake_prep(sleep_state
);
330 status
= acpi_hw_extended_wake_prep(sleep_state
);
331 return_ACPI_STATUS(status
);
334 ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state_prep
)
336 /*******************************************************************************
338 * FUNCTION: acpi_leave_sleep_state
340 * PARAMETERS: sleep_state - Which sleep state we are exiting
344 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
345 * Called with interrupts ENABLED.
347 ******************************************************************************/
348 acpi_status
acpi_leave_sleep_state(u8 sleep_state
)
352 ACPI_FUNCTION_TRACE(acpi_leave_sleep_state
);
354 #if !ACPI_REDUCED_HARDWARE
355 if (!acpi_gbl_reduced_hardware
)
356 status
= acpi_hw_legacy_wake(sleep_state
);
359 status
= acpi_hw_extended_wake(sleep_state
);
360 return_ACPI_STATUS(status
);
363 ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state
)