1 /****************************************************************************** 2 * 3 * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, Intel Corp. 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 44 #define EXPORT_ACPI_INTERFACES 45 46 #include <acpi/acpi.h> 47 #include "accommon.h" 48 49 #define _COMPONENT ACPI_HARDWARE 50 ACPI_MODULE_NAME("hwxfsleep") 51 52 /* Local prototypes */ 53 #if (!ACPI_REDUCED_HARDWARE) 54 static acpi_status 55 acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs, 56 acpi_physical_address physical_address, 57 acpi_physical_address physical_address64); 58 #endif 59 60 static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id); 61 62 /* 63 * Dispatch table used to efficiently branch to the various sleep 64 * functions. 65 */ 66 #define ACPI_SLEEP_FUNCTION_ID 0 67 #define ACPI_WAKE_PREP_FUNCTION_ID 1 68 #define ACPI_WAKE_FUNCTION_ID 2 69 70 /* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */ 71 72 static struct acpi_sleep_functions acpi_sleep_dispatch[] = { 73 {ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_sleep), 74 acpi_hw_extended_sleep}, 75 {ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake_prep), 76 acpi_hw_extended_wake_prep}, 77 {ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake), acpi_hw_extended_wake} 78 }; 79 80 /* 81 * These functions are removed for the ACPI_REDUCED_HARDWARE case: 82 * acpi_set_firmware_waking_vectors 83 * acpi_set_firmware_waking_vector 84 * acpi_set_firmware_waking_vector64 85 * acpi_enter_sleep_state_s4bios 86 */ 87 88 #if (!ACPI_REDUCED_HARDWARE) 89 /******************************************************************************* 90 * 91 * FUNCTION: acpi_hw_set_firmware_waking_vectors 92 * 93 * PARAMETERS: facs - Pointer to FACS table 94 * physical_address - 32-bit physical address of ACPI real mode 95 * entry point. 96 * physical_address64 - 64-bit physical address of ACPI protected 97 * mode entry point. 98 * 99 * RETURN: Status 100 * 101 * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS 102 * 103 ******************************************************************************/ 104 105 static acpi_status 106 acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs, 107 acpi_physical_address physical_address, 108 acpi_physical_address physical_address64) 109 { 110 ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vectors); 111 112 113 /* 114 * According to the ACPI specification 2.0c and later, the 64-bit 115 * waking vector should be cleared and the 32-bit waking vector should 116 * be used, unless we want the wake-up code to be called by the BIOS in 117 * Protected Mode. Some systems (for example HP dv5-1004nr) are known 118 * to fail to resume if the 64-bit vector is used. 119 */ 120 121 /* Set the 32-bit vector */ 122 123 facs->firmware_waking_vector = (u32)physical_address; 124 125 if (facs->length > 32) { 126 if (facs->version >= 1) { 127 128 /* Set the 64-bit vector */ 129 130 facs->xfirmware_waking_vector = physical_address64; 131 } else { 132 /* Clear the 64-bit vector if it exists */ 133 134 facs->xfirmware_waking_vector = 0; 135 } 136 } 137 138 return_ACPI_STATUS(AE_OK); 139 } 140 141 /******************************************************************************* 142 * 143 * FUNCTION: acpi_set_firmware_waking_vectors 144 * 145 * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode 146 * entry point. 147 * physical_address64 - 64-bit physical address of ACPI protected 148 * mode entry point. 149 * 150 * RETURN: Status 151 * 152 * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS 153 * 154 ******************************************************************************/ 155 156 acpi_status 157 acpi_set_firmware_waking_vectors(acpi_physical_address physical_address, 158 acpi_physical_address physical_address64) 159 { 160 161 ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vectors); 162 163 /* If Hardware Reduced flag is set, there is no FACS */ 164 165 if (acpi_gbl_reduced_hardware) { 166 return_ACPI_STATUS (AE_OK); 167 } 168 169 if (acpi_gbl_facs32) { 170 (void)acpi_hw_set_firmware_waking_vectors(acpi_gbl_facs32, 171 physical_address, 172 physical_address64); 173 } 174 if (acpi_gbl_facs64) { 175 (void)acpi_hw_set_firmware_waking_vectors(acpi_gbl_facs64, 176 physical_address, 177 physical_address64); 178 } 179 180 return_ACPI_STATUS(AE_OK); 181 } 182 183 ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vectors) 184 185 /******************************************************************************* 186 * 187 * FUNCTION: acpi_set_firmware_waking_vector 188 * 189 * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode 190 * entry point. 191 * 192 * RETURN: Status 193 * 194 * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS 195 * 196 ******************************************************************************/ 197 acpi_status acpi_set_firmware_waking_vector(u32 physical_address) 198 { 199 acpi_status status; 200 201 ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); 202 203 status = acpi_set_firmware_waking_vectors((acpi_physical_address) 204 physical_address, 0); 205 206 return_ACPI_STATUS(status); 207 } 208 209 ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) 210 211 #if ACPI_MACHINE_WIDTH == 64 212 /******************************************************************************* 213 * 214 * FUNCTION: acpi_set_firmware_waking_vector64 215 * 216 * PARAMETERS: physical_address - 64-bit physical address of ACPI protected 217 * mode entry point. 218 * 219 * RETURN: Status 220 * 221 * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if 222 * it exists in the table. This function is intended for use with 223 * 64-bit host operating systems. 224 * 225 ******************************************************************************/ 226 acpi_status acpi_set_firmware_waking_vector64(u64 physical_address) 227 { 228 acpi_status status; 229 230 ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64); 231 232 status = acpi_set_firmware_waking_vectors(0, 233 (acpi_physical_address) 234 physical_address); 235 236 return_ACPI_STATUS(status); 237 } 238 239 ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) 240 #endif 241 /******************************************************************************* 242 * 243 * FUNCTION: acpi_enter_sleep_state_s4bios 244 * 245 * PARAMETERS: None 246 * 247 * RETURN: Status 248 * 249 * DESCRIPTION: Perform a S4 bios request. 250 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 251 * 252 ******************************************************************************/ 253 acpi_status acpi_enter_sleep_state_s4bios(void) 254 { 255 u32 in_value; 256 acpi_status status; 257 258 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); 259 260 /* Clear the wake status bit (PM1) */ 261 262 status = 263 acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); 264 if (ACPI_FAILURE(status)) { 265 return_ACPI_STATUS(status); 266 } 267 268 status = acpi_hw_clear_acpi_status(); 269 if (ACPI_FAILURE(status)) { 270 return_ACPI_STATUS(status); 271 } 272 273 /* 274 * 1) Disable/Clear all GPEs 275 * 2) Enable all wakeup GPEs 276 */ 277 status = acpi_hw_disable_all_gpes(); 278 if (ACPI_FAILURE(status)) { 279 return_ACPI_STATUS(status); 280 } 281 acpi_gbl_system_awake_and_running = FALSE; 282 283 status = acpi_hw_enable_all_wakeup_gpes(); 284 if (ACPI_FAILURE(status)) { 285 return_ACPI_STATUS(status); 286 } 287 288 ACPI_FLUSH_CPU_CACHE(); 289 290 status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, 291 (u32)acpi_gbl_FADT.s4_bios_request, 8); 292 293 do { 294 acpi_os_stall(ACPI_USEC_PER_MSEC); 295 status = 296 acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); 297 if (ACPI_FAILURE(status)) { 298 return_ACPI_STATUS(status); 299 } 300 } while (!in_value); 301 302 return_ACPI_STATUS(AE_OK); 303 } 304 305 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) 306 #endif /* !ACPI_REDUCED_HARDWARE */ 307 /******************************************************************************* 308 * 309 * FUNCTION: acpi_hw_sleep_dispatch 310 * 311 * PARAMETERS: sleep_state - Which sleep state to enter/exit 312 * function_id - Sleep, wake_prep, or Wake 313 * 314 * RETURN: Status from the invoked sleep handling function. 315 * 316 * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling 317 * function. 318 * 319 ******************************************************************************/ 320 static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id) 321 { 322 acpi_status status; 323 struct acpi_sleep_functions *sleep_functions = 324 &acpi_sleep_dispatch[function_id]; 325 326 #if (!ACPI_REDUCED_HARDWARE) 327 /* 328 * If the Hardware Reduced flag is set (from the FADT), we must 329 * use the extended sleep registers (FADT). Note: As per the ACPI 330 * specification, these extended registers are to be used for HW-reduced 331 * platforms only. They are not general-purpose replacements for the 332 * legacy PM register sleep support. 333 */ 334 if (acpi_gbl_reduced_hardware) { 335 status = sleep_functions->extended_function(sleep_state); 336 } else { 337 /* Legacy sleep */ 338 339 status = sleep_functions->legacy_function(sleep_state); 340 } 341 342 return (status); 343 344 #else 345 /* 346 * For the case where reduced-hardware-only code is being generated, 347 * we know that only the extended sleep registers are available 348 */ 349 status = sleep_functions->extended_function(sleep_state); 350 return (status); 351 352 #endif /* !ACPI_REDUCED_HARDWARE */ 353 } 354 355 /******************************************************************************* 356 * 357 * FUNCTION: acpi_enter_sleep_state_prep 358 * 359 * PARAMETERS: sleep_state - Which sleep state to enter 360 * 361 * RETURN: Status 362 * 363 * DESCRIPTION: Prepare to enter a system sleep state. 364 * This function must execute with interrupts enabled. 365 * We break sleeping into 2 stages so that OSPM can handle 366 * various OS-specific tasks between the two steps. 367 * 368 ******************************************************************************/ 369 370 acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) 371 { 372 acpi_status status; 373 struct acpi_object_list arg_list; 374 union acpi_object arg; 375 u32 sst_value; 376 377 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); 378 379 status = acpi_get_sleep_type_data(sleep_state, 380 &acpi_gbl_sleep_type_a, 381 &acpi_gbl_sleep_type_b); 382 if (ACPI_FAILURE(status)) { 383 return_ACPI_STATUS(status); 384 } 385 386 /* Execute the _PTS method (Prepare To Sleep) */ 387 388 arg_list.count = 1; 389 arg_list.pointer = &arg; 390 arg.type = ACPI_TYPE_INTEGER; 391 arg.integer.value = sleep_state; 392 393 status = 394 acpi_evaluate_object(NULL, METHOD_PATHNAME__PTS, &arg_list, NULL); 395 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 396 return_ACPI_STATUS(status); 397 } 398 399 /* Setup the argument to the _SST method (System STatus) */ 400 401 switch (sleep_state) { 402 case ACPI_STATE_S0: 403 404 sst_value = ACPI_SST_WORKING; 405 break; 406 407 case ACPI_STATE_S1: 408 case ACPI_STATE_S2: 409 case ACPI_STATE_S3: 410 411 sst_value = ACPI_SST_SLEEPING; 412 break; 413 414 case ACPI_STATE_S4: 415 416 sst_value = ACPI_SST_SLEEP_CONTEXT; 417 break; 418 419 default: 420 421 sst_value = ACPI_SST_INDICATOR_OFF; /* Default is off */ 422 break; 423 } 424 425 /* 426 * Set the system indicators to show the desired sleep state. 427 * _SST is an optional method (return no error if not found) 428 */ 429 acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, sst_value); 430 return_ACPI_STATUS(AE_OK); 431 } 432 433 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) 434 435 /******************************************************************************* 436 * 437 * FUNCTION: acpi_enter_sleep_state 438 * 439 * PARAMETERS: sleep_state - Which sleep state to enter 440 * 441 * RETURN: Status 442 * 443 * DESCRIPTION: Enter a system sleep state 444 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 445 * 446 ******************************************************************************/ 447 acpi_status acpi_enter_sleep_state(u8 sleep_state) 448 { 449 acpi_status status; 450 451 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); 452 453 if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || 454 (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { 455 ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X", 456 acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); 457 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 458 } 459 460 status = acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID); 461 return_ACPI_STATUS(status); 462 } 463 464 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) 465 466 /******************************************************************************* 467 * 468 * FUNCTION: acpi_leave_sleep_state_prep 469 * 470 * PARAMETERS: sleep_state - Which sleep state we are exiting 471 * 472 * RETURN: Status 473 * 474 * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a 475 * sleep. Called with interrupts DISABLED. 476 * We break wake/resume into 2 stages so that OSPM can handle 477 * various OS-specific tasks between the two steps. 478 * 479 ******************************************************************************/ 480 acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) 481 { 482 acpi_status status; 483 484 ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); 485 486 status = 487 acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID); 488 return_ACPI_STATUS(status); 489 } 490 491 ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state_prep) 492 493 /******************************************************************************* 494 * 495 * FUNCTION: acpi_leave_sleep_state 496 * 497 * PARAMETERS: sleep_state - Which sleep state we are exiting 498 * 499 * RETURN: Status 500 * 501 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep 502 * Called with interrupts ENABLED. 503 * 504 ******************************************************************************/ 505 acpi_status acpi_leave_sleep_state(u8 sleep_state) 506 { 507 acpi_status status; 508 509 ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); 510 511 status = acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_FUNCTION_ID); 512 return_ACPI_STATUS(status); 513 } 514 515 ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) 516