xref: /onnv-gate/usr/src/uts/intel/io/acpica/hardware/hwsleep.c (revision 10235:e7fdfb407eae)
13446Smrj 
23446Smrj /******************************************************************************
33446Smrj  *
43446Smrj  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
53446Smrj  *
63446Smrj  *****************************************************************************/
73446Smrj 
83446Smrj /******************************************************************************
93446Smrj  *
103446Smrj  * 1. Copyright Notice
113446Smrj  *
129980SDana.Myers@Sun.COM  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
133446Smrj  * All rights reserved.
143446Smrj  *
153446Smrj  * 2. License
163446Smrj  *
173446Smrj  * 2.1. This is your license from Intel Corp. under its intellectual property
183446Smrj  * rights.  You may have additional license terms from the party that provided
193446Smrj  * you this software, covering your right to use that party's intellectual
203446Smrj  * property rights.
213446Smrj  *
223446Smrj  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
233446Smrj  * copy of the source code appearing in this file ("Covered Code") an
243446Smrj  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
253446Smrj  * base code distributed originally by Intel ("Original Intel Code") to copy,
263446Smrj  * make derivatives, distribute, use and display any portion of the Covered
273446Smrj  * Code in any form, with the right to sublicense such rights; and
283446Smrj  *
293446Smrj  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
303446Smrj  * license (with the right to sublicense), under only those claims of Intel
313446Smrj  * patents that are infringed by the Original Intel Code, to make, use, sell,
323446Smrj  * offer to sell, and import the Covered Code and derivative works thereof
333446Smrj  * solely to the minimum extent necessary to exercise the above copyright
343446Smrj  * license, and in no event shall the patent license extend to any additions
353446Smrj  * to or modifications of the Original Intel Code.  No other license or right
363446Smrj  * is granted directly or by implication, estoppel or otherwise;
373446Smrj  *
383446Smrj  * The above copyright and patent license is granted only if the following
393446Smrj  * conditions are met:
403446Smrj  *
413446Smrj  * 3. Conditions
423446Smrj  *
433446Smrj  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
443446Smrj  * Redistribution of source code of any substantial portion of the Covered
453446Smrj  * Code or modification with rights to further distribute source must include
463446Smrj  * the above Copyright Notice, the above License, this list of Conditions,
473446Smrj  * and the following Disclaimer and Export Compliance provision.  In addition,
483446Smrj  * Licensee must cause all Covered Code to which Licensee contributes to
493446Smrj  * contain a file documenting the changes Licensee made to create that Covered
503446Smrj  * Code and the date of any change.  Licensee must include in that file the
513446Smrj  * documentation of any changes made by any predecessor Licensee.  Licensee
523446Smrj  * must include a prominent statement that the modification is derived,
533446Smrj  * directly or indirectly, from Original Intel Code.
543446Smrj  *
553446Smrj  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
563446Smrj  * Redistribution of source code of any substantial portion of the Covered
573446Smrj  * Code or modification without rights to further distribute source must
583446Smrj  * include the following Disclaimer and Export Compliance provision in the
593446Smrj  * documentation and/or other materials provided with distribution.  In
603446Smrj  * addition, Licensee may not authorize further sublicense of source of any
613446Smrj  * portion of the Covered Code, and must include terms to the effect that the
623446Smrj  * license from Licensee to its licensee is limited to the intellectual
633446Smrj  * property embodied in the software Licensee provides to its licensee, and
643446Smrj  * not to intellectual property embodied in modifications its licensee may
653446Smrj  * make.
663446Smrj  *
673446Smrj  * 3.3. Redistribution of Executable. Redistribution in executable form of any
683446Smrj  * substantial portion of the Covered Code or modification must reproduce the
693446Smrj  * above Copyright Notice, and the following Disclaimer and Export Compliance
703446Smrj  * provision in the documentation and/or other materials provided with the
713446Smrj  * distribution.
723446Smrj  *
733446Smrj  * 3.4. Intel retains all right, title, and interest in and to the Original
743446Smrj  * Intel Code.
753446Smrj  *
763446Smrj  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
773446Smrj  * Intel shall be used in advertising or otherwise to promote the sale, use or
783446Smrj  * other dealings in products derived from or relating to the Covered Code
793446Smrj  * without prior written authorization from Intel.
803446Smrj  *
813446Smrj  * 4. Disclaimer and Export Compliance
823446Smrj  *
833446Smrj  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
843446Smrj  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
853446Smrj  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
863446Smrj  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
873446Smrj  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
883446Smrj  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
893446Smrj  * PARTICULAR PURPOSE.
903446Smrj  *
913446Smrj  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
923446Smrj  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
933446Smrj  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
943446Smrj  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
953446Smrj  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
963446Smrj  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
973446Smrj  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
983446Smrj  * LIMITED REMEDY.
993446Smrj  *
1003446Smrj  * 4.3. Licensee shall not export, either directly or indirectly, any of this
1013446Smrj  * software or system incorporating such software without first obtaining any
1023446Smrj  * required license or other approval from the U. S. Department of Commerce or
1033446Smrj  * any other agency or department of the United States Government.  In the
1043446Smrj  * event Licensee exports any such software from the United States or
1053446Smrj  * re-exports any such software from a foreign destination, Licensee shall
1063446Smrj  * ensure that the distribution and export/re-export of the software is in
1073446Smrj  * compliance with all laws, regulations, orders, or other restrictions of the
1083446Smrj  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1093446Smrj  * any of its subsidiaries will export/re-export any technical data, process,
1103446Smrj  * software, or service, directly or indirectly, to any country for which the
1113446Smrj  * United States government or any agency thereof requires an export license,
1123446Smrj  * other governmental approval, or letter of assurance, without first obtaining
1133446Smrj  * such license, approval or letter.
1143446Smrj  *
1153446Smrj  *****************************************************************************/
1163446Smrj 
1173446Smrj #include "acpi.h"
1189980SDana.Myers@Sun.COM #include "accommon.h"
1193446Smrj 
1203446Smrj #define _COMPONENT          ACPI_HARDWARE
1213446Smrj         ACPI_MODULE_NAME    ("hwsleep")
1223446Smrj 
1233446Smrj 
1243446Smrj /*******************************************************************************
1253446Smrj  *
1263446Smrj  * FUNCTION:    AcpiSetFirmwareWakingVector
1273446Smrj  *
1289980SDana.Myers@Sun.COM  * PARAMETERS:  PhysicalAddress     - 32-bit physical address of ACPI real mode
1293446Smrj  *                                    entry point.
1303446Smrj  *
1313446Smrj  * RETURN:      Status
1323446Smrj  *
1339980SDana.Myers@Sun.COM  * DESCRIPTION: Sets the 32-bit FirmwareWakingVector field of the FACS
1343446Smrj  *
1353446Smrj  ******************************************************************************/
1363446Smrj 
1373446Smrj ACPI_STATUS
AcpiSetFirmwareWakingVector(UINT32 PhysicalAddress)1383446Smrj AcpiSetFirmwareWakingVector (
1399980SDana.Myers@Sun.COM     UINT32                  PhysicalAddress)
1403446Smrj {
1413446Smrj     ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector);
1423446Smrj 
1437851SDana.Myers@Sun.COM 
1449980SDana.Myers@Sun.COM     /* Set the 32-bit vector */
1453446Smrj 
1469980SDana.Myers@Sun.COM     AcpiGbl_FACS->FirmwareWakingVector = PhysicalAddress;
1473446Smrj 
1489980SDana.Myers@Sun.COM     /* Clear the 64-bit vector if it exists */
1499980SDana.Myers@Sun.COM 
1509980SDana.Myers@Sun.COM     if ((AcpiGbl_FACS->Length > 32) && (AcpiGbl_FACS->Version >= 1))
1513446Smrj     {
1529980SDana.Myers@Sun.COM         AcpiGbl_FACS->XFirmwareWakingVector = 0;
1533446Smrj     }
1543446Smrj 
1553446Smrj     return_ACPI_STATUS (AE_OK);
1563446Smrj }
1573446Smrj 
ACPI_EXPORT_SYMBOL(AcpiSetFirmwareWakingVector)1583446Smrj ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector)
1593446Smrj 
1603446Smrj 
1619980SDana.Myers@Sun.COM #if ACPI_MACHINE_WIDTH == 64
1623446Smrj /*******************************************************************************
1633446Smrj  *
1649980SDana.Myers@Sun.COM  * FUNCTION:    AcpiSetFirmwareWakingVector64
1659980SDana.Myers@Sun.COM  *
1669980SDana.Myers@Sun.COM  * PARAMETERS:  PhysicalAddress     - 64-bit physical address of ACPI protected
1679980SDana.Myers@Sun.COM  *                                    mode entry point.
1683446Smrj  *
1699980SDana.Myers@Sun.COM  * RETURN:      Status
1703446Smrj  *
1719980SDana.Myers@Sun.COM  * DESCRIPTION: Sets the 64-bit X_FirmwareWakingVector field of the FACS, if
1729980SDana.Myers@Sun.COM  *              it exists in the table. This function is intended for use with
1739980SDana.Myers@Sun.COM  *              64-bit host operating systems.
1743446Smrj  *
1753446Smrj  ******************************************************************************/
1763446Smrj 
1773446Smrj ACPI_STATUS
1789980SDana.Myers@Sun.COM AcpiSetFirmwareWakingVector64 (
1799980SDana.Myers@Sun.COM     UINT64                  PhysicalAddress)
1803446Smrj {
1819980SDana.Myers@Sun.COM     ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64);
1827851SDana.Myers@Sun.COM 
1833446Smrj 
1849980SDana.Myers@Sun.COM     /* Determine if the 64-bit vector actually exists */
1853446Smrj 
1869980SDana.Myers@Sun.COM     if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1))
1873446Smrj     {
1889980SDana.Myers@Sun.COM         return_ACPI_STATUS (AE_NOT_EXIST);
1893446Smrj     }
1903446Smrj 
1919980SDana.Myers@Sun.COM     /* Clear 32-bit vector, set the 64-bit X_ vector */
1923446Smrj 
1939980SDana.Myers@Sun.COM     AcpiGbl_FACS->FirmwareWakingVector = 0;
1949980SDana.Myers@Sun.COM     AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress;
1953446Smrj     return_ACPI_STATUS (AE_OK);
1963446Smrj }
1973446Smrj 
ACPI_EXPORT_SYMBOL(AcpiSetFirmwareWakingVector64)1989980SDana.Myers@Sun.COM ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector64)
1999980SDana.Myers@Sun.COM #endif
2003446Smrj 
2013446Smrj /*******************************************************************************
2023446Smrj  *
2033446Smrj  * FUNCTION:    AcpiEnterSleepStatePrep
2043446Smrj  *
2053446Smrj  * PARAMETERS:  SleepState          - Which sleep state to enter
2063446Smrj  *
2073446Smrj  * RETURN:      Status
2083446Smrj  *
2093446Smrj  * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
2103446Smrj  *              This function must execute with interrupts enabled.
2113446Smrj  *              We break sleeping into 2 stages so that OSPM can handle
2123446Smrj  *              various OS-specific tasks between the two steps.
2133446Smrj  *
2143446Smrj  ******************************************************************************/
2153446Smrj 
2163446Smrj ACPI_STATUS
2173446Smrj AcpiEnterSleepStatePrep (
2187851SDana.Myers@Sun.COM     UINT8                   SleepState)
2193446Smrj {
2207851SDana.Myers@Sun.COM     ACPI_STATUS             Status;
2217851SDana.Myers@Sun.COM     ACPI_OBJECT_LIST        ArgList;
2227851SDana.Myers@Sun.COM     ACPI_OBJECT             Arg;
2233446Smrj 
2243446Smrj 
2253446Smrj     ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep);
2263446Smrj 
2273446Smrj 
2289980SDana.Myers@Sun.COM     /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */
2299980SDana.Myers@Sun.COM 
2303446Smrj     Status = AcpiGetSleepTypeData (SleepState,
2313446Smrj                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
2323446Smrj     if (ACPI_FAILURE (Status))
2333446Smrj     {
2343446Smrj         return_ACPI_STATUS (Status);
2353446Smrj     }
2363446Smrj 
2377851SDana.Myers@Sun.COM     /* Execute the _PTS method (Prepare To Sleep) */
2383446Smrj 
2393446Smrj     ArgList.Count = 1;
2403446Smrj     ArgList.Pointer = &Arg;
2413446Smrj     Arg.Type = ACPI_TYPE_INTEGER;
2423446Smrj     Arg.Integer.Value = SleepState;
2433446Smrj 
2443446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL);
2453446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
2463446Smrj     {
2473446Smrj         return_ACPI_STATUS (Status);
2483446Smrj     }
2493446Smrj 
2507851SDana.Myers@Sun.COM     /* Setup the argument to the _SST method (System STatus) */
2513446Smrj 
2523446Smrj     switch (SleepState)
2533446Smrj     {
2543446Smrj     case ACPI_STATE_S0:
2553446Smrj         Arg.Integer.Value = ACPI_SST_WORKING;
2563446Smrj         break;
2573446Smrj 
2583446Smrj     case ACPI_STATE_S1:
2593446Smrj     case ACPI_STATE_S2:
2603446Smrj     case ACPI_STATE_S3:
2613446Smrj         Arg.Integer.Value = ACPI_SST_SLEEPING;
2623446Smrj         break;
2633446Smrj 
2643446Smrj     case ACPI_STATE_S4:
2653446Smrj         Arg.Integer.Value = ACPI_SST_SLEEP_CONTEXT;
2663446Smrj         break;
2673446Smrj 
2683446Smrj     default:
2693446Smrj         Arg.Integer.Value = ACPI_SST_INDICATOR_OFF; /* Default is off */
2703446Smrj         break;
2713446Smrj     }
2723446Smrj 
2737851SDana.Myers@Sun.COM     /*
2747851SDana.Myers@Sun.COM      * Set the system indicators to show the desired sleep state.
2757851SDana.Myers@Sun.COM      * _SST is an optional method (return no error if not found)
2767851SDana.Myers@Sun.COM      */
2773446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
2783446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
2793446Smrj     {
2803446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "While executing method _SST"));
2813446Smrj     }
2823446Smrj 
2833446Smrj     return_ACPI_STATUS (AE_OK);
2843446Smrj }
2853446Smrj 
ACPI_EXPORT_SYMBOL(AcpiEnterSleepStatePrep)2863446Smrj ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep)
2873446Smrj 
2883446Smrj 
2893446Smrj /*******************************************************************************
2903446Smrj  *
2913446Smrj  * FUNCTION:    AcpiEnterSleepState
2923446Smrj  *
2933446Smrj  * PARAMETERS:  SleepState          - Which sleep state to enter
2943446Smrj  *
2953446Smrj  * RETURN:      Status
2963446Smrj  *
2977851SDana.Myers@Sun.COM  * DESCRIPTION: Enter a system sleep state
2983446Smrj  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
2993446Smrj  *
3003446Smrj  ******************************************************************************/
3013446Smrj 
3023446Smrj ACPI_STATUS
3033446Smrj AcpiEnterSleepState (
3043446Smrj     UINT8                   SleepState)
3053446Smrj {
3069980SDana.Myers@Sun.COM     UINT32                  Pm1aControl;
3079980SDana.Myers@Sun.COM     UINT32                  Pm1bControl;
3083446Smrj     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
3093446Smrj     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
3103446Smrj     UINT32                  InValue;
3117851SDana.Myers@Sun.COM     ACPI_OBJECT_LIST        ArgList;
3127851SDana.Myers@Sun.COM     ACPI_OBJECT             Arg;
3133446Smrj     ACPI_STATUS             Status;
3143446Smrj 
3153446Smrj 
3163446Smrj     ACPI_FUNCTION_TRACE (AcpiEnterSleepState);
3173446Smrj 
3183446Smrj 
3193446Smrj     if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) ||
3203446Smrj         (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX))
3213446Smrj     {
3223446Smrj         ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=%X B=%X",
3233446Smrj             AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB));
3243446Smrj         return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
3253446Smrj     }
3263446Smrj 
3279980SDana.Myers@Sun.COM     SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE);
3283446Smrj     SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
3293446Smrj 
3303446Smrj     /* Clear wake status */
3313446Smrj 
3329980SDana.Myers@Sun.COM     Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
3333446Smrj     if (ACPI_FAILURE (Status))
3343446Smrj     {
3353446Smrj         return_ACPI_STATUS (Status);
3363446Smrj     }
3373446Smrj 
3383446Smrj     /* Clear all fixed and general purpose status bits */
3393446Smrj 
3407851SDana.Myers@Sun.COM     Status = AcpiHwClearAcpiStatus ();
3413446Smrj     if (ACPI_FAILURE (Status))
3423446Smrj     {
3433446Smrj         return_ACPI_STATUS (Status);
3443446Smrj     }
3453446Smrj 
3463446Smrj     if (SleepState != ACPI_STATE_S5)
3473446Smrj     {
348*10235SDana.Myers@Sun.COM 	/*
349*10235SDana.Myers@Sun.COM 	 * Disable BM arbitration. This feature is contained within an
350*10235SDana.Myers@Sun.COM 	 * optional register (PM2 Control), so ignore a BAD_ADDRESS
351*10235SDana.Myers@Sun.COM 	 * exception.
352*10235SDana.Myers@Sun.COM 	 */
3539980SDana.Myers@Sun.COM         Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 1);
354*10235SDana.Myers@Sun.COM 	if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS))
3553446Smrj         {
3563446Smrj             return_ACPI_STATUS (Status);
3573446Smrj         }
3583446Smrj     }
3593446Smrj 
3603446Smrj     /*
3613446Smrj      * 1) Disable/Clear all GPEs
3623446Smrj      * 2) Enable all wakeup GPEs
3633446Smrj      */
3643446Smrj     Status = AcpiHwDisableAllGpes ();
3653446Smrj     if (ACPI_FAILURE (Status))
3663446Smrj     {
3673446Smrj         return_ACPI_STATUS (Status);
3683446Smrj     }
3693446Smrj     AcpiGbl_SystemAwakeAndRunning = FALSE;
3703446Smrj 
3713446Smrj     Status = AcpiHwEnableAllWakeupGpes ();
3723446Smrj     if (ACPI_FAILURE (Status))
3733446Smrj     {
3743446Smrj         return_ACPI_STATUS (Status);
3753446Smrj     }
3763446Smrj 
3777851SDana.Myers@Sun.COM     /* Execute the _GTS method (Going To Sleep) */
3787851SDana.Myers@Sun.COM 
3797851SDana.Myers@Sun.COM     ArgList.Count = 1;
3807851SDana.Myers@Sun.COM     ArgList.Pointer = &Arg;
3817851SDana.Myers@Sun.COM     Arg.Type = ACPI_TYPE_INTEGER;
3827851SDana.Myers@Sun.COM     Arg.Integer.Value = SleepState;
3837851SDana.Myers@Sun.COM 
3847851SDana.Myers@Sun.COM     Status = AcpiEvaluateObject (NULL, METHOD_NAME__GTS, &ArgList, NULL);
3857851SDana.Myers@Sun.COM     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
3867851SDana.Myers@Sun.COM     {
3877851SDana.Myers@Sun.COM         return_ACPI_STATUS (Status);
3887851SDana.Myers@Sun.COM     }
3897851SDana.Myers@Sun.COM 
3903446Smrj     /* Get current value of PM1A control */
3913446Smrj 
3929980SDana.Myers@Sun.COM     Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
3939980SDana.Myers@Sun.COM                 &Pm1aControl);
3943446Smrj     if (ACPI_FAILURE (Status))
3953446Smrj     {
3963446Smrj         return_ACPI_STATUS (Status);
3973446Smrj     }
3983446Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
3993446Smrj         "Entering sleep state [S%d]\n", SleepState));
4003446Smrj 
4019980SDana.Myers@Sun.COM     /* Clear the SLP_EN and SLP_TYP fields */
4023446Smrj 
4039980SDana.Myers@Sun.COM     Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask |
4043446Smrj                      SleepEnableRegInfo->AccessBitMask);
4059980SDana.Myers@Sun.COM     Pm1bControl = Pm1aControl;
4063446Smrj 
4079980SDana.Myers@Sun.COM     /* Insert the SLP_TYP bits */
4083446Smrj 
4099980SDana.Myers@Sun.COM     Pm1aControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
4109980SDana.Myers@Sun.COM     Pm1bControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
4113446Smrj 
4123446Smrj     /*
4133446Smrj      * We split the writes of SLP_TYP and SLP_EN to workaround
4143446Smrj      * poorly implemented hardware.
4153446Smrj      */
4163446Smrj 
4179980SDana.Myers@Sun.COM     /* Write #1: write the SLP_TYP data to the PM1 Control registers */
4183446Smrj 
4199980SDana.Myers@Sun.COM     Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
4203446Smrj     if (ACPI_FAILURE (Status))
4213446Smrj     {
4223446Smrj         return_ACPI_STATUS (Status);
4233446Smrj     }
4243446Smrj 
4259980SDana.Myers@Sun.COM     /* Insert the sleep enable (SLP_EN) bit */
4263446Smrj 
4279980SDana.Myers@Sun.COM     Pm1aControl |= SleepEnableRegInfo->AccessBitMask;
4289980SDana.Myers@Sun.COM     Pm1bControl |= SleepEnableRegInfo->AccessBitMask;
4293446Smrj 
4309980SDana.Myers@Sun.COM     /* Flush caches, as per ACPI specification */
4313446Smrj 
4323446Smrj     ACPI_FLUSH_CPU_CACHE ();
4333446Smrj 
4349980SDana.Myers@Sun.COM     /* Write #2: Write both SLP_TYP + SLP_EN */
4353446Smrj 
4369980SDana.Myers@Sun.COM     Status = AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
4373446Smrj     if (ACPI_FAILURE (Status))
4383446Smrj     {
4393446Smrj         return_ACPI_STATUS (Status);
4403446Smrj     }
4413446Smrj 
4423446Smrj     if (SleepState > ACPI_STATE_S3)
4433446Smrj     {
4443446Smrj         /*
4453446Smrj          * We wanted to sleep > S3, but it didn't happen (by virtue of the
4463446Smrj          * fact that we are still executing!)
4473446Smrj          *
4483446Smrj          * Wait ten seconds, then try again. This is to get S4/S5 to work on
4493446Smrj          * all machines.
4503446Smrj          *
4519980SDana.Myers@Sun.COM          * We wait so long to allow chipsets that poll this reg very slowly
4529980SDana.Myers@Sun.COM          * to still read the right value. Ideally, this block would go
4533446Smrj          * away entirely.
4543446Smrj          */
4553446Smrj         AcpiOsStall (10000000);
4563446Smrj 
4577851SDana.Myers@Sun.COM         Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL,
4583446Smrj                     SleepEnableRegInfo->AccessBitMask);
4593446Smrj         if (ACPI_FAILURE (Status))
4603446Smrj         {
4613446Smrj             return_ACPI_STATUS (Status);
4623446Smrj         }
4633446Smrj     }
4643446Smrj 
4653446Smrj     /* Wait until we enter sleep state */
4663446Smrj 
4673446Smrj     do
4683446Smrj     {
4699980SDana.Myers@Sun.COM         Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
4703446Smrj         if (ACPI_FAILURE (Status))
4713446Smrj         {
4723446Smrj             return_ACPI_STATUS (Status);
4733446Smrj         }
4743446Smrj 
4753446Smrj         /* Spin until we wake */
4763446Smrj 
4773446Smrj     } while (!InValue);
4783446Smrj 
4793446Smrj     return_ACPI_STATUS (AE_OK);
4803446Smrj }
4813446Smrj 
ACPI_EXPORT_SYMBOL(AcpiEnterSleepState)4823446Smrj ACPI_EXPORT_SYMBOL (AcpiEnterSleepState)
4833446Smrj 
4843446Smrj 
4853446Smrj /*******************************************************************************
4863446Smrj  *
4873446Smrj  * FUNCTION:    AcpiEnterSleepStateS4bios
4883446Smrj  *
4893446Smrj  * PARAMETERS:  None
4903446Smrj  *
4913446Smrj  * RETURN:      Status
4923446Smrj  *
4933446Smrj  * DESCRIPTION: Perform a S4 bios request.
4943446Smrj  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
4953446Smrj  *
4963446Smrj  ******************************************************************************/
4973446Smrj 
4983446Smrj ACPI_STATUS
4993446Smrj AcpiEnterSleepStateS4bios (
5003446Smrj     void)
5013446Smrj {
5023446Smrj     UINT32                  InValue;
5033446Smrj     ACPI_STATUS             Status;
5043446Smrj 
5053446Smrj 
5063446Smrj     ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios);
5073446Smrj 
5083446Smrj 
5099980SDana.Myers@Sun.COM     /* Clear the wake status bit (PM1) */
5109980SDana.Myers@Sun.COM 
5119980SDana.Myers@Sun.COM     Status = AcpiWriteBitRegister (ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
5123446Smrj     if (ACPI_FAILURE (Status))
5133446Smrj     {
5143446Smrj         return_ACPI_STATUS (Status);
5153446Smrj     }
5163446Smrj 
5177851SDana.Myers@Sun.COM     Status = AcpiHwClearAcpiStatus ();
5183446Smrj     if (ACPI_FAILURE (Status))
5193446Smrj     {
5203446Smrj         return_ACPI_STATUS (Status);
5213446Smrj     }
5223446Smrj 
5233446Smrj     /*
5243446Smrj      * 1) Disable/Clear all GPEs
5253446Smrj      * 2) Enable all wakeup GPEs
5263446Smrj      */
5273446Smrj     Status = AcpiHwDisableAllGpes ();
5283446Smrj     if (ACPI_FAILURE (Status))
5293446Smrj     {
5303446Smrj         return_ACPI_STATUS (Status);
5313446Smrj     }
5323446Smrj     AcpiGbl_SystemAwakeAndRunning = FALSE;
5333446Smrj 
5343446Smrj     Status = AcpiHwEnableAllWakeupGpes ();
5353446Smrj     if (ACPI_FAILURE (Status))
5363446Smrj     {
5373446Smrj         return_ACPI_STATUS (Status);
5383446Smrj     }
5393446Smrj 
5403446Smrj     ACPI_FLUSH_CPU_CACHE ();
5413446Smrj 
5429980SDana.Myers@Sun.COM     Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand,
5437851SDana.Myers@Sun.COM                 (UINT32) AcpiGbl_FADT.S4BiosRequest, 8);
5443446Smrj 
5453446Smrj     do {
5463446Smrj         AcpiOsStall(1000);
5479980SDana.Myers@Sun.COM         Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
5483446Smrj         if (ACPI_FAILURE (Status))
5493446Smrj         {
5503446Smrj             return_ACPI_STATUS (Status);
5513446Smrj         }
5523446Smrj     } while (!InValue);
5533446Smrj 
5543446Smrj     return_ACPI_STATUS (AE_OK);
5553446Smrj }
5563446Smrj 
ACPI_EXPORT_SYMBOL(AcpiEnterSleepStateS4bios)5573446Smrj ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios)
5583446Smrj 
5593446Smrj 
5603446Smrj /*******************************************************************************
5613446Smrj  *
5623446Smrj  * FUNCTION:    AcpiLeaveSleepState
5633446Smrj  *
5643446Smrj  * PARAMETERS:  SleepState          - Which sleep state we just exited
5653446Smrj  *
5663446Smrj  * RETURN:      Status
5673446Smrj  *
5683446Smrj  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
5693446Smrj  *              Called with interrupts ENABLED.
5703446Smrj  *
5713446Smrj  ******************************************************************************/
5723446Smrj 
5733446Smrj ACPI_STATUS
5743446Smrj AcpiLeaveSleepState (
5753446Smrj     UINT8                   SleepState)
5763446Smrj {
5773446Smrj     ACPI_OBJECT_LIST        ArgList;
5783446Smrj     ACPI_OBJECT             Arg;
5793446Smrj     ACPI_STATUS             Status;
5803446Smrj     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
5813446Smrj     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
5829980SDana.Myers@Sun.COM     UINT32                  Pm1aControl;
5839980SDana.Myers@Sun.COM     UINT32                  Pm1bControl;
5843446Smrj 
5853446Smrj 
5863446Smrj     ACPI_FUNCTION_TRACE (AcpiLeaveSleepState);
5873446Smrj 
5883446Smrj 
5893446Smrj     /*
5903446Smrj      * Set SLP_TYPE and SLP_EN to state S0.
5913446Smrj      * This is unclear from the ACPI Spec, but it is required
5923446Smrj      * by some machines.
5933446Smrj      */
5943446Smrj     Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
5953446Smrj                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
5963446Smrj     if (ACPI_SUCCESS (Status))
5973446Smrj     {
5989980SDana.Myers@Sun.COM         SleepTypeRegInfo =
5999980SDana.Myers@Sun.COM             AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE);
6009980SDana.Myers@Sun.COM         SleepEnableRegInfo =
6019980SDana.Myers@Sun.COM             AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
6023446Smrj 
6033446Smrj         /* Get current value of PM1A control */
6043446Smrj 
6059980SDana.Myers@Sun.COM         Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_CONTROL,
6069980SDana.Myers@Sun.COM                     &Pm1aControl);
6073446Smrj         if (ACPI_SUCCESS (Status))
6083446Smrj         {
6099980SDana.Myers@Sun.COM             /* Clear the SLP_EN and SLP_TYP fields */
6103446Smrj 
6119980SDana.Myers@Sun.COM             Pm1aControl &= ~(SleepTypeRegInfo->AccessBitMask |
6129980SDana.Myers@Sun.COM                 SleepEnableRegInfo->AccessBitMask);
6139980SDana.Myers@Sun.COM             Pm1bControl = Pm1aControl;
6143446Smrj 
6159980SDana.Myers@Sun.COM             /* Insert the SLP_TYP bits */
6163446Smrj 
6179980SDana.Myers@Sun.COM             Pm1aControl |= (AcpiGbl_SleepTypeA <<
6189980SDana.Myers@Sun.COM                 SleepTypeRegInfo->BitPosition);
6199980SDana.Myers@Sun.COM             Pm1bControl |= (AcpiGbl_SleepTypeB <<
6209980SDana.Myers@Sun.COM                 SleepTypeRegInfo->BitPosition);
6213446Smrj 
6229980SDana.Myers@Sun.COM             /* Write the control registers and ignore any errors */
6239980SDana.Myers@Sun.COM 
6249980SDana.Myers@Sun.COM             (void) AcpiHwWritePm1Control (Pm1aControl, Pm1bControl);
6253446Smrj         }
6263446Smrj     }
6273446Smrj 
6283446Smrj     /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
6293446Smrj 
6303446Smrj     AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
6313446Smrj 
6323446Smrj     /* Setup parameter object */
6333446Smrj 
6343446Smrj     ArgList.Count = 1;
6353446Smrj     ArgList.Pointer = &Arg;
6363446Smrj     Arg.Type = ACPI_TYPE_INTEGER;
6373446Smrj 
6383446Smrj     /* Ignore any errors from these methods */
6393446Smrj 
6403446Smrj     Arg.Integer.Value = ACPI_SST_WAKING;
6413446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
6423446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
6433446Smrj     {
6443446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
6453446Smrj     }
6463446Smrj 
6473446Smrj     Arg.Integer.Value = SleepState;
6483446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__BFS, &ArgList, NULL);
6493446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
6503446Smrj     {
6513446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _BFS"));
6523446Smrj     }
6533446Smrj 
6543446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__WAK, &ArgList, NULL);
6553446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
6563446Smrj     {
6573446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _WAK"));
6583446Smrj     }
6593446Smrj     /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
6603446Smrj 
6613446Smrj     /*
6623446Smrj      * Restore the GPEs:
6633446Smrj      * 1) Disable/Clear all GPEs
6643446Smrj      * 2) Enable all runtime GPEs
6653446Smrj      */
6663446Smrj     Status = AcpiHwDisableAllGpes ();
6673446Smrj     if (ACPI_FAILURE (Status))
6683446Smrj     {
6693446Smrj         return_ACPI_STATUS (Status);
6703446Smrj     }
6713446Smrj     AcpiGbl_SystemAwakeAndRunning = TRUE;
6723446Smrj 
6733446Smrj     Status = AcpiHwEnableAllRuntimeGpes ();
6743446Smrj     if (ACPI_FAILURE (Status))
6753446Smrj     {
6763446Smrj         return_ACPI_STATUS (Status);
6773446Smrj     }
6783446Smrj 
6793446Smrj     /* Enable power button */
6803446Smrj 
6819980SDana.Myers@Sun.COM     (void) AcpiWriteBitRegister(
6829980SDana.Myers@Sun.COM             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].EnableRegisterId,
6839980SDana.Myers@Sun.COM             ACPI_ENABLE_EVENT);
6843446Smrj 
6859980SDana.Myers@Sun.COM     (void) AcpiWriteBitRegister(
6869980SDana.Myers@Sun.COM             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId,
6879980SDana.Myers@Sun.COM             ACPI_CLEAR_STATUS);
6883446Smrj 
689*10235SDana.Myers@Sun.COM     /*
690*10235SDana.Myers@Sun.COM      * Enable BM arbitration. This feature is contained within an
691*10235SDana.Myers@Sun.COM      * optional register (PM2 Control), so ignore a BAD_ADDRESS
692*10235SDana.Myers@Sun.COM      * exception.
693*10235SDana.Myers@Sun.COM      */
6949980SDana.Myers@Sun.COM     Status = AcpiWriteBitRegister (ACPI_BITREG_ARB_DISABLE, 0);
695*10235SDana.Myers@Sun.COM     if (ACPI_FAILURE (Status) && (Status != AE_BAD_ADDRESS))
6963446Smrj     {
6973446Smrj         return_ACPI_STATUS (Status);
6983446Smrj     }
6993446Smrj 
7003446Smrj     Arg.Integer.Value = ACPI_SST_WORKING;
7013446Smrj     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
7023446Smrj     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
7033446Smrj     {
7043446Smrj         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
7053446Smrj     }
7063446Smrj 
7073446Smrj     return_ACPI_STATUS (Status);
7083446Smrj }
7093446Smrj 
7103446Smrj ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState)
7113446Smrj 
712