xref: /titanic_50/usr/src/uts/intel/io/acpica/hardware/hwsleep.c (revision 24da5b34f49324ed742a340010ed5bd3d4e06625)
1 
2 /******************************************************************************
3  *
4  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
5  *              $Revision: 1.82 $
6  *
7  *****************************************************************************/
8 
9 /******************************************************************************
10  *
11  * 1. Copyright Notice
12  *
13  * Some or all of this work - Copyright (c) 1999 - 2006, Intel Corp.
14  * All rights reserved.
15  *
16  * 2. License
17  *
18  * 2.1. This is your license from Intel Corp. under its intellectual property
19  * rights.  You may have additional license terms from the party that provided
20  * you this software, covering your right to use that party's intellectual
21  * property rights.
22  *
23  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24  * copy of the source code appearing in this file ("Covered Code") an
25  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26  * base code distributed originally by Intel ("Original Intel Code") to copy,
27  * make derivatives, distribute, use and display any portion of the Covered
28  * Code in any form, with the right to sublicense such rights; and
29  *
30  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31  * license (with the right to sublicense), under only those claims of Intel
32  * patents that are infringed by the Original Intel Code, to make, use, sell,
33  * offer to sell, and import the Covered Code and derivative works thereof
34  * solely to the minimum extent necessary to exercise the above copyright
35  * license, and in no event shall the patent license extend to any additions
36  * to or modifications of the Original Intel Code.  No other license or right
37  * is granted directly or by implication, estoppel or otherwise;
38  *
39  * The above copyright and patent license is granted only if the following
40  * conditions are met:
41  *
42  * 3. Conditions
43  *
44  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45  * Redistribution of source code of any substantial portion of the Covered
46  * Code or modification with rights to further distribute source must include
47  * the above Copyright Notice, the above License, this list of Conditions,
48  * and the following Disclaimer and Export Compliance provision.  In addition,
49  * Licensee must cause all Covered Code to which Licensee contributes to
50  * contain a file documenting the changes Licensee made to create that Covered
51  * Code and the date of any change.  Licensee must include in that file the
52  * documentation of any changes made by any predecessor Licensee.  Licensee
53  * must include a prominent statement that the modification is derived,
54  * directly or indirectly, from Original Intel Code.
55  *
56  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57  * Redistribution of source code of any substantial portion of the Covered
58  * Code or modification without rights to further distribute source must
59  * include the following Disclaimer and Export Compliance provision in the
60  * documentation and/or other materials provided with distribution.  In
61  * addition, Licensee may not authorize further sublicense of source of any
62  * portion of the Covered Code, and must include terms to the effect that the
63  * license from Licensee to its licensee is limited to the intellectual
64  * property embodied in the software Licensee provides to its licensee, and
65  * not to intellectual property embodied in modifications its licensee may
66  * make.
67  *
68  * 3.3. Redistribution of Executable. Redistribution in executable form of any
69  * substantial portion of the Covered Code or modification must reproduce the
70  * above Copyright Notice, and the following Disclaimer and Export Compliance
71  * provision in the documentation and/or other materials provided with the
72  * distribution.
73  *
74  * 3.4. Intel retains all right, title, and interest in and to the Original
75  * Intel Code.
76  *
77  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78  * Intel shall be used in advertising or otherwise to promote the sale, use or
79  * other dealings in products derived from or relating to the Covered Code
80  * without prior written authorization from Intel.
81  *
82  * 4. Disclaimer and Export Compliance
83  *
84  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
87  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
88  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
89  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
90  * PARTICULAR PURPOSE.
91  *
92  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
93  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
94  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
95  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
96  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
97  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
98  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
99  * LIMITED REMEDY.
100  *
101  * 4.3. Licensee shall not export, either directly or indirectly, any of this
102  * software or system incorporating such software without first obtaining any
103  * required license or other approval from the U. S. Department of Commerce or
104  * any other agency or department of the United States Government.  In the
105  * event Licensee exports any such software from the United States or
106  * re-exports any such software from a foreign destination, Licensee shall
107  * ensure that the distribution and export/re-export of the software is in
108  * compliance with all laws, regulations, orders, or other restrictions of the
109  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
110  * any of its subsidiaries will export/re-export any technical data, process,
111  * software, or service, directly or indirectly, to any country for which the
112  * United States government or any agency thereof requires an export license,
113  * other governmental approval, or letter of assurance, without first obtaining
114  * such license, approval or letter.
115  *
116  *****************************************************************************/
117 
118 #include "acpi.h"
119 
120 #define _COMPONENT          ACPI_HARDWARE
121         ACPI_MODULE_NAME    ("hwsleep")
122 
123 
124 /*******************************************************************************
125  *
126  * FUNCTION:    AcpiSetFirmwareWakingVector
127  *
128  * PARAMETERS:  PhysicalAddress     - Physical address of ACPI real mode
129  *                                    entry point.
130  *
131  * RETURN:      Status
132  *
133  * DESCRIPTION: Access function for the FirmwareWakingVector field in FACS
134  *
135  ******************************************************************************/
136 
137 ACPI_STATUS
138 AcpiSetFirmwareWakingVector (
139     ACPI_PHYSICAL_ADDRESS PhysicalAddress)
140 {
141 
142     ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector);
143 
144 
145     /* Set the vector */
146 
147     if (AcpiGbl_CommonFACS.VectorWidth == 32)
148     {
149         *(ACPI_CAST_PTR (UINT32, AcpiGbl_CommonFACS.FirmwareWakingVector))
150                 = (UINT32) PhysicalAddress;
151     }
152     else
153     {
154         *AcpiGbl_CommonFACS.FirmwareWakingVector
155                 = PhysicalAddress;
156     }
157 
158     return_ACPI_STATUS (AE_OK);
159 }
160 
161 ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector)
162 
163 
164 /*******************************************************************************
165  *
166  * FUNCTION:    AcpiGetFirmwareWakingVector
167  *
168  * PARAMETERS:  *PhysicalAddress    - Where the contents of
169  *                                    the FirmwareWakingVector field of
170  *                                    the FACS will be returned.
171  *
172  * RETURN:      Status, vector
173  *
174  * DESCRIPTION: Access function for the FirmwareWakingVector field in FACS
175  *
176  ******************************************************************************/
177 
178 ACPI_STATUS
179 AcpiGetFirmwareWakingVector (
180     ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
181 {
182 
183     ACPI_FUNCTION_TRACE (AcpiGetFirmwareWakingVector);
184 
185 
186     if (!PhysicalAddress)
187     {
188         return_ACPI_STATUS (AE_BAD_PARAMETER);
189     }
190 
191     /* Get the vector */
192 
193     if (AcpiGbl_CommonFACS.VectorWidth == 32)
194     {
195         *PhysicalAddress = (ACPI_PHYSICAL_ADDRESS)
196             *(ACPI_CAST_PTR (UINT32, AcpiGbl_CommonFACS.FirmwareWakingVector));
197     }
198     else
199     {
200         *PhysicalAddress =
201             *AcpiGbl_CommonFACS.FirmwareWakingVector;
202     }
203 
204     return_ACPI_STATUS (AE_OK);
205 }
206 
207 ACPI_EXPORT_SYMBOL (AcpiGetFirmwareWakingVector)
208 
209 
210 /*******************************************************************************
211  *
212  * FUNCTION:    AcpiEnterSleepStatePrep
213  *
214  * PARAMETERS:  SleepState          - Which sleep state to enter
215  *
216  * RETURN:      Status
217  *
218  * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
219  *              This function must execute with interrupts enabled.
220  *              We break sleeping into 2 stages so that OSPM can handle
221  *              various OS-specific tasks between the two steps.
222  *
223  ******************************************************************************/
224 
225 ACPI_STATUS
226 AcpiEnterSleepStatePrep (
227     UINT8               SleepState)
228 {
229     ACPI_STATUS         Status;
230     ACPI_OBJECT_LIST    ArgList;
231     ACPI_OBJECT         Arg;
232 
233 
234     ACPI_FUNCTION_TRACE (AcpiEnterSleepStatePrep);
235 
236 
237     /*
238      * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
239      */
240     Status = AcpiGetSleepTypeData (SleepState,
241                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
242     if (ACPI_FAILURE (Status))
243     {
244         return_ACPI_STATUS (Status);
245     }
246 
247     /* Setup parameter object */
248 
249     ArgList.Count = 1;
250     ArgList.Pointer = &Arg;
251 
252     Arg.Type = ACPI_TYPE_INTEGER;
253     Arg.Integer.Value = SleepState;
254 
255     /* Run the _PTS and _GTS methods */
256 
257     Status = AcpiEvaluateObject (NULL, METHOD_NAME__PTS, &ArgList, NULL);
258     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
259     {
260         return_ACPI_STATUS (Status);
261     }
262 
263     Status = AcpiEvaluateObject (NULL, METHOD_NAME__GTS, &ArgList, NULL);
264     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
265     {
266         return_ACPI_STATUS (Status);
267     }
268 
269     /* Setup the argument to _SST */
270 
271     switch (SleepState)
272     {
273     case ACPI_STATE_S0:
274         Arg.Integer.Value = ACPI_SST_WORKING;
275         break;
276 
277     case ACPI_STATE_S1:
278     case ACPI_STATE_S2:
279     case ACPI_STATE_S3:
280         Arg.Integer.Value = ACPI_SST_SLEEPING;
281         break;
282 
283     case ACPI_STATE_S4:
284         Arg.Integer.Value = ACPI_SST_SLEEP_CONTEXT;
285         break;
286 
287     default:
288         Arg.Integer.Value = ACPI_SST_INDICATOR_OFF; /* Default is off */
289         break;
290     }
291 
292     /* Set the system indicators to show the desired sleep state. */
293 
294     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
295     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
296     {
297         ACPI_EXCEPTION ((AE_INFO, Status, "While executing method _SST"));
298     }
299 
300     return_ACPI_STATUS (AE_OK);
301 }
302 
303 ACPI_EXPORT_SYMBOL (AcpiEnterSleepStatePrep)
304 
305 
306 /*******************************************************************************
307  *
308  * FUNCTION:    AcpiEnterSleepState
309  *
310  * PARAMETERS:  SleepState          - Which sleep state to enter
311  *
312  * RETURN:      Status
313  *
314  * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
315  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
316  *
317  ******************************************************************************/
318 
319 ACPI_STATUS
320 AcpiEnterSleepState (
321     UINT8                   SleepState)
322 {
323     UINT32                  PM1AControl;
324     UINT32                  PM1BControl;
325     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
326     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
327     UINT32                  InValue;
328     ACPI_STATUS             Status;
329 
330 
331     ACPI_FUNCTION_TRACE (AcpiEnterSleepState);
332 
333 
334     if ((AcpiGbl_SleepTypeA > ACPI_SLEEP_TYPE_MAX) ||
335         (AcpiGbl_SleepTypeB > ACPI_SLEEP_TYPE_MAX))
336     {
337         ACPI_ERROR ((AE_INFO, "Sleep values out of range: A=%X B=%X",
338             AcpiGbl_SleepTypeA, AcpiGbl_SleepTypeB));
339         return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
340     }
341 
342     SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
343     SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
344 
345     /* Clear wake status */
346 
347     Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
348     if (ACPI_FAILURE (Status))
349     {
350         return_ACPI_STATUS (Status);
351     }
352 
353     /* Clear all fixed and general purpose status bits */
354 
355     Status = AcpiHwClearAcpiStatus (ACPI_MTX_DO_NOT_LOCK);
356     if (ACPI_FAILURE (Status))
357     {
358         return_ACPI_STATUS (Status);
359     }
360 
361     if (SleepState != ACPI_STATE_S5)
362     {
363         /* Disable BM arbitration */
364 
365         Status = AcpiSetRegister (ACPI_BITREG_ARB_DISABLE,
366                     1, ACPI_MTX_DO_NOT_LOCK);
367         if (ACPI_FAILURE (Status))
368         {
369             return_ACPI_STATUS (Status);
370         }
371     }
372 
373     /*
374      * 1) Disable/Clear all GPEs
375      * 2) Enable all wakeup GPEs
376      */
377     Status = AcpiHwDisableAllGpes ();
378     if (ACPI_FAILURE (Status))
379     {
380         return_ACPI_STATUS (Status);
381     }
382     AcpiGbl_SystemAwakeAndRunning = FALSE;
383 
384     Status = AcpiHwEnableAllWakeupGpes ();
385     if (ACPI_FAILURE (Status))
386     {
387         return_ACPI_STATUS (Status);
388     }
389 
390     /* Get current value of PM1A control */
391 
392     Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
393                 ACPI_REGISTER_PM1_CONTROL, &PM1AControl);
394     if (ACPI_FAILURE (Status))
395     {
396         return_ACPI_STATUS (Status);
397     }
398     ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
399         "Entering sleep state [S%d]\n", SleepState));
400 
401     /* Clear SLP_EN and SLP_TYP fields */
402 
403     PM1AControl &= ~(SleepTypeRegInfo->AccessBitMask |
404                      SleepEnableRegInfo->AccessBitMask);
405     PM1BControl = PM1AControl;
406 
407     /* Insert SLP_TYP bits */
408 
409     PM1AControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
410     PM1BControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
411 
412     /*
413      * We split the writes of SLP_TYP and SLP_EN to workaround
414      * poorly implemented hardware.
415      */
416 
417     /* Write #1: fill in SLP_TYP data */
418 
419     Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
420                 ACPI_REGISTER_PM1A_CONTROL, PM1AControl);
421     if (ACPI_FAILURE (Status))
422     {
423         return_ACPI_STATUS (Status);
424     }
425 
426     Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
427                 ACPI_REGISTER_PM1B_CONTROL, PM1BControl);
428     if (ACPI_FAILURE (Status))
429     {
430         return_ACPI_STATUS (Status);
431     }
432 
433     /* Insert SLP_ENABLE bit */
434 
435     PM1AControl |= SleepEnableRegInfo->AccessBitMask;
436     PM1BControl |= SleepEnableRegInfo->AccessBitMask;
437 
438     /* Write #2: SLP_TYP + SLP_EN */
439 
440     ACPI_FLUSH_CPU_CACHE ();
441 
442     Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
443                 ACPI_REGISTER_PM1A_CONTROL, PM1AControl);
444     if (ACPI_FAILURE (Status))
445     {
446         return_ACPI_STATUS (Status);
447     }
448 
449     Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
450                 ACPI_REGISTER_PM1B_CONTROL, PM1BControl);
451     if (ACPI_FAILURE (Status))
452     {
453         return_ACPI_STATUS (Status);
454     }
455 
456     if (SleepState > ACPI_STATE_S3)
457     {
458         /*
459          * We wanted to sleep > S3, but it didn't happen (by virtue of the
460          * fact that we are still executing!)
461          *
462          * Wait ten seconds, then try again. This is to get S4/S5 to work on
463          * all machines.
464          *
465          * We wait so long to allow chipsets that poll this reg very slowly to
466          * still read the right value. Ideally, this block would go
467          * away entirely.
468          */
469         AcpiOsStall (10000000);
470 
471         Status = AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
472                     ACPI_REGISTER_PM1_CONTROL,
473                     SleepEnableRegInfo->AccessBitMask);
474         if (ACPI_FAILURE (Status))
475         {
476             return_ACPI_STATUS (Status);
477         }
478     }
479 
480     /* Wait until we enter sleep state */
481 
482     do
483     {
484         Status = AcpiGetRegister (ACPI_BITREG_WAKE_STATUS, &InValue,
485             ACPI_MTX_DO_NOT_LOCK);
486         if (ACPI_FAILURE (Status))
487         {
488             return_ACPI_STATUS (Status);
489         }
490 
491         /* Spin until we wake */
492 
493     } while (!InValue);
494 
495     return_ACPI_STATUS (AE_OK);
496 }
497 
498 ACPI_EXPORT_SYMBOL (AcpiEnterSleepState)
499 
500 
501 /*******************************************************************************
502  *
503  * FUNCTION:    AcpiEnterSleepStateS4bios
504  *
505  * PARAMETERS:  None
506  *
507  * RETURN:      Status
508  *
509  * DESCRIPTION: Perform a S4 bios request.
510  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
511  *
512  ******************************************************************************/
513 
514 ACPI_STATUS
515 AcpiEnterSleepStateS4bios (
516     void)
517 {
518     UINT32                  InValue;
519     ACPI_STATUS             Status;
520 
521 
522     ACPI_FUNCTION_TRACE (AcpiEnterSleepStateS4bios);
523 
524 
525     Status = AcpiSetRegister (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
526     if (ACPI_FAILURE (Status))
527     {
528         return_ACPI_STATUS (Status);
529     }
530 
531     Status = AcpiHwClearAcpiStatus (ACPI_MTX_DO_NOT_LOCK);
532     if (ACPI_FAILURE (Status))
533     {
534         return_ACPI_STATUS (Status);
535     }
536 
537     /*
538      * 1) Disable/Clear all GPEs
539      * 2) Enable all wakeup GPEs
540      */
541     Status = AcpiHwDisableAllGpes ();
542     if (ACPI_FAILURE (Status))
543     {
544         return_ACPI_STATUS (Status);
545     }
546     AcpiGbl_SystemAwakeAndRunning = FALSE;
547 
548     Status = AcpiHwEnableAllWakeupGpes ();
549     if (ACPI_FAILURE (Status))
550     {
551         return_ACPI_STATUS (Status);
552     }
553 
554     ACPI_FLUSH_CPU_CACHE ();
555 
556     Status = AcpiOsWritePort (AcpiGbl_FADT->SmiCmd,
557                 (UINT32) AcpiGbl_FADT->S4BiosReq, 8);
558 
559     do {
560         AcpiOsStall(1000);
561         Status = AcpiGetRegister (ACPI_BITREG_WAKE_STATUS, &InValue,
562             ACPI_MTX_DO_NOT_LOCK);
563         if (ACPI_FAILURE (Status))
564         {
565             return_ACPI_STATUS (Status);
566         }
567     } while (!InValue);
568 
569     return_ACPI_STATUS (AE_OK);
570 }
571 
572 ACPI_EXPORT_SYMBOL (AcpiEnterSleepStateS4bios)
573 
574 
575 /*******************************************************************************
576  *
577  * FUNCTION:    AcpiLeaveSleepState
578  *
579  * PARAMETERS:  SleepState          - Which sleep state we just exited
580  *
581  * RETURN:      Status
582  *
583  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
584  *              Called with interrupts ENABLED.
585  *
586  ******************************************************************************/
587 
588 ACPI_STATUS
589 AcpiLeaveSleepState (
590     UINT8                   SleepState)
591 {
592     ACPI_OBJECT_LIST        ArgList;
593     ACPI_OBJECT             Arg;
594     ACPI_STATUS             Status;
595     ACPI_BIT_REGISTER_INFO  *SleepTypeRegInfo;
596     ACPI_BIT_REGISTER_INFO  *SleepEnableRegInfo;
597     UINT32                  PM1AControl;
598     UINT32                  PM1BControl;
599 
600 
601     ACPI_FUNCTION_TRACE (AcpiLeaveSleepState);
602 
603 
604     /*
605      * Set SLP_TYPE and SLP_EN to state S0.
606      * This is unclear from the ACPI Spec, but it is required
607      * by some machines.
608      */
609     Status = AcpiGetSleepTypeData (ACPI_STATE_S0,
610                     &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB);
611     if (ACPI_SUCCESS (Status))
612     {
613         SleepTypeRegInfo   = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_TYPE_A);
614         SleepEnableRegInfo = AcpiHwGetBitRegisterInfo (ACPI_BITREG_SLEEP_ENABLE);
615 
616         /* Get current value of PM1A control */
617 
618         Status = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK,
619                     ACPI_REGISTER_PM1_CONTROL, &PM1AControl);
620         if (ACPI_SUCCESS (Status))
621         {
622             /* Clear SLP_EN and SLP_TYP fields */
623 
624             PM1AControl &= ~(SleepTypeRegInfo->AccessBitMask |
625                              SleepEnableRegInfo->AccessBitMask);
626             PM1BControl = PM1AControl;
627 
628             /* Insert SLP_TYP bits */
629 
630             PM1AControl |= (AcpiGbl_SleepTypeA << SleepTypeRegInfo->BitPosition);
631             PM1BControl |= (AcpiGbl_SleepTypeB << SleepTypeRegInfo->BitPosition);
632 
633             /* Just ignore any errors */
634 
635             (void) AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
636                             ACPI_REGISTER_PM1A_CONTROL, PM1AControl);
637             (void) AcpiHwRegisterWrite (ACPI_MTX_DO_NOT_LOCK,
638                             ACPI_REGISTER_PM1B_CONTROL, PM1BControl);
639         }
640     }
641 
642     /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
643 
644     AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
645 
646     /* Setup parameter object */
647 
648     ArgList.Count = 1;
649     ArgList.Pointer = &Arg;
650     Arg.Type = ACPI_TYPE_INTEGER;
651 
652     /* Ignore any errors from these methods */
653 
654     Arg.Integer.Value = ACPI_SST_WAKING;
655     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
656     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
657     {
658         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
659     }
660 
661     Arg.Integer.Value = SleepState;
662     Status = AcpiEvaluateObject (NULL, METHOD_NAME__BFS, &ArgList, NULL);
663     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
664     {
665         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _BFS"));
666     }
667 
668     Status = AcpiEvaluateObject (NULL, METHOD_NAME__WAK, &ArgList, NULL);
669     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
670     {
671         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _WAK"));
672     }
673     /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
674 
675     /*
676      * Restore the GPEs:
677      * 1) Disable/Clear all GPEs
678      * 2) Enable all runtime GPEs
679      */
680     Status = AcpiHwDisableAllGpes ();
681     if (ACPI_FAILURE (Status))
682     {
683         return_ACPI_STATUS (Status);
684     }
685     AcpiGbl_SystemAwakeAndRunning = TRUE;
686 
687     Status = AcpiHwEnableAllRuntimeGpes ();
688     if (ACPI_FAILURE (Status))
689     {
690         return_ACPI_STATUS (Status);
691     }
692 
693     /* Enable power button */
694 
695     (void) AcpiSetRegister(
696             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].EnableRegisterId,
697             1, ACPI_MTX_DO_NOT_LOCK);
698 
699     (void) AcpiSetRegister(
700             AcpiGbl_FixedEventInfo[ACPI_EVENT_POWER_BUTTON].StatusRegisterId,
701             1, ACPI_MTX_DO_NOT_LOCK);
702 
703     /* Enable BM arbitration */
704 
705     Status = AcpiSetRegister (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK);
706     if (ACPI_FAILURE (Status))
707     {
708         return_ACPI_STATUS (Status);
709     }
710 
711     Arg.Integer.Value = ACPI_SST_WORKING;
712     Status = AcpiEvaluateObject (NULL, METHOD_NAME__SST, &ArgList, NULL);
713     if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
714     {
715         ACPI_EXCEPTION ((AE_INFO, Status, "During Method _SST"));
716     }
717 
718     return_ACPI_STATUS (Status);
719 }
720 
721 ACPI_EXPORT_SYMBOL (AcpiLeaveSleepState)
722 
723