hwsleep.c revision 117521
171867Smsmith
271867Smsmith/******************************************************************************
371867Smsmith *
471867Smsmith * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
571867Smsmith *              $Revision: 56 $
671867Smsmith *
771867Smsmith *****************************************************************************/
8217365Sjkim
9229989Sjkim/******************************************************************************
1071867Smsmith *
1171867Smsmith * 1. Copyright Notice
12217365Sjkim *
13217365Sjkim * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
14217365Sjkim * All rights reserved.
15217365Sjkim *
16217365Sjkim * 2. License
17217365Sjkim *
18217365Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property
19217365Sjkim * rights.  You may have additional license terms from the party that provided
20217365Sjkim * you this software, covering your right to use that party's intellectual
21217365Sjkim * property rights.
22217365Sjkim *
23217365Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24217365Sjkim * copy of the source code appearing in this file ("Covered Code") an
25217365Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2671867Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy,
27217365Sjkim * make derivatives, distribute, use and display any portion of the Covered
28217365Sjkim * Code in any form, with the right to sublicense such rights; and
29217365Sjkim *
3071867Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31217365Sjkim * license (with the right to sublicense), under only those claims of Intel
32217365Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell,
33217365Sjkim * offer to sell, and import the Covered Code and derivative works thereof
34217365Sjkim * solely to the minimum extent necessary to exercise the above copyright
35217365Sjkim * license, and in no event shall the patent license extend to any additions
36217365Sjkim * to or modifications of the Original Intel Code.  No other license or right
37217365Sjkim * is granted directly or by implication, estoppel or otherwise;
38217365Sjkim *
39217365Sjkim * The above copyright and patent license is granted only if the following
40217365Sjkim * conditions are met:
41217365Sjkim *
42217365Sjkim * 3. Conditions
43217365Sjkim *
4471867Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45193341Sjkim * Redistribution of source code of any substantial portion of the Covered
46193341Sjkim * Code or modification with rights to further distribute source must include
4771867Smsmith * the above Copyright Notice, the above License, this list of Conditions,
4877424Smsmith * and the following Disclaimer and Export Compliance provision.  In addition,
4991116Smsmith * Licensee must cause all Covered Code to which Licensee contributes to
5071867Smsmith * contain a file documenting the changes Licensee made to create that Covered
5171867Smsmith * Code and the date of any change.  Licensee must include in that file the
52151937Sjkim * documentation of any changes made by any predecessor Licensee.  Licensee
5371867Smsmith * must include a prominent statement that the modification is derived,
5471867Smsmith * directly or indirectly, from Original Intel Code.
5571867Smsmith *
56193267Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5771867Smsmith * Redistribution of source code of any substantial portion of the Covered
5871867Smsmith * Code or modification without rights to further distribute source must
5991116Smsmith * include the following Disclaimer and Export Compliance provision in the
6071867Smsmith * documentation and/or other materials provided with distribution.  In
61193267Sjkim * addition, Licensee may not authorize further sublicense of source of any
6271867Smsmith * portion of the Covered Code, and must include terms to the effect that the
6371867Smsmith * license from Licensee to its licensee is limited to the intellectual
6471867Smsmith * property embodied in the software Licensee provides to its licensee, and
6571867Smsmith * not to intellectual property embodied in modifications its licensee may
6671867Smsmith * make.
67193267Sjkim *
6871867Smsmith * 3.3. Redistribution of Executable. Redistribution in executable form of any
69193267Sjkim * substantial portion of the Covered Code or modification must reproduce the
7071867Smsmith * above Copyright Notice, and the following Disclaimer and Export Compliance
7171867Smsmith * provision in the documentation and/or other materials provided with the
72193267Sjkim * distribution.
7371867Smsmith *
74193267Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original
75167802Sjkim * Intel Code.
76193267Sjkim *
77167802Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78193267Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or
7971867Smsmith * other dealings in products derived from or relating to the Covered Code
80193267Sjkim * without prior written authorization from Intel.
8171867Smsmith *
8271867Smsmith * 4. Disclaimer and Export Compliance
8371867Smsmith *
8471867Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8571867Smsmith * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86167802Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8771867Smsmith * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
88167802Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
89193267Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
90151937Sjkim * PARTICULAR PURPOSE.
9171867Smsmith *
92193267Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9371867Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
94193267Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
95193267Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9671867Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
97193267Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9871867Smsmith * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
99193267Sjkim * LIMITED REMEDY.
100193267Sjkim *
101193267Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this
10271867Smsmith * software or system incorporating such software without first obtaining any
10371867Smsmith * required license or other approval from the U. S. Department of Commerce or
10471867Smsmith * any other agency or department of the United States Government.  In the
10571867Smsmith * event Licensee exports any such software from the United States or
106193267Sjkim * re-exports any such software from a foreign destination, Licensee shall
107193267Sjkim * ensure that the distribution and export/re-export of the software is in
10871867Smsmith * compliance with all laws, regulations, orders, or other restrictions of the
109193267Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
11071867Smsmith * any of its subsidiaries will export/re-export any technical data, process,
11171867Smsmith * software, or service, directly or indirectly, to any country for which the
112193267Sjkim * United States government or any agency thereof requires an export license,
11371867Smsmith * other governmental approval, or letter of assurance, without first obtaining
114193267Sjkim * such license, approval or letter.
11571867Smsmith *
116193267Sjkim *****************************************************************************/
11771867Smsmith
11871867Smsmith#include "acpi.h"
119193267Sjkim
120167802Sjkim#define _COMPONENT          ACPI_HARDWARE
121193267Sjkim        ACPI_MODULE_NAME    ("hwsleep")
122193267Sjkim
12371867Smsmith
12471867Smsmith/******************************************************************************
12571867Smsmith *
126193267Sjkim * FUNCTION:    AcpiSetFirmwareWakingVector
127193267Sjkim *
12887031Smsmith * PARAMETERS:  PhysicalAddress     - Physical address of ACPI real mode
129151937Sjkim *                                    entry point.
13071867Smsmith *
13187031Smsmith * RETURN:      Status
13271867Smsmith *
13371867Smsmith * DESCRIPTION: Access function for dFirmwareWakingVector field in FACS
13471867Smsmith *
13571867Smsmith ******************************************************************************/
13671867Smsmith
13787031SmsmithACPI_STATUS
13887031SmsmithAcpiSetFirmwareWakingVector (
13987031Smsmith    ACPI_PHYSICAL_ADDRESS PhysicalAddress)
14087031Smsmith{
14171867Smsmith
14271867Smsmith    ACPI_FUNCTION_TRACE ("AcpiSetFirmwareWakingVector");
14371867Smsmith
14471867Smsmith
14587031Smsmith    /* Set the vector */
146193267Sjkim
14771867Smsmith    if (AcpiGbl_CommonFACS.VectorWidth == 32)
148193267Sjkim    {
149193267Sjkim        *(ACPI_CAST_PTR (UINT32, AcpiGbl_CommonFACS.FirmwareWakingVector))
150193267Sjkim                = (UINT32) PhysicalAddress;
15171867Smsmith    }
15277424Smsmith    else
153167802Sjkim    {
15491116Smsmith        *AcpiGbl_CommonFACS.FirmwareWakingVector
15591116Smsmith                = PhysicalAddress;
156193267Sjkim    }
157193267Sjkim
15899679Siwasaki    return_ACPI_STATUS (AE_OK);
15991116Smsmith}
16091116Smsmith
16171867Smsmith
16287031Smsmith/******************************************************************************
16371867Smsmith *
16471867Smsmith * FUNCTION:    AcpiGetFirmwareWakingVector
165193267Sjkim *
16677424Smsmith * PARAMETERS:  *PhysicalAddress    - Output buffer where contents of
16771867Smsmith *                                    the FirmwareWakingVector field of
16871867Smsmith *                                    the FACS will be stored.
16971867Smsmith *
17071867Smsmith * RETURN:      Status
17171867Smsmith *
172126372Snjl * DESCRIPTION: Access function for FirmwareWakingVector field in FACS
17391116Smsmith *
17491116Smsmith ******************************************************************************/
17591116Smsmith
17691116SmsmithACPI_STATUS
17791116SmsmithAcpiGetFirmwareWakingVector (
178193267Sjkim    ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
17991116Smsmith{
180126372Snjl
181126372Snjl    ACPI_FUNCTION_TRACE ("AcpiGetFirmwareWakingVector");
182126372Snjl
183126372Snjl
184126372Snjl    if (!PhysicalAddress)
185126372Snjl    {
186126372Snjl        return_ACPI_STATUS (AE_BAD_PARAMETER);
187126372Snjl    }
188126372Snjl
189126372Snjl    /* Get the vector */
190126372Snjl
191126372Snjl    if (AcpiGbl_CommonFACS.VectorWidth == 32)
192126372Snjl    {
193126372Snjl        *PhysicalAddress = (ACPI_PHYSICAL_ADDRESS)
194126372Snjl            *(ACPI_CAST_PTR (UINT32, AcpiGbl_CommonFACS.FirmwareWakingVector));
195126372Snjl    }
196126372Snjl    else
197151937Sjkim    {
198126372Snjl        *PhysicalAddress =
199126372Snjl            *AcpiGbl_CommonFACS.FirmwareWakingVector;
200126372Snjl    }
201193267Sjkim
202193267Sjkim    return_ACPI_STATUS (AE_OK);
203193267Sjkim}
204193267Sjkim
205126372Snjl
206123315Snjl/******************************************************************************
207123315Snjl *
208167802Sjkim * FUNCTION:    AcpiEnterSleepStatePrep
209123315Snjl *
210123315Snjl * PARAMETERS:  SleepState          - Which sleep state to enter
21187031Smsmith *
21287031Smsmith * RETURN:      Status
21387031Smsmith *
214167802Sjkim * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
21587031Smsmith *              This function must execute with interrupts enabled.
216167802Sjkim *              We break sleeping into 2 stages so that OSPM can handle
217151937Sjkim *              various OS-specific tasks between the two steps.
21887031Smsmith *
21987031Smsmith ******************************************************************************/
22087031Smsmith
22187031SmsmithACPI_STATUS
22287031SmsmithAcpiEnterSleepStatePrep (
22387031Smsmith    UINT8               SleepState)
22487031Smsmith{
225193267Sjkim    ACPI_STATUS         Status;
22687031Smsmith    ACPI_OBJECT_LIST    ArgList;
22787031Smsmith    ACPI_OBJECT         Arg;
22887031Smsmith
22987031Smsmith
23087031Smsmith    ACPI_FUNCTION_TRACE ("AcpiEnterSleepStatePrep");
23187031Smsmith
23291116Smsmith
23387031Smsmith    /*
234193267Sjkim     * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
235193267Sjkim     */
23691116Smsmith    Status = AcpiGetSleepTypeData (SleepState,
23791116Smsmith                    &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
23899679Siwasaki    if (ACPI_FAILURE (Status))
239193267Sjkim    {
240193267Sjkim        return_ACPI_STATUS (Status);
241193335Sjkim    }
24299679Siwasaki
24387031Smsmith    /* Setup parameter object */
24487031Smsmith
245167802Sjkim    ArgList.Count = 1;
24687031Smsmith    ArgList.Pointer = &Arg;
24791116Smsmith
24891116Smsmith    Arg.Type = ACPI_TYPE_INTEGER;
24991116Smsmith    Arg.Integer.Value = SleepState;
25087031Smsmith
251204773Sjkim    /* Run the _PTS and _GTS methods */
25291116Smsmith
25391116Smsmith    Status = AcpiEvaluateObject (NULL, "\\_PTS", &ArgList, NULL);
25487031Smsmith    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
25587031Smsmith    {
256193267Sjkim        return_ACPI_STATUS (Status);
25791116Smsmith    }
25871867Smsmith
259128245Snjl    Status = AcpiEvaluateObject (NULL, "\\_GTS", &ArgList, NULL);
260128245Snjl    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
261193267Sjkim    {
262128245Snjl        return_ACPI_STATUS (Status);
26399679Siwasaki    }
264128245Snjl
265128245Snjl    return_ACPI_STATUS (AE_OK);
26678986Smsmith}
267129684Snjl
268129684Snjl
269167802Sjkim/******************************************************************************
270128245Snjl *
271128245Snjl * FUNCTION:    AcpiEnterSleepState
272128245Snjl *
273128245Snjl * PARAMETERS:  SleepState          - Which sleep state to enter
27487031Smsmith *
275128245Snjl * RETURN:      Status
276128245Snjl *
277197104Sjkim * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
278197104Sjkim *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
279197104Sjkim *
280197104Sjkim ******************************************************************************/
281197104Sjkim
282193267SjkimACPI_STATUS
283197104SjkimAcpiEnterSleepState (
284123315Snjl    UINT8                   SleepState)
285123315Snjl{
286123315Snjl    UINT32                  PM1AControl;
28799679Siwasaki    UINT32                  PM1BControl;
28899679Siwasaki    ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
289128212Snjl    ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
290129684Snjl    UINT32                  InValue;
291128212Snjl    ACPI_STATUS             Status;
292128212Snjl
293151937Sjkim
29499679Siwasaki    ACPI_FUNCTION_TRACE ("AcpiEnterSleepState");
29599679Siwasaki
29699679Siwasaki
29799679Siwasaki    if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) ||
298129684Snjl        (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX))
29999679Siwasaki    {
300151937Sjkim        ACPI_REPORT_ERROR (("Sleep values out of range: A=%X B=%X\n",
301129684Snjl            AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB));
302129684Snjl        return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
303129684Snjl    }
304129684Snjl
305129684Snjl
306193267Sjkim    SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
307193267Sjkim    SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
308193267Sjkim
309193267Sjkim    /* Clear wake status */
310193267Sjkim
311193267Sjkim    Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
312193267Sjkim    if (ACPI_FAILURE (Status))
313193267Sjkim    {
314193267Sjkim        return_ACPI_STATUS (Status);
315193267Sjkim    }
316193267Sjkim
317193267Sjkim    Status = AcpiHwClearAcpiStatus(ACPI_MTX_DO_NOT_LOCK);
318193267Sjkim    if (ACPI_FAILURE (Status))
31991116Smsmith    {
32078986Smsmith        return_ACPI_STATUS (Status);
321193267Sjkim    }
322193267Sjkim
32399679Siwasaki    /* Disable BM arbitration */
32499679Siwasaki
32599679Siwasaki    Status = AcpiSetRegister (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
32699679Siwasaki    if (ACPI_FAILURE (Status))
327151937Sjkim    {
328209746Sjkim        return_ACPI_STATUS (Status);
32982367Smsmith    }
330193267Sjkim
33182367Smsmith    Status = AcpiHwDisableNonWakeupGpes();
332193267Sjkim    if (ACPI_FAILURE (Status))
333151937Sjkim    {
334193267Sjkim        return_ACPI_STATUS (Status);
33571867Smsmith    }
336193267Sjkim
33782367Smsmith    /* Get current value of PM1A control */
338193267Sjkim
339193267Sjkim    Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL, &PM1AControl);
34071867Smsmith    if (ACPI_FAILURE (Status))
341126372Snjl    {
342126372Snjl        return_ACPI_STATUS (Status);
343126372Snjl    }
344126372Snjl    ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Entering sleep state [S%d]\n", SleepState));
345126372Snjl
346193267Sjkim    /* Clear SLP_EN and SLP_TYP fields */
34771867Smsmith
348193267Sjkim    PM1AControl &= ~(SleepTypeRegInfo->AccessBitMask | SleepEnableRegInfo->AccessBitMask);
34999679Siwasaki    PM1BControl = PM1AControl;
35099679Siwasaki
35199679Siwasaki    /* Insert SLP_TYP bits */
35299679Siwasaki
35382367Smsmith    PM1AControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
354193267Sjkim    PM1BControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
35599679Siwasaki
356193267Sjkim    /* Write #1: fill in SLP_TYP data */
357193267Sjkim
35882367Smsmith    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1AControl);
359193267Sjkim    if (ACPI_FAILURE (Status))
36071867Smsmith    {
36199679Siwasaki        return_ACPI_STATUS (Status);
36280062Smsmith    }
363193267Sjkim
36499679Siwasaki    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1BControl);
365193267Sjkim    if (ACPI_FAILURE (Status))
36699679Siwasaki    {
36799679Siwasaki        return_ACPI_STATUS (Status);
36899679Siwasaki    }
36999679Siwasaki
37099679Siwasaki    /* Insert SLP_ENABLE bit */
37182367Smsmith
37282367Smsmith    PM1AControl |= SleepEnableRegInfo->AccessBitMask;
37399679Siwasaki    PM1BControl |= SleepEnableRegInfo->AccessBitMask;
374151937Sjkim
375151937Sjkim    /* Write #2: SLP_TYP + SLP_EN */
376123315Snjl
377151937Sjkim    ACPI_FLUSH_CPU_CACHE ();
378151937Sjkim
379123315Snjl    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1AControl);
380193267Sjkim    if (ACPI_FAILURE (Status))
381193267Sjkim    {
38299679Siwasaki        return_ACPI_STATUS (Status);
38399679Siwasaki    }
38499679Siwasaki
38582367Smsmith    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1BControl);
386193267Sjkim    if (ACPI_FAILURE (Status))
38799679Siwasaki    {
38899679Siwasaki        return_ACPI_STATUS (Status);
38999679Siwasaki    }
39099679Siwasaki
39199679Siwasaki    /*
39280357Speter     * Wait a second, then try again. This is to get S4/5 to work on all machines.
39380062Smsmith     */
39491116Smsmith    if (SleepState > ACPI_STATE_S3)
39571867Smsmith    {
396193335Sjkim        /*
397102550Siwasaki         * We wait so long to allow chipsets that poll this reg very slowly to
39883174Smsmith         * still read the right value. Ideally, this entire block would go
399193267Sjkim         * away entirely.
40099679Siwasaki         */
40199679Siwasaki        AcpiOsStall (10000000);
40299679Siwasaki
40399679Siwasaki        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL,
40499679Siwasaki                    SleepEnableRegInfo->AccessBitMask);
405204920Sjkim        if (ACPI_FAILURE (Status))
406193335Sjkim        {
407204920Sjkim            return_ACPI_STATUS (Status);
408204920Sjkim        }
409204920Sjkim    }
410204920Sjkim
411204920Sjkim    /* Wait until we enter sleep state */
412204920Sjkim
413204920Sjkim    do
414204920Sjkim    {
415193335Sjkim        Status = AcpiGetRegister (ACPI_BITREG_WAKE_STATUS, &InValue, ACPI_MTX_DO_NOT_LOCK);
416193335Sjkim        if (ACPI_FAILURE (Status))
41791116Smsmith        {
41882367Smsmith            return_ACPI_STATUS (Status);
41999679Siwasaki        }
42099679Siwasaki
42171867Smsmith        /* Spin until we wake */
42271867Smsmith
42382367Smsmith    } while (!InValue);
424167802Sjkim
425114237Snjl    return_ACPI_STATUS (AE_OK);
426167802Sjkim}
427151937Sjkim
42882367Smsmith
429114237Snjl/******************************************************************************
430114237Snjl *
431114237Snjl * FUNCTION:    AcpiEnterSleepStateS4bios
432114237Snjl *
433114237Snjl * PARAMETERS:  None
434114237Snjl *
435114237Snjl * RETURN:      Status
436114237Snjl *
437114237Snjl * DESCRIPTION: Perform a S4 bios request.
438114237Snjl *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
439114237Snjl *
440114237Snjl ******************************************************************************/
441114237Snjl
442114237SnjlACPI_STATUS
443114237SnjlAcpiEnterSleepStateS4bios (
444114237Snjl    void)
445114237Snjl{
446114237Snjl    UINT32                  InValue;
447114237Snjl    ACPI_STATUS             Status;
448167802Sjkim
449114237Snjl
450123315Snjl    ACPI_FUNCTION_TRACE ("AcpiEnterSleepStateS4bios");
451193267Sjkim
452193267Sjkim    AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
453193267Sjkim    AcpiHwClearAcpiStatus(ACPI_MTX_DO_NOT_LOCK);
454126372Snjl
455126372Snjl    AcpiHwDisableNonWakeupGpes();
456126372Snjl
457126372Snjl    ACPI_FLUSH_CPU_CACHE();
458114237Snjl
459167802Sjkim    Status = AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, (UINT32) AcpiGbl_FADT->S4BiosReq, 8);
460126372Snjl
461126372Snjl    do {
462126372Snjl        AcpiOsStall(1000);
463126372Snjl        Status = AcpiGetRegister (ACPI_BITREG_WAKE_STATUS, &InValue, ACPI_MTX_DO_NOT_LOCK);
464114237Snjl        if (ACPI_FAILURE (Status))
465128212Snjl        {
466129684Snjl            return_ACPI_STATUS (Status);
467128212Snjl        }
468128212Snjl    } while (!InValue);
469151937Sjkim
470126372Snjl    return_ACPI_STATUS (AE_OK);
471126372Snjl}
472126372Snjl
473126372Snjl
474129684Snjl/******************************************************************************
475114237Snjl *
476151937Sjkim * FUNCTION:    AcpiLeaveSleepState
477129684Snjl *
478129684Snjl * PARAMETERS:  SleepState          - Which sleep state we just exited
479129684Snjl *
480129684Snjl * RETURN:      Status
481129684Snjl *
482126372Snjl * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
483126372Snjl *
484193267Sjkim ******************************************************************************/
485167802Sjkim
486114237SnjlACPI_STATUS
487114237SnjlAcpiLeaveSleepState (
488114237Snjl    UINT8               SleepState)
489193267Sjkim{
490114237Snjl    ACPI_OBJECT_LIST    ArgList;
491114237Snjl    ACPI_OBJECT         Arg;
492114237Snjl    ACPI_STATUS         Status;
493114237Snjl
494114237Snjl
495114237Snjl    ACPI_FUNCTION_TRACE ("AcpiLeaveSleepState");
496114237Snjl
497114237Snjl
498114237Snjl    /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
499167802Sjkim
500114237Snjl    AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
501167802Sjkim
502151937Sjkim    /* Setup parameter object */
503114237Snjl
50482367Smsmith    ArgList.Count = 1;
50582367Smsmith    ArgList.Pointer = &Arg;
50682367Smsmith
50782367Smsmith    Arg.Type = ACPI_TYPE_INTEGER;
50882367Smsmith    Arg.Integer.Value = SleepState;
50982367Smsmith
51082367Smsmith    /* Ignore any errors from these methods */
511138287Smarks
51282367Smsmith    Status = AcpiEvaluateObject (NULL, "\\_BFS", &ArgList, NULL);
51382367Smsmith    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
51482367Smsmith    {
51582367Smsmith        ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", AcpiFormatException (Status)));
51682367Smsmith    }
517123315Snjl
51882367Smsmith    Status = AcpiEvaluateObject (NULL, "\\_WAK", &ArgList, NULL);
519123315Snjl    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
520123315Snjl    {
521123315Snjl        ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", AcpiFormatException (Status)));
522123315Snjl    }
523123315Snjl
524193267Sjkim    /* _WAK returns stuff - do we want to look at it? */
525193267Sjkim
52682367Smsmith    Status = AcpiHwEnableNonWakeupGpes();
52783174Smsmith    if (ACPI_FAILURE (Status))
528167802Sjkim    {
52982367Smsmith        return_ACPI_STATUS (Status);
53091116Smsmith    }
531126372Snjl
532126372Snjl    /* Disable BM arbitration */
533126372Snjl    Status = AcpiSetRegister (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK);
534126372Snjl
535126372Snjl    return_ACPI_STATUS (Status);
536126372Snjl}
537126372Snjl