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