hwsleep.c revision 126372
1101313Stjr
2101313Stjr/******************************************************************************
3101313Stjr *
4101313Stjr * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
5101313Stjr *              $Revision: 65 $
6101313Stjr *
7101313Stjr *****************************************************************************/
8101313Stjr
9101313Stjr/******************************************************************************
10101313Stjr *
11101313Stjr * 1. Copyright Notice
12101313Stjr *
13101313Stjr * Some or all of this work - Copyright (c) 1999 - 2004, Intel Corp.
14101313Stjr * All rights reserved.
15101313Stjr *
16101313Stjr * 2. License
17101313Stjr *
18101313Stjr * 2.1. This is your license from Intel Corp. under its intellectual property
19101313Stjr * rights.  You may have additional license terms from the party that provided
20101313Stjr * you this software, covering your right to use that party's intellectual
21101313Stjr * property rights.
22101313Stjr *
23101313Stjr * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24101313Stjr * copy of the source code appearing in this file ("Covered Code") an
25101313Stjr * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26101313Stjr * base code distributed originally by Intel ("Original Intel Code") to copy,
27104402Stjr * make derivatives, distribute, use and display any portion of the Covered
28101313Stjr * Code in any form, with the right to sublicense such rights; and
29101313Stjr *
30101313Stjr * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31107392Sru * license (with the right to sublicense), under only those claims of Intel
32101313Stjr * patents that are infringed by the Original Intel Code, to make, use, sell,
33101313Stjr * offer to sell, and import the Covered Code and derivative works thereof
34101313Stjr * solely to the minimum extent necessary to exercise the above copyright
35101313Stjr * license, and in no event shall the patent license extend to any additions
36101313Stjr * to or modifications of the Original Intel Code.  No other license or right
37101313Stjr * is granted directly or by implication, estoppel or otherwise;
38101313Stjr *
39101313Stjr * The above copyright and patent license is granted only if the following
40101313Stjr * conditions are met:
41101313Stjr *
42101313Stjr * 3. Conditions
43101313Stjr *
44101313Stjr * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45101313Stjr * Redistribution of source code of any substantial portion of the Covered
46101313Stjr * Code or modification with rights to further distribute source must include
47101313Stjr * the above Copyright Notice, the above License, this list of Conditions,
48101313Stjr * and the following Disclaimer and Export Compliance provision.  In addition,
49101313Stjr * Licensee must cause all Covered Code to which Licensee contributes to
50101313Stjr * contain a file documenting the changes Licensee made to create that Covered
51101313Stjr * Code and the date of any change.  Licensee must include in that file the
52107392Sru * documentation of any changes made by any predecessor Licensee.  Licensee
53101313Stjr * must include a prominent statement that the modification is derived,
54101313Stjr * directly or indirectly, from Original Intel Code.
55101313Stjr *
56101313Stjr * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57101313Stjr * Redistribution of source code of any substantial portion of the Covered
58101313Stjr * Code or modification without rights to further distribute source must
59101313Stjr * include the following Disclaimer and Export Compliance provision in the
60101313Stjr * documentation and/or other materials provided with distribution.  In
61101313Stjr * addition, Licensee may not authorize further sublicense of source of any
62101313Stjr * portion of the Covered Code, and must include terms to the effect that the
63101313Stjr * license from Licensee to its licensee is limited to the intellectual
64101313Stjr * property embodied in the software Licensee provides to its licensee, and
65101313Stjr * not to intellectual property embodied in modifications its licensee may
66101313Stjr * make.
67101313Stjr *
68101313Stjr * 3.3. Redistribution of Executable. Redistribution in executable form of any
69101313Stjr * substantial portion of the Covered Code or modification must reproduce the
70101313Stjr * above Copyright Notice, and the following Disclaimer and Export Compliance
71101313Stjr * provision in the documentation and/or other materials provided with the
72101313Stjr * distribution.
73104402Stjr *
74104402Stjr * 3.4. Intel retains all right, title, and interest in and to the Original
75104402Stjr * Intel Code.
76104402Stjr *
77104402Stjr * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78104402Stjr * Intel shall be used in advertising or otherwise to promote the sale, use or
79104402Stjr * other dealings in products derived from or relating to the Covered Code
80104402Stjr * without prior written authorization from Intel.
81104402Stjr *
82104402Stjr * 4. Disclaimer and Export Compliance
83104402Stjr *
84104402Stjr * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85104402Stjr * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86104402Stjr * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
87101313Stjr * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
88101313Stjr * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
89101313Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
90101313Stjr * PARTICULAR PURPOSE.
91101313Stjr *
92101313Stjr * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
93101313Stjr * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
94101313Stjr * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
95101313Stjr * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
96101313Stjr * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
97101313Stjr * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
98101313Stjr * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
99101313Stjr * LIMITED REMEDY.
100101313Stjr *
101101313Stjr * 4.3. Licensee shall not export, either directly or indirectly, any of this
102101313Stjr * software or system incorporating such software without first obtaining any
103101313Stjr * required license or other approval from the U. S. Department of Commerce or
104101313Stjr * any other agency or department of the United States Government.  In the
105101313Stjr * event Licensee exports any such software from the United States or
106101313Stjr * re-exports any such software from a foreign destination, Licensee shall
107101313Stjr * ensure that the distribution and export/re-export of the software is in
108101313Stjr * compliance with all laws, regulations, orders, or other restrictions of the
109101313Stjr * U.S. Export Administration Regulations. Licensee agrees that neither it nor
110101313Stjr * any of its subsidiaries will export/re-export any technical data, process,
111101313Stjr * software, or service, directly or indirectly, to any country for which the
112101313Stjr * United States government or any agency thereof requires an export license,
113101313Stjr * other governmental approval, or letter of assurance, without first obtaining
114101313Stjr * such license, approval or letter.
115101313Stjr *
116101313Stjr *****************************************************************************/
117101313Stjr
118101313Stjr#include "acpi.h"
119101313Stjr
120101313Stjr#define _COMPONENT          ACPI_HARDWARE
121101313Stjr        ACPI_MODULE_NAME    ("hwsleep")
122101313Stjr
123
124#define METHOD_NAME__BFS        "\\_BFS"
125#define METHOD_NAME__GTS        "\\_GTS"
126#define METHOD_NAME__PTS        "\\_PTS"
127#define METHOD_NAME__SST        "\\_SI._SST"
128#define METHOD_NAME__WAK        "\\_WAK"
129
130#define ACPI_SST_INDICATOR_OFF  0
131#define ACPI_SST_WORKING        1
132#define ACPI_SST_WAKING         2
133#define ACPI_SST_SLEEPING       3
134#define ACPI_SST_SLEEP_CONTEXT  4
135
136
137/******************************************************************************
138 *
139 * FUNCTION:    AcpiSetFirmwareWakingVector
140 *
141 * PARAMETERS:  PhysicalAddress     - Physical address of ACPI real mode
142 *                                    entry point.
143 *
144 * RETURN:      Status
145 *
146 * DESCRIPTION: Access function for dFirmwareWakingVector field in FACS
147 *
148 ******************************************************************************/
149
150ACPI_STATUS
151AcpiSetFirmwareWakingVector (
152    ACPI_PHYSICAL_ADDRESS PhysicalAddress)
153{
154
155    ACPI_FUNCTION_TRACE ("AcpiSetFirmwareWakingVector");
156
157
158    /* Set the vector */
159
160    if (AcpiGbl_CommonFACS.VectorWidth == 32)
161    {
162        *(ACPI_CAST_PTR (UINT32, AcpiGbl_CommonFACS.FirmwareWakingVector))
163                = (UINT32) PhysicalAddress;
164    }
165    else
166    {
167        *AcpiGbl_CommonFACS.FirmwareWakingVector
168                = PhysicalAddress;
169    }
170
171    return_ACPI_STATUS (AE_OK);
172}
173
174
175/******************************************************************************
176 *
177 * FUNCTION:    AcpiGetFirmwareWakingVector
178 *
179 * PARAMETERS:  *PhysicalAddress    - Output buffer where contents of
180 *                                    the FirmwareWakingVector field of
181 *                                    the FACS will be stored.
182 *
183 * RETURN:      Status
184 *
185 * DESCRIPTION: Access function for FirmwareWakingVector field in FACS
186 *
187 ******************************************************************************/
188
189ACPI_STATUS
190AcpiGetFirmwareWakingVector (
191    ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
192{
193
194    ACPI_FUNCTION_TRACE ("AcpiGetFirmwareWakingVector");
195
196
197    if (!PhysicalAddress)
198    {
199        return_ACPI_STATUS (AE_BAD_PARAMETER);
200    }
201
202    /* Get the vector */
203
204    if (AcpiGbl_CommonFACS.VectorWidth == 32)
205    {
206        *PhysicalAddress = (ACPI_PHYSICAL_ADDRESS)
207            *(ACPI_CAST_PTR (UINT32, AcpiGbl_CommonFACS.FirmwareWakingVector));
208    }
209    else
210    {
211        *PhysicalAddress =
212            *AcpiGbl_CommonFACS.FirmwareWakingVector;
213    }
214
215    return_ACPI_STATUS (AE_OK);
216}
217
218
219/******************************************************************************
220 *
221 * FUNCTION:    AcpiEnterSleepStatePrep
222 *
223 * PARAMETERS:  SleepState          - Which sleep state to enter
224 *
225 * RETURN:      Status
226 *
227 * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
228 *              This function must execute with interrupts enabled.
229 *              We break sleeping into 2 stages so that OSPM can handle
230 *              various OS-specific tasks between the two steps.
231 *
232 ******************************************************************************/
233
234ACPI_STATUS
235AcpiEnterSleepStatePrep (
236    UINT8               SleepState)
237{
238    ACPI_STATUS         Status;
239    ACPI_OBJECT_LIST    ArgList;
240    ACPI_OBJECT         Arg;
241
242
243    ACPI_FUNCTION_TRACE ("AcpiEnterSleepStatePrep");
244
245
246    /*
247     * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
248     */
249    Status = AcpiGetSleepTypeData (SleepState,
250                    &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
251    if (ACPI_FAILURE (Status))
252    {
253        return_ACPI_STATUS (Status);
254    }
255
256    /* Setup parameter object */
257
258    ArgList.Count = 1;
259    ArgList.Pointer = &Arg;
260
261    Arg.Type = ACPI_TYPE_INTEGER;
262    Arg.Integer.Value = SleepState;
263
264    /* Run the _PTS and _GTS methods */
265
266    Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL);
267    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
268    {
269        return_ACPI_STATUS (Status);
270    }
271
272    Status = AcpiEvaluateObject (NULL, METHOD_NAME__GTS, &ArgList, NULL);
273    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
274    {
275        return_ACPI_STATUS (Status);
276    }
277
278    /* Setup the argument to _SST */
279
280    switch (SleepState)
281    {
282    case ACPI_STATE_S0:
283        Arg.Integer.Value = ACPI_SST_WORKING;
284        break;
285
286    case ACPI_STATE_S1:
287    case ACPI_STATE_S2:
288    case ACPI_STATE_S3:
289        Arg.Integer.Value = ACPI_SST_SLEEPING;
290        break;
291
292    case ACPI_STATE_S4:
293        Arg.Integer.Value = ACPI_SST_SLEEP_CONTEXT;
294        break;
295
296    default:
297        Arg.Integer.Value = ACPI_SST_INDICATOR_OFF; /* Default is indicator off */
298        break;
299    }
300
301    /* Set the system indicators to show the desired sleep state. */
302
303    Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
304    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
305    {
306         ACPI_REPORT_ERROR (("Method _SST failed, %s\n", AcpiFormatException (Status)));
307    }
308
309    return_ACPI_STATUS (AE_OK);
310}
311
312
313/******************************************************************************
314 *
315 * FUNCTION:    AcpiEnterSleepState
316 *
317 * PARAMETERS:  SleepState          - Which sleep state to enter
318 *
319 * RETURN:      Status
320 *
321 * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
322 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
323 *
324 ******************************************************************************/
325
326ACPI_STATUS
327AcpiEnterSleepState (
328    UINT8                   SleepState)
329{
330    UINT32                  PM1AControl;
331    UINT32                  PM1BControl;
332    ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
333    ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
334    UINT32                  InValue;
335    ACPI_STATUS             Status;
336
337
338    ACPI_FUNCTION_TRACE ("AcpiEnterSleepState");
339
340
341    if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) ||
342        (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX))
343    {
344        ACPI_REPORT_ERROR (("Sleep values out of range: A=%X B=%X\n",
345            AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB));
346        return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
347    }
348
349    SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
350    SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
351
352    if (SleepState != ACPI_STATE_S5)
353    {
354        /* Clear wake status */
355
356        Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
357        if (ACPI_FAILURE (Status))
358        {
359            return_ACPI_STATUS (Status);
360        }
361
362        Status = AcpiHwClearAcpiStatus (ACPI_MTX_DO_NOT_LOCK);
363        if (ACPI_FAILURE (Status))
364        {
365            return_ACPI_STATUS (Status);
366        }
367
368        /* Disable BM arbitration */
369
370        Status = AcpiSetRegister (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
371        if (ACPI_FAILURE (Status))
372        {
373            return_ACPI_STATUS (Status);
374        }
375    }
376
377    Status = AcpiHwDisableNonWakeupGpes ();
378    if (ACPI_FAILURE (Status))
379    {
380        return_ACPI_STATUS (Status);
381    }
382
383    /* Get current value of PM1A control */
384
385    Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL, &PM1AControl);
386    if (ACPI_FAILURE (Status))
387    {
388        return_ACPI_STATUS (Status);
389    }
390    ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Entering sleep state [S%d]\n", SleepState));
391
392    /* Clear SLP_EN and SLP_TYP fields */
393
394    PM1AControl &= ~(SleepTypeRegInfo->AccessBitMask | SleepEnableRegInfo->AccessBitMask);
395    PM1BControl = PM1AControl;
396
397    /* Insert SLP_TYP bits */
398
399    PM1AControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
400    PM1BControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
401
402    /*
403     * We split the writes of SLP_TYP and SLP_EN to workaround
404     * poorly implemented hardware.
405     */
406
407    /* Write #1: fill in SLP_TYP data */
408
409    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1AControl);
410    if (ACPI_FAILURE (Status))
411    {
412        return_ACPI_STATUS (Status);
413    }
414
415    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1BControl);
416    if (ACPI_FAILURE (Status))
417    {
418        return_ACPI_STATUS (Status);
419    }
420
421    /* Insert SLP_ENABLE bit */
422
423    PM1AControl |= SleepEnableRegInfo->AccessBitMask;
424    PM1BControl |= SleepEnableRegInfo->AccessBitMask;
425
426    /* Write #2: SLP_TYP + SLP_EN */
427
428    ACPI_FLUSH_CPU_CACHE ();
429
430    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1AControl);
431    if (ACPI_FAILURE (Status))
432    {
433        return_ACPI_STATUS (Status);
434    }
435
436    Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1BControl);
437    if (ACPI_FAILURE (Status))
438    {
439        return_ACPI_STATUS (Status);
440    }
441
442    if (SleepState > ACPI_STATE_S3)
443    {
444        /*
445         * We wanted to sleep > S3, but it didn't happen (by virtue of the fact that
446         * we are still executing!)
447         *
448         * Wait ten seconds, then try again. This is to get S4/S5 to work on all machines.
449         *
450         * We wait so long to allow chipsets that poll this reg very slowly to
451         * still read the right value. Ideally, this block would go
452         * away entirely.
453         */
454        AcpiOsStall (10000000);
455
456        Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_CONTROL,
457                    SleepEnableRegInfo->AccessBitMask);
458        if (ACPI_FAILURE (Status))
459        {
460            return_ACPI_STATUS (Status);
461        }
462    }
463
464    /* Wait until we enter sleep state */
465
466    do
467    {
468        Status = AcpiGetRegister (ACPI_BITREG_WAKE_STATUS, &InValue, ACPI_MTX_DO_NOT_LOCK);
469        if (ACPI_FAILURE (Status))
470        {
471            return_ACPI_STATUS (Status);
472        }
473
474        /* Spin until we wake */
475
476    } while (!InValue);
477
478    return_ACPI_STATUS (AE_OK);
479}
480
481
482/******************************************************************************
483 *
484 * FUNCTION:    AcpiEnterSleepStateS4bios
485 *
486 * PARAMETERS:  None
487 *
488 * RETURN:      Status
489 *
490 * DESCRIPTION: Perform a S4 bios request.
491 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
492 *
493 ******************************************************************************/
494
495ACPI_STATUS
496AcpiEnterSleepStateS4bios (
497    void)
498{
499    UINT32                  InValue;
500    ACPI_STATUS             Status;
501
502
503    ACPI_FUNCTION_TRACE ("AcpiEnterSleepStateS4bios");
504
505
506    Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
507    if (ACPI_FAILURE (Status))
508    {
509        return_ACPI_STATUS (Status);
510    }
511
512    Status = AcpiHwClearAcpiStatus (ACPI_MTX_DO_NOT_LOCK);
513    if (ACPI_FAILURE (Status))
514    {
515        return_ACPI_STATUS (Status);
516    }
517
518    Status = AcpiHwDisableNonWakeupGpes ();
519    if (ACPI_FAILURE (Status))
520    {
521        return_ACPI_STATUS (Status);
522    }
523
524    ACPI_FLUSH_CPU_CACHE ();
525
526    Status = AcpiOsWritePort (AcpiGbl_FADT->SmiCmd, (UINT32) AcpiGbl_FADT->S4BiosReq, 8);
527
528    do {
529        AcpiOsStall(1000);
530        Status = AcpiGetRegister (ACPI_BITREG_WAKE_STATUS, &InValue, ACPI_MTX_DO_NOT_LOCK);
531        if (ACPI_FAILURE (Status))
532        {
533            return_ACPI_STATUS (Status);
534        }
535    } while (!InValue);
536
537    return_ACPI_STATUS (AE_OK);
538}
539
540
541/******************************************************************************
542 *
543 * FUNCTION:    AcpiLeaveSleepState
544 *
545 * PARAMETERS:  SleepState          - Which sleep state we just exited
546 *
547 * RETURN:      Status
548 *
549 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
550 *
551 ******************************************************************************/
552
553ACPI_STATUS
554AcpiLeaveSleepState (
555    UINT8                   SleepState)
556{
557    ACPI_OBJECT_LIST        ArgList;
558    ACPI_OBJECT             Arg;
559    ACPI_STATUS             Status;
560    ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
561    ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
562    UINT32                  PM1AControl;
563    UINT32                  PM1BControl;
564
565
566    ACPI_FUNCTION_TRACE ("AcpiLeaveSleepState");
567
568
569    /*
570     * Set SLP_TYPE and SLP_EN to state S0.
571     * This is unclear from the ACPI Spec, but it is required
572     * by some machines.
573     */
574    Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
575                    &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
576    if (ACPI_SUCCESS (Status))
577    {
578        SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
579        SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
580
581        /* Get current value of PM1A control */
582
583        Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
584                    ACPI_REGISTER_PM1_CONTROL, &PM1AControl);
585        if (ACPI_SUCCESS (Status))
586        {
587            /* Clear SLP_EN and SLP_TYP fields */
588
589            PM1AControl &= ~(SleepTypeRegInfo->AccessBitMask |
590                             SleepEnableRegInfo->AccessBitMask);
591            PM1BControl = PM1AControl;
592
593            /* Insert SLP_TYP bits */
594
595            PM1AControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
596            PM1BControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
597
598            /* Just ignore any errors */
599
600            (void) AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
601                            ACPI_REGISTER_PM1A_CONTROL, PM1AControl);
602            (void) AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
603                            ACPI_REGISTER_PM1B_CONTROL, PM1BControl);
604        }
605    }
606
607    /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
608
609    AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
610
611    /* Setup parameter object */
612
613    ArgList.Count = 1;
614    ArgList.Pointer = &Arg;
615    Arg.Type = ACPI_TYPE_INTEGER;
616
617    /* Ignore any errors from these methods */
618
619    Arg.Integer.Value = ACPI_SST_WAKING;
620    Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
621    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
622    {
623        ACPI_REPORT_ERROR (("Method _SST failed, %s\n", AcpiFormatException (Status)));
624    }
625
626    Arg.Integer.Value = SleepState;
627    Status = AcpiEvaluateObject (NULL, METHOD_NAME__BFS, &ArgList, NULL);
628    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
629    {
630        ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", AcpiFormatException (Status)));
631    }
632
633    Status = AcpiEvaluateObject (NULL, METHOD_NAME__WAK, &ArgList, NULL);
634    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
635    {
636        ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", AcpiFormatException (Status)));
637    }
638
639    /* _WAK returns stuff - do we want to look at it? */
640
641    Status = AcpiHwEnableNonWakeupGpes ();
642    if (ACPI_FAILURE (Status))
643    {
644        return_ACPI_STATUS (Status);
645    }
646
647    /* Enable power button */
648
649    AcpiSetRegister(AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].EnableRegisterId,
650            1, ACPI_MTX_DO_NOT_LOCK);
651    AcpiSetRegister(AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId,
652            1, ACPI_MTX_DO_NOT_LOCK);
653
654    /* Enable BM arbitration */
655
656    Status = AcpiSetRegister (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK);
657    if (ACPI_FAILURE (Status))
658    {
659        return_ACPI_STATUS (Status);
660    }
661
662    Arg.Integer.Value = ACPI_SST_WORKING;
663    Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
664    if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
665    {
666        ACPI_REPORT_ERROR (("Method _SST failed, %s\n", AcpiFormatException (Status)));
667    }
668
669    return_ACPI_STATUS (Status);
670}
671