Home | History | Annotate | Line # | Download | only in hardware
hwsleep.c revision 1.1.1.2.4.2
      1 
      2 /******************************************************************************
      3  *
      4  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2011, Intel Corp.
     10  * All rights reserved.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions, and the following disclaimer,
     17  *    without modification.
     18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     19  *    substantially similar to the "NO WARRANTY" disclaimer below
     20  *    ("Disclaimer") and any redistribution must be conditioned upon
     21  *    including a substantially similar Disclaimer requirement for further
     22  *    binary redistribution.
     23  * 3. Neither the names of the above-listed copyright holders nor the names
     24  *    of any contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * Alternatively, this software may be distributed under the terms of the
     28  * GNU General Public License ("GPL") version 2 as published by the Free
     29  * Software Foundation.
     30  *
     31  * NO WARRANTY
     32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     42  * POSSIBILITY OF SUCH DAMAGES.
     43  */
     44 
     45 #include "acpi.h"
     46 #include "accommon.h"
     47 
     48 #define _COMPONENT          ACPI_HARDWARE
     49         ACPI_MODULE_NAME    ("hwsleep")
     50 
     51 
     52 /*******************************************************************************
     53  *
     54  * FUNCTION:    AcpiSetFirmwareWakingVector
     55  *
     56  * PARAMETERS:  PhysicalAddress     - 32-bit physical address of ACPI real mode
     57  *                                    entry point.
     58  *
     59  * RETURN:      Status
     60  *
     61  * DESCRIPTION: Sets the 32-bit FirmwareWakingVector field of the FACS
     62  *
     63  ******************************************************************************/
     64 
     65 ACPI_STATUS
     66 AcpiSetFirmwareWakingVector (
     67     UINT32                  PhysicalAddress)
     68 {
     69     ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector);
     70 
     71 
     72     /* Set the 32-bit vector */
     73 
     74     AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress;
     75 
     76     /* Clear the 64-bit vector if it exists */
     77 
     78     if ((AcpiGbl_FACS->Length > 32) && (AcpiGbl_FACS->Version >= 1))
     79     {
     80         AcpiGbl_FACS->XFirmwareWakingVector = 0;
     81     }
     82 
     83     return_ACPI_STATUS (AE_OK);
     84 }
     85 
     86 ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector)
     87 
     88 
     89 #if ACPI_MACHINE_WIDTH == 64
     90 /*******************************************************************************
     91  *
     92  * FUNCTION:    AcpiSetFirmwareWakingVector64
     93  *
     94  * PARAMETERS:  PhysicalAddress     - 64-bit physical address of ACPI protected
     95  *                                    mode entry point.
     96  *
     97  * RETURN:      Status
     98  *
     99  * DESCRIPTION: Sets the 64-bit X_FirmwareWakingVector field of the FACS, if
    100  *              it exists in the table. This function is intended for use with
    101  *              64-bit host operating systems.
    102  *
    103  ******************************************************************************/
    104 
    105 ACPI_STATUS
    106 AcpiSetFirmwareWakingVector64 (
    107     UINT64                  PhysicalAddress)
    108 {
    109     ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64);
    110 
    111 
    112     /* Determine if the 64-bit vector actually exists */
    113 
    114     if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1))
    115     {
    116         return_ACPI_STATUS (AE_NOT_EXIST);
    117     }
    118 
    119     /* Clear 32-bit vector, set the 64-bit X_ vector */
    120 
    121     AcpiGbl_FACS->FirmwareWakingVector = 0;
    122     AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress;
    123     return_ACPI_STATUS (AE_OK);
    124 }
    125 
    126 ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector64)
    127 #endif
    128 
    129 /*******************************************************************************
    130  *
    131  * FUNCTION:    AcpiEnterSleepStatePrep
    132  *
    133  * PARAMETERS:  SleepState          - Which sleep state to enter
    134  *
    135  * RETURN:      Status
    136  *
    137  * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
    138  *              This function must execute with interrupts enabled.
    139  *              We break sleeping into 2 stages so that OSPM can handle
    140  *              various OS-specific tasks between the two steps.
    141  *
    142  ******************************************************************************/
    143 
    144 ACPI_STATUS
    145 AcpiEnterSleepStatePrep (
    146     UINT8                   SleepState)
    147 {
    148     ACPI_STATUS             Status;
    149     ACPI_OBJECT_LIST        ArgList;
    150     ACPI_OBJECT             Arg;
    151 
    152 
    153     ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep);
    154 
    155 
    156     /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */
    157 
    158     Status = AcpiGetSleepTypeData (SleepState,
    159                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
    160     if (ACPI_FAILURE (Status))
    161     {
    162         return_ACPI_STATUS (Status);
    163     }
    164 
    165     /* Execute the _PTS method (Prepare To Sleep) */
    166 
    167     ArgList.Count = 1;
    168     ArgList.Pointer = &Arg;
    169     Arg.Type = ACPI_TYPE_INTEGER;
    170     Arg.Integer.Value = SleepState;
    171 
    172     Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL);
    173     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
    174     {
    175         return_ACPI_STATUS (Status);
    176     }
    177 
    178     /* Setup the argument to the _SST method (System STatus) */
    179 
    180     switch (SleepState)
    181     {
    182     case ACPI_STATE_S0:
    183         Arg.Integer.Value = ACPI_SST_WORKING;
    184         break;
    185 
    186     case ACPI_STATE_S1:
    187     case ACPI_STATE_S2:
    188     case ACPI_STATE_S3:
    189         Arg.Integer.Value = ACPI_SST_SLEEPING;
    190         break;
    191 
    192     case ACPI_STATE_S4:
    193         Arg.Integer.Value = ACPI_SST_SLEEP_CONTEXT;
    194         break;
    195 
    196     default:
    197         Arg.Integer.Value = ACPI_SST_INDICATOR_OFF; /* Default is off */
    198         break;
    199     }
    200 
    201     /*
    202      * Set the system indicators to show the desired sleep state.
    203      * _SST is an optional method (return no error if not found)
    204      */
    205     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
    206     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
    207     {
    208         ACPI_EXCEPTION ((AE_INFO, Status, "While executing method _SST"));
    209     }
    210 
    211     return_ACPI_STATUS (AE_OK);
    212 }
    213 
    214 ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep)
    215 
    216 
    217 /*******************************************************************************
    218  *
    219  * FUNCTION:    AcpiEnterSleepState
    220  *
    221  * PARAMETERS:  SleepState          - Which sleep state to enter
    222  *
    223  * RETURN:      Status
    224  *
    225  * DESCRIPTION: Enter a system sleep state
    226  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
    227  *
    228  ******************************************************************************/
    229 
    230 ACPI_STATUS
    231 AcpiEnterSleepState (
    232     UINT8                   SleepState)
    233 {
    234     UINT32                  Pm1aControl;
    235     UINT32                  Pm1bControl;
    236     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
    237     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
    238     UINT32                  InValue;
    239     ACPI_OBJECT_LIST        ArgList;
    240     ACPI_OBJECT             Arg;
    241     ACPI_STATUS             Status;
    242 
    243 
    244     ACPI_FUNCTION_TRACE (AcpiEnterSleepState);
    245 
    246 
    247     if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) ||
    248         (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX))
    249     {
    250         ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X",
    251             AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB));
    252         return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
    253     }
    254 
    255     SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE);
    256     SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
    257 
    258     /* Clear wake status */
    259 
    260     Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
    261     if (ACPI_FAILURE (Status))
    262     {
    263         return_ACPI_STATUS (Status);
    264     }
    265 
    266     /* Clear all fixed and general purpose status bits */
    267 
    268     Status = AcpiHwClearAcpiStatus ();
    269     if (ACPI_FAILURE (Status))
    270     {
    271         return_ACPI_STATUS (Status);
    272     }
    273 
    274     if (SleepState != ACPI_STATE_S5)
    275     {
    276         /*
    277          * Disable BM arbitration. This feature is contained within an
    278          * optional register (PM2 Control), so ignore a BAD_ADDRESS
    279          * exception.
    280          */
    281         Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 1);
    282         if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS))
    283         {
    284             return_ACPI_STATUS (Status);
    285         }
    286     }
    287 
    288     /*
    289      * 1) Disable/Clear all GPEs
    290      * 2) Enable all wakeup GPEs
    291      */
    292     Status = AcpiHwDisableAllGpes ();
    293     if (ACPI_FAILURE (Status))
    294     {
    295         return_ACPI_STATUS (Status);
    296     }
    297     AcpiGbl_SystemAwakeAndRunning = FALSE;
    298 
    299     Status = AcpiHwEnableAllWakeupGpes ();
    300     if (ACPI_FAILURE (Status))
    301     {
    302         return_ACPI_STATUS (Status);
    303     }
    304 
    305     /* Execute the _GTS method (Going To Sleep) */
    306 
    307     ArgList.Count = 1;
    308     ArgList.Pointer = &Arg;
    309     Arg.Type = ACPI_TYPE_INTEGER;
    310     Arg.Integer.Value = SleepState;
    311 
    312     Status = AcpiEvaluateObject (NULL, METHOD_NAME__GTS, &ArgList, NULL);
    313     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
    314     {
    315         return_ACPI_STATUS (Status);
    316     }
    317 
    318     /* Get current value of PM1A control */
    319 
    320     Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
    321                 &Pm1aControl);
    322     if (ACPI_FAILURE (Status))
    323     {
    324         return_ACPI_STATUS (Status);
    325     }
    326     ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
    327         "Entering sleep state [S%u]\n", SleepState));
    328 
    329     /* Clear the SLP_EN and SLP_TYP fields */
    330 
    331     Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask |
    332                      SleepEnableRegInfo->AccessBitMask);
    333     Pm1bControl = Pm1aControl;
    334 
    335     /* Insert the SLP_TYP bits */
    336 
    337     Pm1aControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
    338     Pm1bControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
    339 
    340     /*
    341      * We split the writes of SLP_TYP and SLP_EN to workaround
    342      * poorly implemented hardware.
    343      */
    344 
    345     /* Write #1: write the SLP_TYP data to the PM1 Control registers */
    346 
    347     Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
    348     if (ACPI_FAILURE (Status))
    349     {
    350         return_ACPI_STATUS (Status);
    351     }
    352 
    353     /* Insert the sleep enable (SLP_EN) bit */
    354 
    355     Pm1aControl |= SleepEnableRegInfo->AccessBitMask;
    356     Pm1bControl |= SleepEnableRegInfo->AccessBitMask;
    357 
    358     /* Flush caches, as per ACPI specification */
    359 
    360     ACPI_FLUSH_CPU_CACHE ();
    361 
    362     /* Write #2: Write both SLP_TYP + SLP_EN */
    363 
    364     Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
    365     if (ACPI_FAILURE (Status))
    366     {
    367         return_ACPI_STATUS (Status);
    368     }
    369 
    370     if (SleepState > ACPI_STATE_S3)
    371     {
    372         /*
    373          * We wanted to sleep > S3, but it didn't happen (by virtue of the
    374          * fact that we are still executing!)
    375          *
    376          * Wait ten seconds, then try again. This is to get S4/S5 to work on
    377          * all machines.
    378          *
    379          * We wait so long to allow chipsets that poll this reg very slowly
    380          * to still read the right value. Ideally, this block would go
    381          * away entirely.
    382          */
    383         AcpiOsStall (10000000);
    384 
    385         Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL,
    386                     SleepEnableRegInfo->AccessBitMask);
    387         if (ACPI_FAILURE (Status))
    388         {
    389             return_ACPI_STATUS (Status);
    390         }
    391     }
    392 
    393     /* Wait until we enter sleep state */
    394 
    395     do
    396     {
    397         Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
    398         if (ACPI_FAILURE (Status))
    399         {
    400             return_ACPI_STATUS (Status);
    401         }
    402 
    403         /* Spin until we wake */
    404 
    405     } while (!InValue);
    406 
    407     return_ACPI_STATUS (AE_OK);
    408 }
    409 
    410 ACPI_EXPORT_SYMBOL (AcpiEnterSleepState)
    411 
    412 
    413 /*******************************************************************************
    414  *
    415  * FUNCTION:    AcpiEnterSleepStateS4bios
    416  *
    417  * PARAMETERS:  None
    418  *
    419  * RETURN:      Status
    420  *
    421  * DESCRIPTION: Perform a S4 bios request.
    422  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
    423  *
    424  ******************************************************************************/
    425 
    426 ACPI_STATUS
    427 AcpiEnterSleepStateS4bios (
    428     void)
    429 {
    430     UINT32                  InValue;
    431     ACPI_STATUS             Status;
    432 
    433 
    434     ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios);
    435 
    436 
    437     /* Clear the wake status bit (PM1) */
    438 
    439     Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
    440     if (ACPI_FAILURE (Status))
    441     {
    442         return_ACPI_STATUS (Status);
    443     }
    444 
    445     Status = AcpiHwClearAcpiStatus ();
    446     if (ACPI_FAILURE (Status))
    447     {
    448         return_ACPI_STATUS (Status);
    449     }
    450 
    451     /*
    452      * 1) Disable/Clear all GPEs
    453      * 2) Enable all wakeup GPEs
    454      */
    455     Status = AcpiHwDisableAllGpes ();
    456     if (ACPI_FAILURE (Status))
    457     {
    458         return_ACPI_STATUS (Status);
    459     }
    460     AcpiGbl_SystemAwakeAndRunning = FALSE;
    461 
    462     Status = AcpiHwEnableAllWakeupGpes ();
    463     if (ACPI_FAILURE (Status))
    464     {
    465         return_ACPI_STATUS (Status);
    466     }
    467 
    468     ACPI_FLUSH_CPU_CACHE ();
    469 
    470     Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
    471                 (UINT32) AcpiGbl_FADT.S4BiosRequest, 8);
    472 
    473     do {
    474         AcpiOsStall(1000);
    475         Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
    476         if (ACPI_FAILURE (Status))
    477         {
    478             return_ACPI_STATUS (Status);
    479         }
    480     } while (!InValue);
    481 
    482     return_ACPI_STATUS (AE_OK);
    483 }
    484 
    485 ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios)
    486 
    487 
    488 /*******************************************************************************
    489  *
    490  * FUNCTION:    AcpiLeaveSleepState
    491  *
    492  * PARAMETERS:  SleepState          - Which sleep state we just exited
    493  *
    494  * RETURN:      Status
    495  *
    496  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
    497  *              Called with interrupts ENABLED.
    498  *
    499  ******************************************************************************/
    500 
    501 ACPI_STATUS
    502 AcpiLeaveSleepState (
    503     UINT8                   SleepState)
    504 {
    505     ACPI_OBJECT_LIST        ArgList;
    506     ACPI_OBJECT             Arg;
    507     ACPI_STATUS             Status;
    508     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
    509     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
    510     UINT32                  Pm1aControl;
    511     UINT32                  Pm1bControl;
    512 
    513 
    514     ACPI_FUNCTION_TRACE (AcpiLeaveSleepState);
    515 
    516 
    517     /*
    518      * Set SLP_TYPE and SLP_EN to state S0.
    519      * This is unclear from the ACPI Spec, but it is required
    520      * by some machines.
    521      */
    522     Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
    523                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
    524     if (ACPI_SUCCESS (Status))
    525     {
    526         SleepTypeRegInfo =
    527             AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE);
    528         SleepEnableRegInfo =
    529             AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
    530 
    531         /* Get current value of PM1A control */
    532 
    533         Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
    534                     &Pm1aControl);
    535         if (ACPI_SUCCESS (Status))
    536         {
    537             /* Clear the SLP_EN and SLP_TYP fields */
    538 
    539             Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask |
    540                 SleepEnableRegInfo->AccessBitMask);
    541             Pm1bControl = Pm1aControl;
    542 
    543             /* Insert the SLP_TYP bits */
    544 
    545             Pm1aControl |= (AcpiGbl_SleepTypeA <<
    546                 SleepTypeRegInfo->BitPosition);
    547             Pm1bControl |= (AcpiGbl_SleepTypeB <<
    548                 SleepTypeRegInfo->BitPosition);
    549 
    550             /* Write the control registers and ignore any errors */
    551 
    552             (void) AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
    553         }
    554     }
    555 
    556     /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
    557 
    558     AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
    559 
    560     /* Setup parameter object */
    561 
    562     ArgList.Count = 1;
    563     ArgList.Pointer = &Arg;
    564     Arg.Type = ACPI_TYPE_INTEGER;
    565 
    566     /* Ignore any errors from these methods */
    567 
    568     Arg.Integer.Value = ACPI_SST_WAKING;
    569     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
    570     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
    571     {
    572         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
    573     }
    574 
    575     Arg.Integer.Value = SleepState;
    576     Status = AcpiEvaluateObject (NULL, METHOD_NAME__BFS, &ArgList, NULL);
    577     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
    578     {
    579         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _BFS"));
    580     }
    581 
    582     Status = AcpiEvaluateObject (NULL, METHOD_NAME__WAK, &ArgList, NULL);
    583     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
    584     {
    585         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _WAK"));
    586     }
    587     /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
    588 
    589     /*
    590      * Restore the GPEs:
    591      * 1) Disable/Clear all GPEs
    592      * 2) Enable all runtime GPEs
    593      */
    594     Status = AcpiHwDisableAllGpes ();
    595     if (ACPI_FAILURE (Status))
    596     {
    597         return_ACPI_STATUS (Status);
    598     }
    599     AcpiGbl_SystemAwakeAndRunning = TRUE;
    600 
    601     Status = AcpiHwEnableAllRuntimeGpes ();
    602     if (ACPI_FAILURE (Status))
    603     {
    604         return_ACPI_STATUS (Status);
    605     }
    606 
    607     /* Enable power button */
    608 
    609     (void) AcpiWriteBitRegister(
    610             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].EnableRegisterId,
    611             ACPI_ENABLE_EVENT);
    612 
    613     (void) AcpiWriteBitRegister(
    614             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId,
    615             ACPI_CLEAR_STATUS);
    616 
    617     /*
    618      * Enable BM arbitration. This feature is contained within an
    619      * optional register (PM2 Control), so ignore a BAD_ADDRESS
    620      * exception.
    621      */
    622     Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 0);
    623     if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS))
    624     {
    625         return_ACPI_STATUS (Status);
    626     }
    627 
    628     Arg.Integer.Value = ACPI_SST_WORKING;
    629     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
    630     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
    631     {
    632         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
    633     }
    634 
    635     return_ACPI_STATUS (Status);
    636 }
    637 
    638 ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState)
    639 
    640