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