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