1228753Smm/****************************************************************************** 2228753Smm * 3228753Smm * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces 4228753Smm * 5228753Smm *****************************************************************************/ 6228753Smm 7228753Smm/* 8228753Smm * Copyright (C) 2000 - 2016, Intel Corp. 9228753Smm * All rights reserved. 10228753Smm * 11228753Smm * Redistribution and use in source and binary forms, with or without 12228753Smm * modification, are permitted provided that the following conditions 13228753Smm * are met: 14228753Smm * 1. Redistributions of source code must retain the above copyright 15228753Smm * notice, this list of conditions, and the following disclaimer, 16228753Smm * without modification. 17228753Smm * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18228753Smm * substantially similar to the "NO WARRANTY" disclaimer below 19228753Smm * ("Disclaimer") and any redistribution must be conditioned upon 20228753Smm * including a substantially similar Disclaimer requirement for further 21228753Smm * binary redistribution. 22228753Smm * 3. Neither the names of the above-listed copyright holders nor the names 23228753Smm * of any contributors may be used to endorse or promote products derived 24228753Smm * from this software without specific prior written permission. 25228763Smm * 26228753Smm * Alternatively, this software may be distributed under the terms of the 27238856Smm * GNU General Public License ("GPL") version 2 as published by the Free 28238856Smm * Software Foundation. 29228753Smm * 30228753Smm * NO WARRANTY 31228753Smm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32228753Smm * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33228753Smm * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34228753Smm * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35228753Smm * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36228753Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37228753Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38228753Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39228753Smm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40228753Smm * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41228753Smm * POSSIBILITY OF SUCH DAMAGES. 42228753Smm */ 43228753Smm 44232153Smm#define EXPORT_ACPI_INTERFACES 45228753Smm 46228753Smm#include <contrib/dev/acpica/include/acpi.h> 47232153Smm#include <contrib/dev/acpica/include/accommon.h> 48228753Smm 49228753Smm#define _COMPONENT ACPI_HARDWARE 50228753Smm ACPI_MODULE_NAME ("hwxfsleep") 51228753Smm 52232153Smm/* Local prototypes */ 53228753Smm 54228753Smm#if (!ACPI_REDUCED_HARDWARE) 55228753Smmstatic ACPI_STATUS 56228753SmmAcpiHwSetFirmwareWakingVector ( 57228753Smm ACPI_TABLE_FACS *Facs, 58228753Smm ACPI_PHYSICAL_ADDRESS PhysicalAddress, 59228753Smm ACPI_PHYSICAL_ADDRESS PhysicalAddress64); 60228753Smm#endif 61228753Smm 62228753Smmstatic ACPI_STATUS 63228753SmmAcpiHwSleepDispatch ( 64228753Smm UINT8 SleepState, 65228753Smm UINT32 FunctionId); 66228753Smm 67228753Smm/* 68228753Smm * Dispatch table used to efficiently branch to the various sleep 69228753Smm * functions. 70228753Smm */ 71228753Smm#define ACPI_SLEEP_FUNCTION_ID 0 72228753Smm#define ACPI_WAKE_PREP_FUNCTION_ID 1 73228753Smm#define ACPI_WAKE_FUNCTION_ID 2 74228753Smm 75228753Smm/* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */ 76228753Smm 77228753Smmstatic ACPI_SLEEP_FUNCTIONS AcpiSleepDispatch[] = 78228753Smm{ 79228753Smm {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacySleep), AcpiHwExtendedSleep}, 80228753Smm {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWakePrep), AcpiHwExtendedWakePrep}, 81228753Smm {ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWake), AcpiHwExtendedWake} 82228753Smm}; 83228753Smm 84228753Smm 85228753Smm/* 86228753Smm * These functions are removed for the ACPI_REDUCED_HARDWARE case: 87228753Smm * AcpiSetFirmwareWakingVector 88228753Smm * AcpiEnterSleepStateS4bios 89228753Smm */ 90228753Smm 91228753Smm#if (!ACPI_REDUCED_HARDWARE) 92228753Smm/******************************************************************************* 93228753Smm * 94228753Smm * FUNCTION: AcpiHwSetFirmwareWakingVector 95228753Smm * 96228753Smm * PARAMETERS: Facs - Pointer to FACS table 97228753Smm * PhysicalAddress - 32-bit physical address of ACPI real mode 98228753Smm * entry point 99228753Smm * PhysicalAddress64 - 64-bit physical address of ACPI protected 100228753Smm * mode entry point 101228753Smm * 102228753Smm * RETURN: Status 103228753Smm * 104228753Smm * DESCRIPTION: Sets the FirmwareWakingVector fields of the FACS 105228753Smm * 106228753Smm ******************************************************************************/ 107228753Smm 108228753Smmstatic ACPI_STATUS 109228753SmmAcpiHwSetFirmwareWakingVector ( 110228753Smm ACPI_TABLE_FACS *Facs, 111228753Smm ACPI_PHYSICAL_ADDRESS PhysicalAddress, 112228753Smm ACPI_PHYSICAL_ADDRESS PhysicalAddress64) 113228753Smm{ 114228753Smm ACPI_FUNCTION_TRACE (AcpiHwSetFirmwareWakingVector); 115228753Smm 116228753Smm 117228753Smm /* 118228753Smm * According to the ACPI specification 2.0c and later, the 64-bit 119228753Smm * waking vector should be cleared and the 32-bit waking vector should 120228753Smm * be used, unless we want the wake-up code to be called by the BIOS in 121228753Smm * Protected Mode. Some systems (for example HP dv5-1004nr) are known 122228753Smm * to fail to resume if the 64-bit vector is used. 123228753Smm */ 124228753Smm 125228753Smm /* Set the 32-bit vector */ 126228753Smm 127228753Smm Facs->FirmwareWakingVector = (UINT32) PhysicalAddress; 128228753Smm 129228753Smm if (Facs->Length > 32) 130228753Smm { 131228753Smm if (Facs->Version >= 1) 132228753Smm { 133228753Smm /* Set the 64-bit vector */ 134228753Smm 135228753Smm Facs->XFirmwareWakingVector = PhysicalAddress64; 136228753Smm } 137228753Smm else 138228753Smm { 139228753Smm /* Clear the 64-bit vector if it exists */ 140228753Smm 141228753Smm Facs->XFirmwareWakingVector = 0; 142228753Smm } 143228753Smm } 144228753Smm 145228753Smm return_ACPI_STATUS (AE_OK); 146228753Smm} 147228753Smm 148228753Smm 149228753Smm/******************************************************************************* 150228753Smm * 151228753Smm * FUNCTION: AcpiSetFirmwareWakingVector 152228753Smm * 153228753Smm * PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode 154228753Smm * entry point 155228753Smm * PhysicalAddress64 - 64-bit physical address of ACPI protected 156228753Smm * mode entry point 157228753Smm * 158228753Smm * RETURN: Status 159228753Smm * 160228753Smm * DESCRIPTION: Sets the FirmwareWakingVector fields of the FACS 161228753Smm * 162228753Smm ******************************************************************************/ 163228753Smm 164228753SmmACPI_STATUS 165228753SmmAcpiSetFirmwareWakingVector ( 166228753Smm ACPI_PHYSICAL_ADDRESS PhysicalAddress, 167228753Smm ACPI_PHYSICAL_ADDRESS PhysicalAddress64) 168228753Smm{ 169228753Smm 170228753Smm ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector); 171228753Smm 172228753Smm if (AcpiGbl_FACS) 173228753Smm { 174228753Smm (void) AcpiHwSetFirmwareWakingVector (AcpiGbl_FACS, 175228753Smm PhysicalAddress, PhysicalAddress64); 176228753Smm } 177228753Smm 178228753Smm return_ACPI_STATUS (AE_OK); 179228753Smm} 180228753Smm 181228753SmmACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector) 182228753Smm 183228753Smm 184228753Smm/******************************************************************************* 185228753Smm * 186228753Smm * FUNCTION: AcpiEnterSleepStateS4bios 187228753Smm * 188228753Smm * PARAMETERS: None 189228753Smm * 190228753Smm * RETURN: Status 191228753Smm * 192228753Smm * DESCRIPTION: Perform a S4 bios request. 193228753Smm * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 194228753Smm * 195228753Smm ******************************************************************************/ 196228753Smm 197228753SmmACPI_STATUS 198228753SmmAcpiEnterSleepStateS4bios ( 199228753Smm void) 200228753Smm{ 201228753Smm UINT32 InValue; 202228753Smm ACPI_STATUS Status; 203228753Smm 204228753Smm 205228753Smm ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios); 206228753Smm 207228753Smm 208228753Smm /* Clear the wake status bit (PM1) */ 209228753Smm 210228753Smm Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); 211228753Smm if (ACPI_FAILURE (Status)) 212228753Smm { 213228753Smm return_ACPI_STATUS (Status); 214228753Smm } 215228753Smm 216228753Smm Status = AcpiHwClearAcpiStatus (); 217228753Smm if (ACPI_FAILURE (Status)) 218228753Smm { 219228753Smm return_ACPI_STATUS (Status); 220228753Smm } 221228753Smm 222228753Smm /* 223228753Smm * 1) Disable/Clear all GPEs 224228753Smm * 2) Enable all wakeup GPEs 225228753Smm */ 226228753Smm Status = AcpiHwDisableAllGpes (); 227228753Smm if (ACPI_FAILURE (Status)) 228228753Smm { 229228753Smm return_ACPI_STATUS (Status); 230228753Smm } 231228753Smm AcpiGbl_SystemAwakeAndRunning = FALSE; 232228753Smm 233228753Smm Status = AcpiHwEnableAllWakeupGpes (); 234228753Smm if (ACPI_FAILURE (Status)) 235228753Smm { 236228753Smm return_ACPI_STATUS (Status); 237228753Smm } 238228753Smm 239228753Smm ACPI_FLUSH_CPU_CACHE (); 240228753Smm 241228753Smm Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, 242228753Smm (UINT32) AcpiGbl_FADT.S4BiosRequest, 8); 243228753Smm 244228753Smm do { 245228753Smm AcpiOsStall (ACPI_USEC_PER_MSEC); 246228753Smm Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue); 247228753Smm if (ACPI_FAILURE (Status)) 248228753Smm { 249228753Smm return_ACPI_STATUS (Status); 250228753Smm } 251228753Smm 252228753Smm } while (!InValue); 253228753Smm 254228753Smm return_ACPI_STATUS (AE_OK); 255228753Smm} 256228753Smm 257228753SmmACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios) 258228753Smm 259228753Smm#endif /* !ACPI_REDUCED_HARDWARE */ 260228753Smm 261228753Smm 262228753Smm/******************************************************************************* 263228753Smm * 264228753Smm * FUNCTION: AcpiHwSleepDispatch 265228753Smm * 266228753Smm * PARAMETERS: SleepState - Which sleep state to enter/exit 267228753Smm * FunctionId - Sleep, WakePrep, or Wake 268228753Smm * 269228753Smm * RETURN: Status from the invoked sleep handling function. 270228753Smm * 271228753Smm * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling 272228753Smm * function. 273228753Smm * 274228753Smm ******************************************************************************/ 275228753Smm 276228753Smmstatic ACPI_STATUS 277228753SmmAcpiHwSleepDispatch ( 278228753Smm UINT8 SleepState, 279228753Smm UINT32 FunctionId) 280228753Smm{ 281228753Smm ACPI_STATUS Status; 282228753Smm ACPI_SLEEP_FUNCTIONS *SleepFunctions = &AcpiSleepDispatch[FunctionId]; 283228753Smm 284228753Smm 285228753Smm#if (!ACPI_REDUCED_HARDWARE) 286228753Smm /* 287228753Smm * If the Hardware Reduced flag is set (from the FADT), we must 288228753Smm * use the extended sleep registers (FADT). Note: As per the ACPI 289228753Smm * specification, these extended registers are to be used for HW-reduced 290228753Smm * platforms only. They are not general-purpose replacements for the 291228753Smm * legacy PM register sleep support. 292228753Smm */ 293228753Smm if (AcpiGbl_ReducedHardware) 294228753Smm { 295228753Smm Status = SleepFunctions->ExtendedFunction (SleepState); 296228753Smm } 297228753Smm else 298228753Smm { 299228753Smm /* Legacy sleep */ 300228753Smm 301228753Smm Status = SleepFunctions->LegacyFunction (SleepState); 302228753Smm } 303228753Smm 304228753Smm return (Status); 305228753Smm 306228753Smm#else 307228753Smm /* 308228753Smm * For the case where reduced-hardware-only code is being generated, 309228753Smm * we know that only the extended sleep registers are available 310228753Smm */ 311228753Smm Status = SleepFunctions->ExtendedFunction (SleepState); 312228753Smm return (Status); 313228753Smm 314228753Smm#endif /* !ACPI_REDUCED_HARDWARE */ 315228753Smm} 316228753Smm 317228753Smm 318228753Smm/******************************************************************************* 319228753Smm * 320228753Smm * FUNCTION: AcpiEnterSleepStatePrep 321228753Smm * 322228753Smm * PARAMETERS: SleepState - Which sleep state to enter 323228753Smm * 324228753Smm * RETURN: Status 325228753Smm * 326228753Smm * DESCRIPTION: Prepare to enter a system sleep state. 327228753Smm * This function must execute with interrupts enabled. 328228753Smm * We break sleeping into 2 stages so that OSPM can handle 329228753Smm * various OS-specific tasks between the two steps. 330228753Smm * 331228753Smm ******************************************************************************/ 332228753Smm 333228753SmmACPI_STATUS 334228753SmmAcpiEnterSleepStatePrep ( 335228753Smm UINT8 SleepState) 336228753Smm{ 337228753Smm ACPI_STATUS Status; 338228753Smm ACPI_OBJECT_LIST ArgList; 339228753Smm ACPI_OBJECT Arg; 340228753Smm UINT32 SstValue; 341228753Smm 342228753Smm 343228753Smm ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep); 344228753Smm 345228753Smm 346228753Smm Status = AcpiGetSleepTypeData (SleepState, 347228753Smm &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB); 348228753Smm if (ACPI_FAILURE (Status)) 349228753Smm { 350228753Smm return_ACPI_STATUS (Status); 351228753Smm } 352228753Smm 353353377Smm /* Execute the _PTS method (Prepare To Sleep) */ 354353377Smm 355228753Smm ArgList.Count = 1; 356228753Smm ArgList.Pointer = &Arg; 357228753Smm Arg.Type = ACPI_TYPE_INTEGER; 358228753Smm Arg.Integer.Value = SleepState; 359228753Smm 360228753Smm Status = AcpiEvaluateObject (NULL, METHOD_PATHNAME__PTS, &ArgList, NULL); 361228753Smm if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) 362228753Smm { 363228753Smm return_ACPI_STATUS (Status); 364228753Smm } 365228753Smm 366 /* Setup the argument to the _SST method (System STatus) */ 367 368 switch (SleepState) 369 { 370 case ACPI_STATE_S0: 371 372 SstValue = ACPI_SST_WORKING; 373 break; 374 375 case ACPI_STATE_S1: 376 case ACPI_STATE_S2: 377 case ACPI_STATE_S3: 378 379 SstValue = ACPI_SST_SLEEPING; 380 break; 381 382 case ACPI_STATE_S4: 383 384 SstValue = ACPI_SST_SLEEP_CONTEXT; 385 break; 386 387 default: 388 389 SstValue = ACPI_SST_INDICATOR_OFF; /* Default is off */ 390 break; 391 } 392 393 /* 394 * Set the system indicators to show the desired sleep state. 395 * _SST is an optional method (return no error if not found) 396 */ 397 AcpiHwExecuteSleepMethod (METHOD_PATHNAME__SST, SstValue); 398 return_ACPI_STATUS (AE_OK); 399} 400 401ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep) 402 403 404/******************************************************************************* 405 * 406 * FUNCTION: AcpiEnterSleepState 407 * 408 * PARAMETERS: SleepState - Which sleep state to enter 409 * 410 * RETURN: Status 411 * 412 * DESCRIPTION: Enter a system sleep state 413 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 414 * 415 ******************************************************************************/ 416 417ACPI_STATUS 418AcpiEnterSleepState ( 419 UINT8 SleepState) 420{ 421 ACPI_STATUS Status; 422 423 424 ACPI_FUNCTION_TRACE (AcpiEnterSleepState); 425 426 427 if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) || 428 (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX)) 429 { 430 ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X", 431 AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB)); 432 return_ACPI_STATUS (AE_AML_OPERAND_VALUE); 433 } 434 435 Status = AcpiHwSleepDispatch (SleepState, ACPI_SLEEP_FUNCTION_ID); 436 return_ACPI_STATUS (Status); 437} 438 439ACPI_EXPORT_SYMBOL (AcpiEnterSleepState) 440 441 442/******************************************************************************* 443 * 444 * FUNCTION: AcpiLeaveSleepStatePrep 445 * 446 * PARAMETERS: SleepState - Which sleep state we are exiting 447 * 448 * RETURN: Status 449 * 450 * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a 451 * sleep. Called with interrupts DISABLED. 452 * We break wake/resume into 2 stages so that OSPM can handle 453 * various OS-specific tasks between the two steps. 454 * 455 ******************************************************************************/ 456 457ACPI_STATUS 458AcpiLeaveSleepStatePrep ( 459 UINT8 SleepState) 460{ 461 ACPI_STATUS Status; 462 463 464 ACPI_FUNCTION_TRACE (AcpiLeaveSleepStatePrep); 465 466 467 Status = AcpiHwSleepDispatch (SleepState, ACPI_WAKE_PREP_FUNCTION_ID); 468 return_ACPI_STATUS (Status); 469} 470 471ACPI_EXPORT_SYMBOL (AcpiLeaveSleepStatePrep) 472 473 474/******************************************************************************* 475 * 476 * FUNCTION: AcpiLeaveSleepState 477 * 478 * PARAMETERS: SleepState - Which sleep state we are exiting 479 * 480 * RETURN: Status 481 * 482 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep 483 * Called with interrupts ENABLED. 484 * 485 ******************************************************************************/ 486 487ACPI_STATUS 488AcpiLeaveSleepState ( 489 UINT8 SleepState) 490{ 491 ACPI_STATUS Status; 492 493 494 ACPI_FUNCTION_TRACE (AcpiLeaveSleepState); 495 496 497 Status = AcpiHwSleepDispatch (SleepState, ACPI_WAKE_FUNCTION_ID); 498 return_ACPI_STATUS (Status); 499} 500 501ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState) 502