]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/dev/acpica/hardware/hwgpe.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / dev / acpica / hardware / hwgpe.c
1
2 /******************************************************************************
3  *
4  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2011, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44
45 #include <contrib/dev/acpica/include/acpi.h>
46 #include <contrib/dev/acpica/include/accommon.h>
47 #include <contrib/dev/acpica/include/acevents.h>
48
49 #define _COMPONENT          ACPI_HARDWARE
50         ACPI_MODULE_NAME    ("hwgpe")
51
52 /* Local prototypes */
53
54 static ACPI_STATUS
55 AcpiHwEnableWakeupGpeBlock (
56     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
57     ACPI_GPE_BLOCK_INFO     *GpeBlock,
58     void                    *Context);
59
60
61 /******************************************************************************
62  *
63  * FUNCTION:    AcpiHwGetGpeRegisterBit
64  *
65  * PARAMETERS:  GpeEventInfo        - Info block for the GPE
66  *              GpeRegisterInfo     - Info block for the GPE register
67  *
68  * RETURN:      Register mask with a one in the GPE bit position
69  *
70  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
71  *              correct position for the input GPE.
72  *
73  ******************************************************************************/
74
75 UINT32
76 AcpiHwGetGpeRegisterBit (
77     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
78     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo)
79 {
80
81     return ((UINT32) 1 <<
82         (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
83 }
84
85
86 /******************************************************************************
87  *
88  * FUNCTION:    AcpiHwLowSetGpe
89  *
90  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be disabled
91  *              Action              - Enable or disable
92  *
93  * RETURN:      Status
94  *
95  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
96  *
97  ******************************************************************************/
98
99 ACPI_STATUS
100 AcpiHwLowSetGpe (
101     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
102     UINT32                  Action)
103 {
104     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
105     ACPI_STATUS             Status;
106     UINT32                  EnableMask;
107     UINT32                  RegisterBit;
108
109
110     ACPI_FUNCTION_ENTRY ();
111
112
113     /* Get the info block for the entire GPE register */
114
115     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
116     if (!GpeRegisterInfo)
117     {
118         return (AE_NOT_EXIST);
119     }
120
121     /* Get current value of the enable register that contains this GPE */
122
123     Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress);
124     if (ACPI_FAILURE (Status))
125     {
126         return (Status);
127     }
128
129     /* Set or clear just the bit that corresponds to this GPE */
130
131     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
132     switch (Action)
133     {
134     case ACPI_GPE_CONDITIONAL_ENABLE:
135
136         /* Only enable if the EnableForRun bit is set */
137
138         if (!(RegisterBit & GpeRegisterInfo->EnableForRun))
139         {
140             return (AE_BAD_PARAMETER);
141         }
142
143         /*lint -fallthrough */
144
145     case ACPI_GPE_ENABLE:
146         ACPI_SET_BIT (EnableMask, RegisterBit);
147         break;
148
149     case ACPI_GPE_DISABLE:
150         ACPI_CLEAR_BIT (EnableMask, RegisterBit);
151         break;
152
153     default:
154         ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u\n", Action));
155         return (AE_BAD_PARAMETER);
156     }
157
158     /* Write the updated enable mask */
159
160     Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
161     return (Status);
162 }
163
164
165 /******************************************************************************
166  *
167  * FUNCTION:    AcpiHwClearGpe
168  *
169  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be cleared
170  *
171  * RETURN:      Status
172  *
173  * DESCRIPTION: Clear the status bit for a single GPE.
174  *
175  ******************************************************************************/
176
177 ACPI_STATUS
178 AcpiHwClearGpe (
179     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
180 {
181     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
182     ACPI_STATUS             Status;
183     UINT32                  RegisterBit;
184
185
186     ACPI_FUNCTION_ENTRY ();
187
188     /* Get the info block for the entire GPE register */
189
190     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
191     if (!GpeRegisterInfo)
192     {
193         return (AE_NOT_EXIST);
194     }
195
196     /*
197      * Write a one to the appropriate bit in the status register to
198      * clear this GPE.
199      */
200     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
201
202     Status = AcpiHwWrite (RegisterBit,
203                     &GpeRegisterInfo->StatusAddress);
204
205     return (Status);
206 }
207
208
209 /******************************************************************************
210  *
211  * FUNCTION:    AcpiHwGetGpeStatus
212  *
213  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to queried
214  *              EventStatus         - Where the GPE status is returned
215  *
216  * RETURN:      Status
217  *
218  * DESCRIPTION: Return the status of a single GPE.
219  *
220  ******************************************************************************/
221
222 ACPI_STATUS
223 AcpiHwGetGpeStatus (
224     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
225     ACPI_EVENT_STATUS       *EventStatus)
226 {
227     UINT32                  InByte;
228     UINT32                  RegisterBit;
229     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
230     ACPI_EVENT_STATUS       LocalEventStatus = 0;
231     ACPI_STATUS             Status;
232
233
234     ACPI_FUNCTION_ENTRY ();
235
236
237     if (!EventStatus)
238     {
239         return (AE_BAD_PARAMETER);
240     }
241
242     /* Get the info block for the entire GPE register */
243
244     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
245
246     /* Get the register bitmask for this GPE */
247
248     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
249
250     /* GPE currently enabled? (enabled for runtime?) */
251
252     if (RegisterBit & GpeRegisterInfo->EnableForRun)
253     {
254         LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
255     }
256
257     /* GPE enabled for wake? */
258
259     if (RegisterBit & GpeRegisterInfo->EnableForWake)
260     {
261         LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
262     }
263
264     /* GPE currently active (status bit == 1)? */
265
266     Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
267     if (ACPI_FAILURE (Status))
268     {
269         return (Status);
270     }
271
272     if (RegisterBit & InByte)
273     {
274         LocalEventStatus |= ACPI_EVENT_FLAG_SET;
275     }
276
277     /* Set return value */
278
279     (*EventStatus) = LocalEventStatus;
280     return (AE_OK);
281 }
282
283
284 /******************************************************************************
285  *
286  * FUNCTION:    AcpiHwDisableGpeBlock
287  *
288  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
289  *              GpeBlock            - Gpe Block info
290  *
291  * RETURN:      Status
292  *
293  * DESCRIPTION: Disable all GPEs within a single GPE block
294  *
295  ******************************************************************************/
296
297 ACPI_STATUS
298 AcpiHwDisableGpeBlock (
299     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
300     ACPI_GPE_BLOCK_INFO     *GpeBlock,
301     void                    *Context)
302 {
303     UINT32                  i;
304     ACPI_STATUS             Status;
305
306
307     /* Examine each GPE Register within the block */
308
309     for (i = 0; i < GpeBlock->RegisterCount; i++)
310     {
311         /* Disable all GPEs in this register */
312
313         Status = AcpiHwWrite (0x00, &GpeBlock->RegisterInfo[i].EnableAddress);
314         if (ACPI_FAILURE (Status))
315         {
316             return (Status);
317         }
318     }
319
320     return (AE_OK);
321 }
322
323
324 /******************************************************************************
325  *
326  * FUNCTION:    AcpiHwClearGpeBlock
327  *
328  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
329  *              GpeBlock            - Gpe Block info
330  *
331  * RETURN:      Status
332  *
333  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
334  *
335  ******************************************************************************/
336
337 ACPI_STATUS
338 AcpiHwClearGpeBlock (
339     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
340     ACPI_GPE_BLOCK_INFO     *GpeBlock,
341     void                    *Context)
342 {
343     UINT32                  i;
344     ACPI_STATUS             Status;
345
346
347     /* Examine each GPE Register within the block */
348
349     for (i = 0; i < GpeBlock->RegisterCount; i++)
350     {
351         /* Clear status on all GPEs in this register */
352
353         Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
354         if (ACPI_FAILURE (Status))
355         {
356             return (Status);
357         }
358     }
359
360     return (AE_OK);
361 }
362
363
364 /******************************************************************************
365  *
366  * FUNCTION:    AcpiHwEnableRuntimeGpeBlock
367  *
368  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
369  *              GpeBlock            - Gpe Block info
370  *
371  * RETURN:      Status
372  *
373  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
374  *              combination wake/run GPEs.
375  *
376  ******************************************************************************/
377
378 ACPI_STATUS
379 AcpiHwEnableRuntimeGpeBlock (
380     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
381     ACPI_GPE_BLOCK_INFO     *GpeBlock,
382     void                    *Context)
383 {
384     UINT32                  i;
385     ACPI_STATUS             Status;
386
387
388     /* NOTE: assumes that all GPEs are currently disabled */
389
390     /* Examine each GPE Register within the block */
391
392     for (i = 0; i < GpeBlock->RegisterCount; i++)
393     {
394         if (!GpeBlock->RegisterInfo[i].EnableForRun)
395         {
396             continue;
397         }
398
399         /* Enable all "runtime" GPEs in this register */
400
401         Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun,
402                     &GpeBlock->RegisterInfo[i].EnableAddress);
403         if (ACPI_FAILURE (Status))
404         {
405             return (Status);
406         }
407     }
408
409     return (AE_OK);
410 }
411
412
413 /******************************************************************************
414  *
415  * FUNCTION:    AcpiHwEnableWakeupGpeBlock
416  *
417  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
418  *              GpeBlock            - Gpe Block info
419  *
420  * RETURN:      Status
421  *
422  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
423  *              combination wake/run GPEs.
424  *
425  ******************************************************************************/
426
427 static ACPI_STATUS
428 AcpiHwEnableWakeupGpeBlock (
429     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
430     ACPI_GPE_BLOCK_INFO     *GpeBlock,
431     void                    *Context)
432 {
433     UINT32                  i;
434     ACPI_STATUS             Status;
435
436
437     /* Examine each GPE Register within the block */
438
439     for (i = 0; i < GpeBlock->RegisterCount; i++)
440     {
441         if (!GpeBlock->RegisterInfo[i].EnableForWake)
442         {
443             continue;
444         }
445
446         /* Enable all "wake" GPEs in this register */
447
448         Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake,
449                     &GpeBlock->RegisterInfo[i].EnableAddress);
450         if (ACPI_FAILURE (Status))
451         {
452             return (Status);
453         }
454     }
455
456     return (AE_OK);
457 }
458
459
460 /******************************************************************************
461  *
462  * FUNCTION:    AcpiHwDisableAllGpes
463  *
464  * PARAMETERS:  None
465  *
466  * RETURN:      Status
467  *
468  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
469  *
470  ******************************************************************************/
471
472 ACPI_STATUS
473 AcpiHwDisableAllGpes (
474     void)
475 {
476     ACPI_STATUS             Status;
477
478
479     ACPI_FUNCTION_TRACE (HwDisableAllGpes);
480
481
482     Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
483     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
484     return_ACPI_STATUS (Status);
485 }
486
487
488 /******************************************************************************
489  *
490  * FUNCTION:    AcpiHwEnableAllRuntimeGpes
491  *
492  * PARAMETERS:  None
493  *
494  * RETURN:      Status
495  *
496  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
497  *
498  ******************************************************************************/
499
500 ACPI_STATUS
501 AcpiHwEnableAllRuntimeGpes (
502     void)
503 {
504     ACPI_STATUS             Status;
505
506
507     ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
508
509
510     Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
511     return_ACPI_STATUS (Status);
512 }
513
514
515 /******************************************************************************
516  *
517  * FUNCTION:    AcpiHwEnableAllWakeupGpes
518  *
519  * PARAMETERS:  None
520  *
521  * RETURN:      Status
522  *
523  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
524  *
525  ******************************************************************************/
526
527 ACPI_STATUS
528 AcpiHwEnableAllWakeupGpes (
529     void)
530 {
531     ACPI_STATUS             Status;
532
533
534     ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
535
536
537     Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
538     return_ACPI_STATUS (Status);
539 }
540