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