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