Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 : : /****************************************************************************** 3 : : * 4 : : * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces 5 : : * 6 : : * Copyright (C) 2000 - 2020, Intel Corp. 7 : : * 8 : : *****************************************************************************/ 9 : : 10 : : #define EXPORT_ACPI_INTERFACES 11 : : 12 : : #include <acpi/acpi.h> 13 : : #include "accommon.h" 14 : : 15 : : #define _COMPONENT ACPI_HARDWARE 16 : : ACPI_MODULE_NAME("hwxfsleep") 17 : : 18 : : /* Local prototypes */ 19 : : #if (!ACPI_REDUCED_HARDWARE) 20 : : static acpi_status 21 : : acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs, 22 : : acpi_physical_address physical_address, 23 : : acpi_physical_address physical_address64); 24 : : #endif 25 : : 26 : : /* 27 : : * These functions are removed for the ACPI_REDUCED_HARDWARE case: 28 : : * acpi_set_firmware_waking_vector 29 : : * acpi_enter_sleep_state_s4bios 30 : : */ 31 : : 32 : : #if (!ACPI_REDUCED_HARDWARE) 33 : : /******************************************************************************* 34 : : * 35 : : * FUNCTION: acpi_hw_set_firmware_waking_vector 36 : : * 37 : : * PARAMETERS: facs - Pointer to FACS table 38 : : * physical_address - 32-bit physical address of ACPI real mode 39 : : * entry point 40 : : * physical_address64 - 64-bit physical address of ACPI protected 41 : : * mode entry point 42 : : * 43 : : * RETURN: Status 44 : : * 45 : : * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS 46 : : * 47 : : ******************************************************************************/ 48 : : 49 : : static acpi_status 50 : 0 : acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs, 51 : : acpi_physical_address physical_address, 52 : : acpi_physical_address physical_address64) 53 : : { 54 : 0 : ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vector); 55 : : 56 : : 57 : : /* 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. 63 : : */ 64 : : 65 : : /* Set the 32-bit vector */ 66 : : 67 : 0 : facs->firmware_waking_vector = (u32)physical_address; 68 : : 69 [ # # ]: 0 : if (facs->length > 32) { 70 [ # # ]: 0 : if (facs->version >= 1) { 71 : : 72 : : /* Set the 64-bit vector */ 73 : : 74 : 0 : facs->xfirmware_waking_vector = physical_address64; 75 : : } else { 76 : : /* Clear the 64-bit vector if it exists */ 77 : : 78 : 0 : facs->xfirmware_waking_vector = 0; 79 : : } 80 : : } 81 : : 82 : 0 : return_ACPI_STATUS(AE_OK); 83 : : } 84 : : 85 : : /******************************************************************************* 86 : : * 87 : : * FUNCTION: acpi_set_firmware_waking_vector 88 : : * 89 : : * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode 90 : : * entry point 91 : : * physical_address64 - 64-bit physical address of ACPI protected 92 : : * mode entry point 93 : : * 94 : : * RETURN: Status 95 : : * 96 : : * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS 97 : : * 98 : : ******************************************************************************/ 99 : : 100 : : acpi_status 101 : 0 : acpi_set_firmware_waking_vector(acpi_physical_address physical_address, 102 : : acpi_physical_address physical_address64) 103 : : { 104 : : 105 : 0 : ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); 106 : : 107 [ # # ]: 0 : if (acpi_gbl_FACS) { 108 : 0 : (void)acpi_hw_set_firmware_waking_vector(acpi_gbl_FACS, 109 : : physical_address, 110 : : physical_address64); 111 : : } 112 : : 113 : 0 : return_ACPI_STATUS(AE_OK); 114 : : } 115 : : 116 : : ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) 117 : : 118 : : /******************************************************************************* 119 : : * 120 : : * FUNCTION: acpi_enter_sleep_state_s4bios 121 : : * 122 : : * PARAMETERS: None 123 : : * 124 : : * RETURN: Status 125 : : * 126 : : * DESCRIPTION: Perform a S4 bios request. 127 : : * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 128 : : * 129 : : ******************************************************************************/ 130 : 0 : acpi_status acpi_enter_sleep_state_s4bios(void) 131 : : { 132 : 0 : u32 in_value; 133 : 0 : acpi_status status; 134 : : 135 : 0 : ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); 136 : : 137 : : /* Clear the wake status bit (PM1) */ 138 : : 139 : 0 : status = 140 : 0 : acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); 141 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 142 : : return_ACPI_STATUS(status); 143 : : } 144 : : 145 : 0 : status = acpi_hw_clear_acpi_status(); 146 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 147 : : return_ACPI_STATUS(status); 148 : : } 149 : : 150 : : /* 151 : : * 1) Disable all GPEs 152 : : * 2) Enable all wakeup GPEs 153 : : */ 154 : 0 : status = acpi_hw_disable_all_gpes(); 155 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 156 : : return_ACPI_STATUS(status); 157 : : } 158 : 0 : acpi_gbl_system_awake_and_running = FALSE; 159 : : 160 : 0 : status = acpi_hw_enable_all_wakeup_gpes(); 161 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 162 : : return_ACPI_STATUS(status); 163 : : } 164 : : 165 : 0 : ACPI_FLUSH_CPU_CACHE(); 166 : : 167 : 0 : status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, 168 : 0 : (u32)acpi_gbl_FADT.s4_bios_request, 8); 169 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 170 : : return_ACPI_STATUS(status); 171 : : } 172 : : 173 : 0 : do { 174 : 0 : acpi_os_stall(ACPI_USEC_PER_MSEC); 175 : 0 : status = 176 : 0 : acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); 177 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 178 : 0 : return_ACPI_STATUS(status); 179 : : } 180 : : 181 [ # # ]: 0 : } while (!in_value); 182 : : 183 : : return_ACPI_STATUS(AE_OK); 184 : : } 185 : : 186 : : ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) 187 : : #endif /* !ACPI_REDUCED_HARDWARE */ 188 : : 189 : : /******************************************************************************* 190 : : * 191 : : * FUNCTION: acpi_enter_sleep_state_prep 192 : : * 193 : : * PARAMETERS: sleep_state - Which sleep state to enter 194 : : * 195 : : * RETURN: Status 196 : : * 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. 201 : : * 202 : : ******************************************************************************/ 203 : : 204 : 0 : acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) 205 : : { 206 : 0 : acpi_status status; 207 : 0 : struct acpi_object_list arg_list; 208 : 0 : union acpi_object arg; 209 : 0 : u32 sst_value; 210 : : 211 : 0 : ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); 212 : : 213 : 0 : status = acpi_get_sleep_type_data(sleep_state, 214 : : &acpi_gbl_sleep_type_a, 215 : : &acpi_gbl_sleep_type_b); 216 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 217 : : return_ACPI_STATUS(status); 218 : : } 219 : : 220 : : /* Execute the _PTS method (Prepare To Sleep) */ 221 : : 222 : 0 : arg_list.count = 1; 223 : 0 : arg_list.pointer = &arg; 224 : 0 : arg.type = ACPI_TYPE_INTEGER; 225 : 0 : arg.integer.value = sleep_state; 226 : : 227 : 0 : status = 228 : 0 : acpi_evaluate_object(NULL, METHOD_PATHNAME__PTS, &arg_list, NULL); 229 [ # # ]: 0 : if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 230 : : return_ACPI_STATUS(status); 231 : : } 232 : : 233 : : /* Setup the argument to the _SST method (System STatus) */ 234 : : 235 [ # # ]: 0 : switch (sleep_state) { 236 : : case ACPI_STATE_S0: 237 : : 238 : : sst_value = ACPI_SST_WORKING; 239 : : break; 240 : : 241 : : case ACPI_STATE_S1: 242 : : case ACPI_STATE_S2: 243 : : case ACPI_STATE_S3: 244 : : 245 : : sst_value = ACPI_SST_SLEEPING; 246 : : break; 247 : : 248 : : case ACPI_STATE_S4: 249 : : 250 : : sst_value = ACPI_SST_SLEEP_CONTEXT; 251 : : break; 252 : : 253 : : default: 254 : : 255 : : sst_value = ACPI_SST_INDICATOR_OFF; /* Default is off */ 256 : : break; 257 : : } 258 : : 259 : : /* 260 : : * Set the system indicators to show the desired sleep state. 261 : : * _SST is an optional method (return no error if not found) 262 : : */ 263 : 0 : acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, sst_value); 264 : 0 : return_ACPI_STATUS(AE_OK); 265 : : } 266 : : 267 : : ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) 268 : : 269 : : /******************************************************************************* 270 : : * 271 : : * FUNCTION: acpi_enter_sleep_state 272 : : * 273 : : * PARAMETERS: sleep_state - Which sleep state to enter 274 : : * 275 : : * RETURN: Status 276 : : * 277 : : * DESCRIPTION: Enter a system sleep state 278 : : * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 279 : : * 280 : : ******************************************************************************/ 281 : 0 : acpi_status acpi_enter_sleep_state(u8 sleep_state) 282 : : { 283 : 0 : acpi_status status; 284 : : 285 : 0 : ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); 286 : : 287 [ # # ]: 0 : if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || 288 [ # # ]: 0 : (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { 289 : 0 : 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 : 0 : return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 292 : : } 293 : : 294 : : #if !ACPI_REDUCED_HARDWARE 295 [ # # ]: 0 : if (!acpi_gbl_reduced_hardware) 296 : 0 : status = acpi_hw_legacy_sleep(sleep_state); 297 : : else 298 : : #endif 299 : 0 : status = acpi_hw_extended_sleep(sleep_state); 300 : : return_ACPI_STATUS(status); 301 : : } 302 : : 303 : : ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) 304 : : 305 : : /******************************************************************************* 306 : : * 307 : : * FUNCTION: acpi_leave_sleep_state_prep 308 : : * 309 : : * PARAMETERS: sleep_state - Which sleep state we are exiting 310 : : * 311 : : * RETURN: Status 312 : : * 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. 317 : : * 318 : : ******************************************************************************/ 319 : 0 : acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) 320 : : { 321 : 0 : acpi_status status; 322 : : 323 : 0 : ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); 324 : : 325 : : #if !ACPI_REDUCED_HARDWARE 326 [ # # ]: 0 : if (!acpi_gbl_reduced_hardware) 327 : 0 : status = acpi_hw_legacy_wake_prep(sleep_state); 328 : : else 329 : : #endif 330 : 0 : status = acpi_hw_extended_wake_prep(sleep_state); 331 : 0 : return_ACPI_STATUS(status); 332 : : } 333 : : 334 : : ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state_prep) 335 : : 336 : : /******************************************************************************* 337 : : * 338 : : * FUNCTION: acpi_leave_sleep_state 339 : : * 340 : : * PARAMETERS: sleep_state - Which sleep state we are exiting 341 : : * 342 : : * RETURN: Status 343 : : * 344 : : * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep 345 : : * Called with interrupts ENABLED. 346 : : * 347 : : ******************************************************************************/ 348 : 0 : acpi_status acpi_leave_sleep_state(u8 sleep_state) 349 : : { 350 : 0 : acpi_status status; 351 : : 352 : 0 : ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); 353 : : 354 : : #if !ACPI_REDUCED_HARDWARE 355 [ # # ]: 0 : if (!acpi_gbl_reduced_hardware) 356 : 0 : status = acpi_hw_legacy_wake(sleep_state); 357 : : else 358 : : #endif 359 : 0 : status = acpi_hw_extended_wake(sleep_state); 360 : 0 : return_ACPI_STATUS(status); 361 : : } 362 : : 363 : : ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)