Home | History | Annotate | Line # | Download | only in hardware
hwxfsleep.c revision 1.6
      1 /******************************************************************************
      2  *
      3  * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, 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 (AcpiGbl_FACS)
    173     {
    174         (void) AcpiHwSetFirmwareWakingVector (AcpiGbl_FACS,
    175             PhysicalAddress, PhysicalAddress64);
    176     }
    177 
    178     return_ACPI_STATUS (AE_OK);
    179 }
    180 
    181 ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector)
    182 
    183 
    184 /*******************************************************************************
    185  *
    186  * FUNCTION:    AcpiEnterSleepStateS4bios
    187  *
    188  * PARAMETERS:  None
    189  *
    190  * RETURN:      Status
    191  *
    192  * DESCRIPTION: Perform a S4 bios request.
    193  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
    194  *
    195  ******************************************************************************/
    196 
    197 ACPI_STATUS
    198 AcpiEnterSleepStateS4bios (
    199     void)
    200 {
    201     UINT32                  InValue;
    202     ACPI_STATUS             Status;
    203 
    204 
    205     ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios);
    206 
    207 
    208     /* Clear the wake status bit (PM1) */
    209 
    210     Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
    211     if (ACPI_FAILURE (Status))
    212     {
    213         return_ACPI_STATUS (Status);
    214     }
    215 
    216     Status = AcpiHwClearAcpiStatus ();
    217     if (ACPI_FAILURE (Status))
    218     {
    219         return_ACPI_STATUS (Status);
    220     }
    221 
    222     /*
    223      * 1) Disable/Clear all GPEs
    224      * 2) Enable all wakeup GPEs
    225      */
    226     Status = AcpiHwDisableAllGpes ();
    227     if (ACPI_FAILURE (Status))
    228     {
    229         return_ACPI_STATUS (Status);
    230     }
    231     AcpiGbl_SystemAwakeAndRunning = FALSE;
    232 
    233     Status = AcpiHwEnableAllWakeupGpes ();
    234     if (ACPI_FAILURE (Status))
    235     {
    236         return_ACPI_STATUS (Status);
    237     }
    238 
    239     ACPI_FLUSH_CPU_CACHE ();
    240 
    241     Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
    242         (UINT32) AcpiGbl_FADT.S4BiosRequest, 8);
    243 
    244     do {
    245         AcpiOsStall (ACPI_USEC_PER_MSEC);
    246         Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
    247         if (ACPI_FAILURE (Status))
    248         {
    249             return_ACPI_STATUS (Status);
    250         }
    251 
    252     } while (!InValue);
    253 
    254     return_ACPI_STATUS (AE_OK);
    255 }
    256 
    257 ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios)
    258 
    259 #endif /* !ACPI_REDUCED_HARDWARE */
    260 
    261 
    262 /*******************************************************************************
    263  *
    264  * FUNCTION:    AcpiHwSleepDispatch
    265  *
    266  * PARAMETERS:  SleepState          - Which sleep state to enter/exit
    267  *              FunctionId          - Sleep, WakePrep, or Wake
    268  *
    269  * RETURN:      Status from the invoked sleep handling function.
    270  *
    271  * DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling
    272  *              function.
    273  *
    274  ******************************************************************************/
    275 
    276 static ACPI_STATUS
    277 AcpiHwSleepDispatch (
    278     UINT8                   SleepState,
    279     UINT32                  FunctionId)
    280 {
    281     ACPI_STATUS             Status;
    282     ACPI_SLEEP_FUNCTIONS    *SleepFunctions = &AcpiSleepDispatch[FunctionId];
    283 
    284 
    285 #if (!ACPI_REDUCED_HARDWARE)
    286     /*
    287      * If the Hardware Reduced flag is set (from the FADT), we must
    288      * use the extended sleep registers (FADT). Note: As per the ACPI
    289      * specification, these extended registers are to be used for HW-reduced
    290      * platforms only. They are not general-purpose replacements for the
    291      * legacy PM register sleep support.
    292      */
    293     if (AcpiGbl_ReducedHardware)
    294     {
    295         Status = SleepFunctions->ExtendedFunction (SleepState);
    296     }
    297     else
    298     {
    299         /* Legacy sleep */
    300 
    301         Status = SleepFunctions->LegacyFunction (SleepState);
    302     }
    303 
    304     return (Status);
    305 
    306 #else
    307     /*
    308      * For the case where reduced-hardware-only code is being generated,
    309      * we know that only the extended sleep registers are available
    310      */
    311     Status = SleepFunctions->ExtendedFunction (SleepState);
    312     return (Status);
    313 
    314 #endif /* !ACPI_REDUCED_HARDWARE */
    315 }
    316 
    317 
    318 /*******************************************************************************
    319  *
    320  * FUNCTION:    AcpiEnterSleepStatePrep
    321  *
    322  * PARAMETERS:  SleepState          - Which sleep state to enter
    323  *
    324  * RETURN:      Status
    325  *
    326  * DESCRIPTION: Prepare to enter a system sleep state.
    327  *              This function must execute with interrupts enabled.
    328  *              We break sleeping into 2 stages so that OSPM can handle
    329  *              various OS-specific tasks between the two steps.
    330  *
    331  ******************************************************************************/
    332 
    333 ACPI_STATUS
    334 AcpiEnterSleepStatePrep (
    335     UINT8                   SleepState)
    336 {
    337     ACPI_STATUS             Status;
    338     ACPI_OBJECT_LIST        ArgList;
    339     ACPI_OBJECT             Arg;
    340     UINT32                  SstValue;
    341 
    342 
    343     ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep);
    344 
    345 
    346     Status = AcpiGetSleepTypeData (SleepState,
    347         &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
    348     if (ACPI_FAILURE (Status))
    349     {
    350         return_ACPI_STATUS (Status);
    351     }
    352 
    353     /* Execute the _PTS method (Prepare To Sleep) */
    354 
    355     ArgList.Count = 1;
    356     ArgList.Pointer = &Arg;
    357     Arg.Type = ACPI_TYPE_INTEGER;
    358     Arg.Integer.Value = SleepState;
    359 
    360     Status = AcpiEvaluateObject (NULL, METHOD_PATHNAME__PTS, &ArgList, NULL);
    361     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
    362     {
    363         return_ACPI_STATUS (Status);
    364     }
    365 
    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 (__UNCONST(METHOD_PATHNAME__SST), SstValue);
    398     return_ACPI_STATUS (AE_OK);
    399 }
    400 
    401 ACPI_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 
    417 ACPI_STATUS
    418 AcpiEnterSleepState (
    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 
    439 ACPI_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 
    457 ACPI_STATUS
    458 AcpiLeaveSleepStatePrep (
    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 
    471 ACPI_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 
    487 ACPI_STATUS
    488 AcpiLeaveSleepState (
    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 
    501 ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState)
    502