xref: /onnv-gate/usr/src/uts/intel/io/acpica/hardware/hwsleep.c (revision 7851:e828bbb1689c)
13446Smrj 
23446Smrj /******************************************************************************
33446Smrj  *
43446Smrj  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
5*7851SDana.Myers@Sun.COM  *              $Revision: 1.89 $
63446Smrj  *
73446Smrj  *****************************************************************************/
83446Smrj 
93446Smrj /******************************************************************************
103446Smrj  *
113446Smrj  * 1. Copyright Notice
123446Smrj  *
13*7851SDana.Myers@Sun.COM  * Some or all of this work - Copyright (c) 1999 - 2008, Intel Corp.
143446Smrj  * All rights reserved.
153446Smrj  *
163446Smrj  * 2. License
173446Smrj  *
183446Smrj  * 2.1. This is your license from Intel Corp. under its intellectual property
193446Smrj  * rights.  You may have additional license terms from the party that provided
203446Smrj  * you this software, covering your right to use that party's intellectual
213446Smrj  * property rights.
223446Smrj  *
233446Smrj  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
243446Smrj  * copy of the source code appearing in this file ("Covered Code") an
253446Smrj  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
263446Smrj  * base code distributed originally by Intel ("Original Intel Code") to copy,
273446Smrj  * make derivatives, distribute, use and display any portion of the Covered
283446Smrj  * Code in any form, with the right to sublicense such rights; and
293446Smrj  *
303446Smrj  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
313446Smrj  * license (with the right to sublicense), under only those claims of Intel
323446Smrj  * patents that are infringed by the Original Intel Code, to make, use, sell,
333446Smrj  * offer to sell, and import the Covered Code and derivative works thereof
343446Smrj  * solely to the minimum extent necessary to exercise the above copyright
353446Smrj  * license, and in no event shall the patent license extend to any additions
363446Smrj  * to or modifications of the Original Intel Code.  No other license or right
373446Smrj  * is granted directly or by implication, estoppel or otherwise;
383446Smrj  *
393446Smrj  * The above copyright and patent license is granted only if the following
403446Smrj  * conditions are met:
413446Smrj  *
423446Smrj  * 3. Conditions
433446Smrj  *
443446Smrj  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
453446Smrj  * Redistribution of source code of any substantial portion of the Covered
463446Smrj  * Code or modification with rights to further distribute source must include
473446Smrj  * the above Copyright Notice, the above License, this list of Conditions,
483446Smrj  * and the following Disclaimer and Export Compliance provision.  In addition,
493446Smrj  * Licensee must cause all Covered Code to which Licensee contributes to
503446Smrj  * contain a file documenting the changes Licensee made to create that Covered
513446Smrj  * Code and the date of any change.  Licensee must include in that file the
523446Smrj  * documentation of any changes made by any predecessor Licensee.  Licensee
533446Smrj  * must include a prominent statement that the modification is derived,
543446Smrj  * directly or indirectly, from Original Intel Code.
553446Smrj  *
563446Smrj  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
573446Smrj  * Redistribution of source code of any substantial portion of the Covered
583446Smrj  * Code or modification without rights to further distribute source must
593446Smrj  * include the following Disclaimer and Export Compliance provision in the
603446Smrj  * documentation and/or other materials provided with distribution.  In
613446Smrj  * addition, Licensee may not authorize further sublicense of source of any
623446Smrj  * portion of the Covered Code, and must include terms to the effect that the
633446Smrj  * license from Licensee to its licensee is limited to the intellectual
643446Smrj  * property embodied in the software Licensee provides to its licensee, and
653446Smrj  * not to intellectual property embodied in modifications its licensee may
663446Smrj  * make.
673446Smrj  *
683446Smrj  * 3.3. Redistribution of Executable. Redistribution in executable form of any
693446Smrj  * substantial portion of the Covered Code or modification must reproduce the
703446Smrj  * above Copyright Notice, and the following Disclaimer and Export Compliance
713446Smrj  * provision in the documentation and/or other materials provided with the
723446Smrj  * distribution.
733446Smrj  *
743446Smrj  * 3.4. Intel retains all right, title, and interest in and to the Original
753446Smrj  * Intel Code.
763446Smrj  *
773446Smrj  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
783446Smrj  * Intel shall be used in advertising or otherwise to promote the sale, use or
793446Smrj  * other dealings in products derived from or relating to the Covered Code
803446Smrj  * without prior written authorization from Intel.
813446Smrj  *
823446Smrj  * 4. Disclaimer and Export Compliance
833446Smrj  *
843446Smrj  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
853446Smrj  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
863446Smrj  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
873446Smrj  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
883446Smrj  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
893446Smrj  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
903446Smrj  * PARTICULAR PURPOSE.
913446Smrj  *
923446Smrj  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
933446Smrj  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
943446Smrj  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
953446Smrj  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
963446Smrj  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
973446Smrj  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
983446Smrj  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
993446Smrj  * LIMITED REMEDY.
1003446Smrj  *
1013446Smrj  * 4.3. Licensee shall not export, either directly or indirectly, any of this
1023446Smrj  * software or system incorporating such software without first obtaining any
1033446Smrj  * required license or other approval from the U. S. Department of Commerce or
1043446Smrj  * any other agency or department of the United States Government.  In the
1053446Smrj  * event Licensee exports any such software from the United States or
1063446Smrj  * re-exports any such software from a foreign destination, Licensee shall
1073446Smrj  * ensure that the distribution and export/re-export of the software is in
1083446Smrj  * compliance with all laws, regulations, orders, or other restrictions of the
1093446Smrj  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1103446Smrj  * any of its subsidiaries will export/re-export any technical data, process,
1113446Smrj  * software, or service, directly or indirectly, to any country for which the
1123446Smrj  * United States government or any agency thereof requires an export license,
1133446Smrj  * other governmental approval, or letter of assurance, without first obtaining
1143446Smrj  * such license, approval or letter.
1153446Smrj  *
1163446Smrj  *****************************************************************************/
1173446Smrj 
1183446Smrj #include "acpi.h"
1193446Smrj 
1203446Smrj #define _COMPONENT          ACPI_HARDWARE
1213446Smrj         ACPI_MODULE_NAME    ("hwsleep")
1223446Smrj 
1233446Smrj 
1243446Smrj /*******************************************************************************
1253446Smrj  *
1263446Smrj  * FUNCTION:    AcpiSetFirmwareWakingVector
1273446Smrj  *
1283446Smrj  * PARAMETERS:  PhysicalAddress     - Physical address of ACPI real mode
1293446Smrj  *                                    entry point.
1303446Smrj  *
1313446Smrj  * RETURN:      Status
1323446Smrj  *
1333446Smrj  * DESCRIPTION: Access function for the FirmwareWakingVector field in FACS
1343446Smrj  *
1353446Smrj  ******************************************************************************/
1363446Smrj 
1373446Smrj ACPI_STATUS
1383446Smrj AcpiSetFirmwareWakingVector (
139*7851SDana.Myers@Sun.COM     ACPI_PHYSICAL_ADDRESS   PhysicalAddress)
1403446Smrj {
141*7851SDana.Myers@Sun.COM     ACPI_TABLE_FACS         *Facs;
142*7851SDana.Myers@Sun.COM     ACPI_STATUS             Status;
143*7851SDana.Myers@Sun.COM 
1443446Smrj 
1453446Smrj     ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector);
1463446Smrj 
147*7851SDana.Myers@Sun.COM     /* Get the FACS */
148*7851SDana.Myers@Sun.COM 
149*7851SDana.Myers@Sun.COM     Status = AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS,
150*7851SDana.Myers@Sun.COM                 ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs));
151*7851SDana.Myers@Sun.COM     if (ACPI_FAILURE (Status))
152*7851SDana.Myers@Sun.COM     {
153*7851SDana.Myers@Sun.COM         return_ACPI_STATUS (Status);
154*7851SDana.Myers@Sun.COM     }
1553446Smrj 
1563446Smrj     /* Set the vector */
1573446Smrj 
158*7851SDana.Myers@Sun.COM     if ((Facs->Length < 32) ||
159*7851SDana.Myers@Sun.COM         (!(Facs->XFirmwareWakingVector)))
1603446Smrj     {
161*7851SDana.Myers@Sun.COM         /*
162*7851SDana.Myers@Sun.COM          * ACPI 1.0 FACS or short table or optional X_ field is zero
163*7851SDana.Myers@Sun.COM          */
164*7851SDana.Myers@Sun.COM         Facs->FirmwareWakingVector = (UINT32) PhysicalAddress;
1653446Smrj     }
1663446Smrj     else
1673446Smrj     {
168*7851SDana.Myers@Sun.COM         /*
169*7851SDana.Myers@Sun.COM          * ACPI 2.0 FACS with valid X_ field
170*7851SDana.Myers@Sun.COM          */
171*7851SDana.Myers@Sun.COM         Facs->XFirmwareWakingVector = PhysicalAddress;
1723446Smrj     }
1733446Smrj 
1743446Smrj     return_ACPI_STATUS (AE_OK);
1753446Smrj }
1763446Smrj 
1773446Smrj ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector)
1783446Smrj 
1793446Smrj 
1803446Smrj /*******************************************************************************
1813446Smrj  *
1823446Smrj  * FUNCTION:    AcpiGetFirmwareWakingVector
1833446Smrj  *
1843446Smrj  * PARAMETERS:  *PhysicalAddress    - Where the contents of
1853446Smrj  *                                    the FirmwareWakingVector field of
1863446Smrj  *                                    the FACS will be returned.
1873446Smrj  *
1883446Smrj  * RETURN:      Status, vector
1893446Smrj  *
1903446Smrj  * DESCRIPTION: Access function for the FirmwareWakingVector field in FACS
1913446Smrj  *
1923446Smrj  ******************************************************************************/
1933446Smrj 
1943446Smrj ACPI_STATUS
1953446Smrj AcpiGetFirmwareWakingVector (
196*7851SDana.Myers@Sun.COM     ACPI_PHYSICAL_ADDRESS   *PhysicalAddress)
1973446Smrj {
198*7851SDana.Myers@Sun.COM     ACPI_TABLE_FACS         *Facs;
199*7851SDana.Myers@Sun.COM     ACPI_STATUS             Status;
200*7851SDana.Myers@Sun.COM 
2013446Smrj 
2023446Smrj     ACPI_FUNCTION_TRACE (AcpiGetFirmwareWakingVector);
2033446Smrj 
2043446Smrj 
2053446Smrj     if (!PhysicalAddress)
2063446Smrj     {
2073446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
2083446Smrj     }
2093446Smrj 
210*7851SDana.Myers@Sun.COM     /* Get the FACS */
211*7851SDana.Myers@Sun.COM 
212*7851SDana.Myers@Sun.COM     Status = AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS,
213*7851SDana.Myers@Sun.COM                 ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs));
214*7851SDana.Myers@Sun.COM     if (ACPI_FAILURE (Status))
215*7851SDana.Myers@Sun.COM     {
216*7851SDana.Myers@Sun.COM         return_ACPI_STATUS (Status);
217*7851SDana.Myers@Sun.COM     }
218*7851SDana.Myers@Sun.COM 
2193446Smrj     /* Get the vector */
2203446Smrj 
221*7851SDana.Myers@Sun.COM     if ((Facs->Length < 32) ||
222*7851SDana.Myers@Sun.COM         (!(Facs->XFirmwareWakingVector)))
2233446Smrj     {
224*7851SDana.Myers@Sun.COM         /*
225*7851SDana.Myers@Sun.COM          * ACPI 1.0 FACS or short table or optional X_ field is zero
226*7851SDana.Myers@Sun.COM          */
227*7851SDana.Myers@Sun.COM         *PhysicalAddress =
228*7851SDana.Myers@Sun.COM             (ACPI_PHYSICAL_ADDRESS) Facs->FirmwareWakingVector;
2293446Smrj     }
2303446Smrj     else
2313446Smrj     {
232*7851SDana.Myers@Sun.COM         /*
233*7851SDana.Myers@Sun.COM          * ACPI 2.0 FACS with valid X_ field
234*7851SDana.Myers@Sun.COM          */
235*7851SDana.Myers@Sun.COM         *PhysicalAddress = (ACPI_PHYSICAL_ADDRESS) Facs->XFirmwareWakingVector;
2363446Smrj     }
2373446Smrj 
2383446Smrj     return_ACPI_STATUS (AE_OK);
2393446Smrj }
2403446Smrj 
2413446Smrj ACPI_EXPORT_SYMBOL (AcpiGetFirmwareWakingVector)
2423446Smrj 
2433446Smrj 
2443446Smrj /*******************************************************************************
2453446Smrj  *
2463446Smrj  * FUNCTION:    AcpiEnterSleepStatePrep
2473446Smrj  *
2483446Smrj  * PARAMETERS:  SleepState          - Which sleep state to enter
2493446Smrj  *
2503446Smrj  * RETURN:      Status
2513446Smrj  *
2523446Smrj  * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
2533446Smrj  *              This function must execute with interrupts enabled.
2543446Smrj  *              We break sleeping into 2 stages so that OSPM can handle
2553446Smrj  *              various OS-specific tasks between the two steps.
2563446Smrj  *
2573446Smrj  ******************************************************************************/
2583446Smrj 
2593446Smrj ACPI_STATUS
2603446Smrj AcpiEnterSleepStatePrep (
261*7851SDana.Myers@Sun.COM     UINT8                   SleepState)
2623446Smrj {
263*7851SDana.Myers@Sun.COM     ACPI_STATUS             Status;
264*7851SDana.Myers@Sun.COM     ACPI_OBJECT_LIST        ArgList;
265*7851SDana.Myers@Sun.COM     ACPI_OBJECT             Arg;
2663446Smrj 
2673446Smrj 
2683446Smrj     ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep);
2693446Smrj 
2703446Smrj 
2713446Smrj     /*
2723446Smrj      * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
2733446Smrj      */
2743446Smrj     Status = AcpiGetSleepTypeData (SleepState,
2753446Smrj                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
2763446Smrj     if (ACPI_FAILURE (Status))
2773446Smrj     {
2783446Smrj         return_ACPI_STATUS (Status);
2793446Smrj     }
2803446Smrj 
281*7851SDana.Myers@Sun.COM     /* Execute the _PTS method (Prepare To Sleep) */
2823446Smrj 
2833446Smrj     ArgList.Count = 1;
2843446Smrj     ArgList.Pointer = &Arg;
2853446Smrj     Arg.Type = ACPI_TYPE_INTEGER;
2863446Smrj     Arg.Integer.Value = SleepState;
2873446Smrj 
2883446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL);
2893446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
2903446Smrj     {
2913446Smrj         return_ACPI_STATUS (Status);
2923446Smrj     }
2933446Smrj 
294*7851SDana.Myers@Sun.COM     /* Setup the argument to the _SST method (System STatus) */
2953446Smrj 
2963446Smrj     switch (SleepState)
2973446Smrj     {
2983446Smrj     case ACPI_STATE_S0:
2993446Smrj         Arg.Integer.Value = ACPI_SST_WORKING;
3003446Smrj         break;
3013446Smrj 
3023446Smrj     case ACPI_STATE_S1:
3033446Smrj     case ACPI_STATE_S2:
3043446Smrj     case ACPI_STATE_S3:
3053446Smrj         Arg.Integer.Value = ACPI_SST_SLEEPING;
3063446Smrj         break;
3073446Smrj 
3083446Smrj     case ACPI_STATE_S4:
3093446Smrj         Arg.Integer.Value = ACPI_SST_SLEEP_CONTEXT;
3103446Smrj         break;
3113446Smrj 
3123446Smrj     default:
3133446Smrj         Arg.Integer.Value = ACPI_SST_INDICATOR_OFF; /* Default is off */
3143446Smrj         break;
3153446Smrj     }
3163446Smrj 
317*7851SDana.Myers@Sun.COM     /*
318*7851SDana.Myers@Sun.COM      * Set the system indicators to show the desired sleep state.
319*7851SDana.Myers@Sun.COM      * _SST is an optional method (return no error if not found)
320*7851SDana.Myers@Sun.COM      */
3213446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
3223446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
3233446Smrj     {
3243446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "While executing method _SST"));
3253446Smrj     }
3263446Smrj 
3273446Smrj     return_ACPI_STATUS (AE_OK);
3283446Smrj }
3293446Smrj 
3303446Smrj ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep)
3313446Smrj 
3323446Smrj 
3333446Smrj /*******************************************************************************
3343446Smrj  *
3353446Smrj  * FUNCTION:    AcpiEnterSleepState
3363446Smrj  *
3373446Smrj  * PARAMETERS:  SleepState          - Which sleep state to enter
3383446Smrj  *
3393446Smrj  * RETURN:      Status
3403446Smrj  *
341*7851SDana.Myers@Sun.COM  * DESCRIPTION: Enter a system sleep state
3423446Smrj  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
3433446Smrj  *
3443446Smrj  ******************************************************************************/
3453446Smrj 
3463446Smrj ACPI_STATUS
3473446Smrj AcpiEnterSleepState (
3483446Smrj     UINT8                   SleepState)
3493446Smrj {
3503446Smrj     UINT32                  PM1AControl;
3513446Smrj     UINT32                  PM1BControl;
3523446Smrj     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
3533446Smrj     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
3543446Smrj     UINT32                  InValue;
355*7851SDana.Myers@Sun.COM     ACPI_OBJECT_LIST        ArgList;
356*7851SDana.Myers@Sun.COM     ACPI_OBJECT             Arg;
3573446Smrj     ACPI_STATUS             Status;
3583446Smrj 
3593446Smrj 
3603446Smrj     ACPI_FUNCTION_TRACE (AcpiEnterSleepState);
3613446Smrj 
3623446Smrj 
3633446Smrj     if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) ||
3643446Smrj         (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX))
3653446Smrj     {
3663446Smrj         ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=%X B=%X",
3673446Smrj             AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB));
3683446Smrj         return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
3693446Smrj     }
3703446Smrj 
3713446Smrj     SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
3723446Smrj     SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
3733446Smrj 
3743446Smrj     /* Clear wake status */
3753446Smrj 
376*7851SDana.Myers@Sun.COM     Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1);
3773446Smrj     if (ACPI_FAILURE (Status))
3783446Smrj     {
3793446Smrj         return_ACPI_STATUS (Status);
3803446Smrj     }
3813446Smrj 
3823446Smrj     /* Clear all fixed and general purpose status bits */
3833446Smrj 
384*7851SDana.Myers@Sun.COM     Status = AcpiHwClearAcpiStatus ();
3853446Smrj     if (ACPI_FAILURE (Status))
3863446Smrj     {
3873446Smrj         return_ACPI_STATUS (Status);
3883446Smrj     }
3893446Smrj 
3903446Smrj     if (SleepState != ACPI_STATE_S5)
3913446Smrj     {
3923446Smrj         /* Disable BM arbitration */
3933446Smrj 
394*7851SDana.Myers@Sun.COM         Status = AcpiSetRegister (ACPI_BITREG_ARB_DISABLE, 1);
3953446Smrj         if (ACPI_FAILURE (Status))
3963446Smrj         {
3973446Smrj             return_ACPI_STATUS (Status);
3983446Smrj         }
3993446Smrj     }
4003446Smrj 
4013446Smrj     /*
4023446Smrj      * 1) Disable/Clear all GPEs
4033446Smrj      * 2) Enable all wakeup GPEs
4043446Smrj      */
4053446Smrj     Status = AcpiHwDisableAllGpes ();
4063446Smrj     if (ACPI_FAILURE (Status))
4073446Smrj     {
4083446Smrj         return_ACPI_STATUS (Status);
4093446Smrj     }
4103446Smrj     AcpiGbl_SystemAwakeAndRunning = FALSE;
4113446Smrj 
4123446Smrj     Status = AcpiHwEnableAllWakeupGpes ();
4133446Smrj     if (ACPI_FAILURE (Status))
4143446Smrj     {
4153446Smrj         return_ACPI_STATUS (Status);
4163446Smrj     }
4173446Smrj 
418*7851SDana.Myers@Sun.COM     /* Execute the _GTS method (Going To Sleep) */
419*7851SDana.Myers@Sun.COM 
420*7851SDana.Myers@Sun.COM     ArgList.Count = 1;
421*7851SDana.Myers@Sun.COM     ArgList.Pointer = &Arg;
422*7851SDana.Myers@Sun.COM     Arg.Type = ACPI_TYPE_INTEGER;
423*7851SDana.Myers@Sun.COM     Arg.Integer.Value = SleepState;
424*7851SDana.Myers@Sun.COM 
425*7851SDana.Myers@Sun.COM     Status = AcpiEvaluateObject (NULL, METHOD_NAME__GTS, &ArgList, NULL);
426*7851SDana.Myers@Sun.COM     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
427*7851SDana.Myers@Sun.COM     {
428*7851SDana.Myers@Sun.COM         return_ACPI_STATUS (Status);
429*7851SDana.Myers@Sun.COM     }
430*7851SDana.Myers@Sun.COM 
4313446Smrj     /* Get current value of PM1A control */
4323446Smrj 
433*7851SDana.Myers@Sun.COM     Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
434*7851SDana.Myers@Sun.COM                 &PM1AControl);
4353446Smrj     if (ACPI_FAILURE (Status))
4363446Smrj     {
4373446Smrj         return_ACPI_STATUS (Status);
4383446Smrj     }
4393446Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
4403446Smrj         "Entering sleep state [S%d]\n", SleepState));
4413446Smrj 
4423446Smrj     /* Clear SLP_EN and SLP_TYP fields */
4433446Smrj 
4443446Smrj     PM1AControl &= ~(SleepTypeRegInfo->AccessBitMask |
4453446Smrj                      SleepEnableRegInfo->AccessBitMask);
4463446Smrj     PM1BControl = PM1AControl;
4473446Smrj 
4483446Smrj     /* Insert SLP_TYP bits */
4493446Smrj 
4503446Smrj     PM1AControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
4513446Smrj     PM1BControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
4523446Smrj 
4533446Smrj     /*
4543446Smrj      * We split the writes of SLP_TYP and SLP_EN to workaround
4553446Smrj      * poorly implemented hardware.
4563446Smrj      */
4573446Smrj 
4583446Smrj     /* Write #1: fill in SLP_TYP data */
4593446Smrj 
460*7851SDana.Myers@Sun.COM     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1A_CONTROL,
461*7851SDana.Myers@Sun.COM                 PM1AControl);
4623446Smrj     if (ACPI_FAILURE (Status))
4633446Smrj     {
4643446Smrj         return_ACPI_STATUS (Status);
4653446Smrj     }
4663446Smrj 
467*7851SDana.Myers@Sun.COM     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1B_CONTROL,
468*7851SDana.Myers@Sun.COM                 PM1BControl);
4693446Smrj     if (ACPI_FAILURE (Status))
4703446Smrj     {
4713446Smrj         return_ACPI_STATUS (Status);
4723446Smrj     }
4733446Smrj 
4743446Smrj     /* Insert SLP_ENABLE bit */
4753446Smrj 
4763446Smrj     PM1AControl |= SleepEnableRegInfo->AccessBitMask;
4773446Smrj     PM1BControl |= SleepEnableRegInfo->AccessBitMask;
4783446Smrj 
4793446Smrj     /* Write #2: SLP_TYP + SLP_EN */
4803446Smrj 
4813446Smrj     ACPI_FLUSH_CPU_CACHE ();
4823446Smrj 
483*7851SDana.Myers@Sun.COM     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1A_CONTROL,
484*7851SDana.Myers@Sun.COM                 PM1AControl);
4853446Smrj     if (ACPI_FAILURE (Status))
4863446Smrj     {
4873446Smrj         return_ACPI_STATUS (Status);
4883446Smrj     }
4893446Smrj 
490*7851SDana.Myers@Sun.COM     Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1B_CONTROL,
491*7851SDana.Myers@Sun.COM                 PM1BControl);
4923446Smrj     if (ACPI_FAILURE (Status))
4933446Smrj     {
4943446Smrj         return_ACPI_STATUS (Status);
4953446Smrj     }
4963446Smrj 
4973446Smrj     if (SleepState > ACPI_STATE_S3)
4983446Smrj     {
4993446Smrj         /*
5003446Smrj          * We wanted to sleep > S3, but it didn't happen (by virtue of the
5013446Smrj          * fact that we are still executing!)
5023446Smrj          *
5033446Smrj          * Wait ten seconds, then try again. This is to get S4/S5 to work on
5043446Smrj          * all machines.
5053446Smrj          *
5063446Smrj          * We wait so long to allow chipsets that poll this reg very slowly to
5073446Smrj          * still read the right value. Ideally, this block would go
5083446Smrj          * away entirely.
5093446Smrj          */
5103446Smrj         AcpiOsStall (10000000);
5113446Smrj 
512*7851SDana.Myers@Sun.COM         Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL,
5133446Smrj                     SleepEnableRegInfo->AccessBitMask);
5143446Smrj         if (ACPI_FAILURE (Status))
5153446Smrj         {
5163446Smrj             return_ACPI_STATUS (Status);
5173446Smrj         }
5183446Smrj     }
5193446Smrj 
5203446Smrj     /* Wait until we enter sleep state */
5213446Smrj 
5223446Smrj     do
5233446Smrj     {
524*7851SDana.Myers@Sun.COM         Status = AcpiGetRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
5253446Smrj         if (ACPI_FAILURE (Status))
5263446Smrj         {
5273446Smrj             return_ACPI_STATUS (Status);
5283446Smrj         }
5293446Smrj 
5303446Smrj         /* Spin until we wake */
5313446Smrj 
5323446Smrj     } while (!InValue);
5333446Smrj 
5343446Smrj     return_ACPI_STATUS (AE_OK);
5353446Smrj }
5363446Smrj 
5373446Smrj ACPI_EXPORT_SYMBOL (AcpiEnterSleepState)
5383446Smrj 
5393446Smrj 
5403446Smrj /*******************************************************************************
5413446Smrj  *
5423446Smrj  * FUNCTION:    AcpiEnterSleepStateS4bios
5433446Smrj  *
5443446Smrj  * PARAMETERS:  None
5453446Smrj  *
5463446Smrj  * RETURN:      Status
5473446Smrj  *
5483446Smrj  * DESCRIPTION: Perform a S4 bios request.
5493446Smrj  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
5503446Smrj  *
5513446Smrj  ******************************************************************************/
5523446Smrj 
5533446Smrj ACPI_STATUS
5543446Smrj AcpiEnterSleepStateS4bios (
5553446Smrj     void)
5563446Smrj {
5573446Smrj     UINT32                  InValue;
5583446Smrj     ACPI_STATUS             Status;
5593446Smrj 
5603446Smrj 
5613446Smrj     ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios);
5623446Smrj 
5633446Smrj 
564*7851SDana.Myers@Sun.COM     Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1);
5653446Smrj     if (ACPI_FAILURE (Status))
5663446Smrj     {
5673446Smrj         return_ACPI_STATUS (Status);
5683446Smrj     }
5693446Smrj 
570*7851SDana.Myers@Sun.COM     Status = AcpiHwClearAcpiStatus ();
5713446Smrj     if (ACPI_FAILURE (Status))
5723446Smrj     {
5733446Smrj         return_ACPI_STATUS (Status);
5743446Smrj     }
5753446Smrj 
5763446Smrj     /*
5773446Smrj      * 1) Disable/Clear all GPEs
5783446Smrj      * 2) Enable all wakeup GPEs
5793446Smrj      */
5803446Smrj     Status = AcpiHwDisableAllGpes ();
5813446Smrj     if (ACPI_FAILURE (Status))
5823446Smrj     {
5833446Smrj         return_ACPI_STATUS (Status);
5843446Smrj     }
5853446Smrj     AcpiGbl_SystemAwakeAndRunning = FALSE;
5863446Smrj 
5873446Smrj     Status = AcpiHwEnableAllWakeupGpes ();
5883446Smrj     if (ACPI_FAILURE (Status))
5893446Smrj     {
5903446Smrj         return_ACPI_STATUS (Status);
5913446Smrj     }
5923446Smrj 
5933446Smrj     ACPI_FLUSH_CPU_CACHE ();
5943446Smrj 
595*7851SDana.Myers@Sun.COM     Status = AcpiOsWritePort (AcpiGbl_FADT.SmiCommand,
596*7851SDana.Myers@Sun.COM                 (UINT32) AcpiGbl_FADT.S4BiosRequest, 8);
5973446Smrj 
5983446Smrj     do {
5993446Smrj         AcpiOsStall(1000);
600*7851SDana.Myers@Sun.COM         Status = AcpiGetRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
6013446Smrj         if (ACPI_FAILURE (Status))
6023446Smrj         {
6033446Smrj             return_ACPI_STATUS (Status);
6043446Smrj         }
6053446Smrj     } while (!InValue);
6063446Smrj 
6073446Smrj     return_ACPI_STATUS (AE_OK);
6083446Smrj }
6093446Smrj 
6103446Smrj ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios)
6113446Smrj 
6123446Smrj 
6133446Smrj /*******************************************************************************
6143446Smrj  *
6153446Smrj  * FUNCTION:    AcpiLeaveSleepState
6163446Smrj  *
6173446Smrj  * PARAMETERS:  SleepState          - Which sleep state we just exited
6183446Smrj  *
6193446Smrj  * RETURN:      Status
6203446Smrj  *
6213446Smrj  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
6223446Smrj  *              Called with interrupts ENABLED.
6233446Smrj  *
6243446Smrj  ******************************************************************************/
6253446Smrj 
6263446Smrj ACPI_STATUS
6273446Smrj AcpiLeaveSleepState (
6283446Smrj     UINT8                   SleepState)
6293446Smrj {
6303446Smrj     ACPI_OBJECT_LIST        ArgList;
6313446Smrj     ACPI_OBJECT             Arg;
6323446Smrj     ACPI_STATUS             Status;
6333446Smrj     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
6343446Smrj     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
6353446Smrj     UINT32                  PM1AControl;
6363446Smrj     UINT32                  PM1BControl;
6373446Smrj 
6383446Smrj 
6393446Smrj     ACPI_FUNCTION_TRACE (AcpiLeaveSleepState);
6403446Smrj 
6413446Smrj 
6423446Smrj     /*
6433446Smrj      * Set SLP_TYPE and SLP_EN to state S0.
6443446Smrj      * This is unclear from the ACPI Spec, but it is required
6453446Smrj      * by some machines.
6463446Smrj      */
6473446Smrj     Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
6483446Smrj                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
6493446Smrj     if (ACPI_SUCCESS (Status))
6503446Smrj     {
6513446Smrj         SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
6523446Smrj         SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
6533446Smrj 
6543446Smrj         /* Get current value of PM1A control */
6553446Smrj 
656*7851SDana.Myers@Sun.COM         Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
657*7851SDana.Myers@Sun.COM                     &PM1AControl);
6583446Smrj         if (ACPI_SUCCESS (Status))
6593446Smrj         {
6603446Smrj             /* Clear SLP_EN and SLP_TYP fields */
6613446Smrj 
6623446Smrj             PM1AControl &= ~(SleepTypeRegInfo->AccessBitMask |
6633446Smrj                              SleepEnableRegInfo->AccessBitMask);
6643446Smrj             PM1BControl = PM1AControl;
6653446Smrj 
6663446Smrj             /* Insert SLP_TYP bits */
6673446Smrj 
6683446Smrj             PM1AControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
6693446Smrj             PM1BControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
6703446Smrj 
6713446Smrj             /* Just ignore any errors */
6723446Smrj 
673*7851SDana.Myers@Sun.COM             (void) AcpiHwRegisterWrite (ACPI_REGISTER_PM1A_CONTROL,
674*7851SDana.Myers@Sun.COM                             PM1AControl);
675*7851SDana.Myers@Sun.COM             (void) AcpiHwRegisterWrite (ACPI_REGISTER_PM1B_CONTROL,
676*7851SDana.Myers@Sun.COM                             PM1BControl);
6773446Smrj         }
6783446Smrj     }
6793446Smrj 
6803446Smrj     /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
6813446Smrj 
6823446Smrj     AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
6833446Smrj 
6843446Smrj     /* Setup parameter object */
6853446Smrj 
6863446Smrj     ArgList.Count = 1;
6873446Smrj     ArgList.Pointer = &Arg;
6883446Smrj     Arg.Type = ACPI_TYPE_INTEGER;
6893446Smrj 
6903446Smrj     /* Ignore any errors from these methods */
6913446Smrj 
6923446Smrj     Arg.Integer.Value = ACPI_SST_WAKING;
6933446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
6943446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
6953446Smrj     {
6963446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
6973446Smrj     }
6983446Smrj 
6993446Smrj     Arg.Integer.Value = SleepState;
7003446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__BFS, &ArgList, NULL);
7013446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
7023446Smrj     {
7033446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _BFS"));
7043446Smrj     }
7053446Smrj 
7063446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__WAK, &ArgList, NULL);
7073446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
7083446Smrj     {
7093446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _WAK"));
7103446Smrj     }
7113446Smrj     /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
7123446Smrj 
7133446Smrj     /*
7143446Smrj      * Restore the GPEs:
7153446Smrj      * 1) Disable/Clear all GPEs
7163446Smrj      * 2) Enable all runtime GPEs
7173446Smrj      */
7183446Smrj     Status = AcpiHwDisableAllGpes ();
7193446Smrj     if (ACPI_FAILURE (Status))
7203446Smrj     {
7213446Smrj         return_ACPI_STATUS (Status);
7223446Smrj     }
7233446Smrj     AcpiGbl_SystemAwakeAndRunning = TRUE;
7243446Smrj 
7253446Smrj     Status = AcpiHwEnableAllRuntimeGpes ();
7263446Smrj     if (ACPI_FAILURE (Status))
7273446Smrj     {
7283446Smrj         return_ACPI_STATUS (Status);
7293446Smrj     }
7303446Smrj 
7313446Smrj     /* Enable power button */
7323446Smrj 
7333446Smrj     (void) AcpiSetRegister(
734*7851SDana.Myers@Sun.COM             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].EnableRegisterId, 1);
7353446Smrj 
7363446Smrj     (void) AcpiSetRegister(
737*7851SDana.Myers@Sun.COM             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId, 1);
7383446Smrj 
7393446Smrj     /* Enable BM arbitration */
7403446Smrj 
741*7851SDana.Myers@Sun.COM     Status = AcpiSetRegister (ACPI_BITREG_ARB_DISABLE, 0);
7423446Smrj     if (ACPI_FAILURE (Status))
7433446Smrj     {
7443446Smrj         return_ACPI_STATUS (Status);
7453446Smrj     }
7463446Smrj 
7473446Smrj     Arg.Integer.Value = ACPI_SST_WORKING;
7483446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
7493446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
7503446Smrj     {
7513446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
7523446Smrj     }
7533446Smrj 
7543446Smrj     return_ACPI_STATUS (Status);
7553446Smrj }
7563446Smrj 
7573446Smrj ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState)
7583446Smrj 
759