Merge branch 'vendor/GCC50'
[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 - 2015, 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 static ACPI_STATUS
62 AcpiHwGpeEnableWrite (
63     UINT8                   EnableMask,
64     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo);
65
66
67 /******************************************************************************
68  *
69  * FUNCTION:    AcpiHwGetGpeRegisterBit
70  *
71  * PARAMETERS:  GpeEventInfo        - Info block for the GPE
72  *
73  * RETURN:      Register mask with a one in the GPE bit position
74  *
75  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
76  *              correct position for the input GPE.
77  *
78  ******************************************************************************/
79
80 UINT32
81 AcpiHwGetGpeRegisterBit (
82     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
83 {
84
85     return ((UINT32) 1 <<
86         (GpeEventInfo->GpeNumber - GpeEventInfo->RegisterInfo->BaseGpeNumber));
87 }
88
89
90 /******************************************************************************
91  *
92  * FUNCTION:    AcpiHwLowSetGpe
93  *
94  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be disabled
95  *              Action              - Enable or disable
96  *
97  * RETURN:      Status
98  *
99  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
100  *
101  ******************************************************************************/
102
103 ACPI_STATUS
104 AcpiHwLowSetGpe (
105     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
106     UINT32                  Action)
107 {
108     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
109     ACPI_STATUS             Status;
110     UINT32                  EnableMask;
111     UINT32                  RegisterBit;
112
113
114     ACPI_FUNCTION_ENTRY ();
115
116
117     /* Get the info block for the entire GPE register */
118
119     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
120     if (!GpeRegisterInfo)
121     {
122         return (AE_NOT_EXIST);
123     }
124
125     /* Get current value of the enable register that contains this GPE */
126
127     Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress);
128     if (ACPI_FAILURE (Status))
129     {
130         return (Status);
131     }
132
133     /* Set or clear just the bit that corresponds to this GPE */
134
135     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
136     switch (Action & ~ACPI_GPE_SAVE_MASK)
137     {
138     case ACPI_GPE_CONDITIONAL_ENABLE:
139
140         /* Only enable if the corresponding EnableMask bit is set */
141
142         if (!(RegisterBit & GpeRegisterInfo->EnableMask))
143         {
144             return (AE_BAD_PARAMETER);
145         }
146
147         /*lint -fallthrough */
148
149     case ACPI_GPE_ENABLE:
150
151         ACPI_SET_BIT (EnableMask, RegisterBit);
152         break;
153
154     case ACPI_GPE_DISABLE:
155
156         ACPI_CLEAR_BIT (EnableMask, RegisterBit);
157         break;
158
159     default:
160
161         ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u", Action));
162         return (AE_BAD_PARAMETER);
163     }
164
165     /* Write the updated enable mask */
166
167     Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
168     if (ACPI_SUCCESS (Status) && (Action & ACPI_GPE_SAVE_MASK))
169     {
170         GpeRegisterInfo->EnableMask = (UINT8) EnableMask;
171     }
172     return (Status);
173 }
174
175
176 /******************************************************************************
177  *
178  * FUNCTION:    AcpiHwClearGpe
179  *
180  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be cleared
181  *
182  * RETURN:      Status
183  *
184  * DESCRIPTION: Clear the status bit for a single GPE.
185  *
186  ******************************************************************************/
187
188 ACPI_STATUS
189 AcpiHwClearGpe (
190     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
191 {
192     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
193     ACPI_STATUS             Status;
194     UINT32                  RegisterBit;
195
196
197     ACPI_FUNCTION_ENTRY ();
198
199     /* Get the info block for the entire GPE register */
200
201     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
202     if (!GpeRegisterInfo)
203     {
204         return (AE_NOT_EXIST);
205     }
206
207     /*
208      * Write a one to the appropriate bit in the status register to
209      * clear this GPE.
210      */
211     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
212
213     Status = AcpiHwWrite (RegisterBit,
214                     &GpeRegisterInfo->StatusAddress);
215
216     return (Status);
217 }
218
219
220 /******************************************************************************
221  *
222  * FUNCTION:    AcpiHwGetGpeStatus
223  *
224  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to queried
225  *              EventStatus         - Where the GPE status is returned
226  *
227  * RETURN:      Status
228  *
229  * DESCRIPTION: Return the status of a single GPE.
230  *
231  ******************************************************************************/
232
233 ACPI_STATUS
234 AcpiHwGetGpeStatus (
235     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
236     ACPI_EVENT_STATUS       *EventStatus)
237 {
238     UINT32                  InByte;
239     UINT32                  RegisterBit;
240     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
241     ACPI_EVENT_STATUS       LocalEventStatus = 0;
242     ACPI_STATUS             Status;
243
244
245     ACPI_FUNCTION_ENTRY ();
246
247
248     if (!EventStatus)
249     {
250         return (AE_BAD_PARAMETER);
251     }
252
253     /* GPE currently handled? */
254
255     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
256             ACPI_GPE_DISPATCH_NONE)
257     {
258         LocalEventStatus |= ACPI_EVENT_FLAG_HAS_HANDLER;
259     }
260
261     /* Get the info block for the entire GPE register */
262
263     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
264
265     /* Get the register bitmask for this GPE */
266
267     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
268
269     /* GPE currently enabled? (enabled for runtime?) */
270
271     if (RegisterBit & GpeRegisterInfo->EnableForRun)
272     {
273         LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
274     }
275
276     /* GPE enabled for wake? */
277
278     if (RegisterBit & GpeRegisterInfo->EnableForWake)
279     {
280         LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
281     }
282
283     /* GPE currently active (status bit == 1)? */
284
285     Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
286     if (ACPI_FAILURE (Status))
287     {
288         return (Status);
289     }
290
291     if (RegisterBit & InByte)
292     {
293         LocalEventStatus |= ACPI_EVENT_FLAG_SET;
294     }
295
296     /* Set return value */
297
298     (*EventStatus) = LocalEventStatus;
299     return (AE_OK);
300 }
301
302
303 /******************************************************************************
304  *
305  * FUNCTION:    AcpiHwGpeEnableWrite
306  *
307  * PARAMETERS:  EnableMask          - Bit mask to write to the GPE register
308  *              GpeRegisterInfo     - Gpe Register info
309  *
310  * RETURN:      Status
311  *
312  * DESCRIPTION: Write the enable mask byte to the given GPE register.
313  *
314  ******************************************************************************/
315
316 static ACPI_STATUS
317 AcpiHwGpeEnableWrite (
318     UINT8                   EnableMask,
319     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo)
320 {
321     ACPI_STATUS             Status;
322
323
324     Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
325     if (ACPI_SUCCESS (Status))
326     {
327         GpeRegisterInfo->EnableMask = EnableMask;
328     }
329
330     return (Status);
331 }
332
333
334 /******************************************************************************
335  *
336  * FUNCTION:    AcpiHwDisableGpeBlock
337  *
338  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
339  *              GpeBlock            - Gpe Block info
340  *
341  * RETURN:      Status
342  *
343  * DESCRIPTION: Disable all GPEs within a single GPE block
344  *
345  ******************************************************************************/
346
347 ACPI_STATUS
348 AcpiHwDisableGpeBlock (
349     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
350     ACPI_GPE_BLOCK_INFO     *GpeBlock,
351     void                    *Context)
352 {
353     UINT32                  i;
354     ACPI_STATUS             Status;
355
356
357     /* Examine each GPE Register within the block */
358
359     for (i = 0; i < GpeBlock->RegisterCount; i++)
360     {
361         /* Disable all GPEs in this register */
362
363         Status = AcpiHwGpeEnableWrite (0x00, &GpeBlock->RegisterInfo[i]);
364         if (ACPI_FAILURE (Status))
365         {
366             return (Status);
367         }
368     }
369
370     return (AE_OK);
371 }
372
373
374 /******************************************************************************
375  *
376  * FUNCTION:    AcpiHwClearGpeBlock
377  *
378  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
379  *              GpeBlock            - Gpe Block info
380  *
381  * RETURN:      Status
382  *
383  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
384  *
385  ******************************************************************************/
386
387 ACPI_STATUS
388 AcpiHwClearGpeBlock (
389     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
390     ACPI_GPE_BLOCK_INFO     *GpeBlock,
391     void                    *Context)
392 {
393     UINT32                  i;
394     ACPI_STATUS             Status;
395
396
397     /* Examine each GPE Register within the block */
398
399     for (i = 0; i < GpeBlock->RegisterCount; i++)
400     {
401         /* Clear status on all GPEs in this register */
402
403         Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
404         if (ACPI_FAILURE (Status))
405         {
406             return (Status);
407         }
408     }
409
410     return (AE_OK);
411 }
412
413
414 /******************************************************************************
415  *
416  * FUNCTION:    AcpiHwEnableRuntimeGpeBlock
417  *
418  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
419  *              GpeBlock            - Gpe Block info
420  *
421  * RETURN:      Status
422  *
423  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
424  *              combination wake/run GPEs.
425  *
426  ******************************************************************************/
427
428 ACPI_STATUS
429 AcpiHwEnableRuntimeGpeBlock (
430     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
431     ACPI_GPE_BLOCK_INFO     *GpeBlock,
432     void                    *Context)
433 {
434     UINT32                  i;
435     ACPI_STATUS             Status;
436     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
437
438
439     /* NOTE: assumes that all GPEs are currently disabled */
440
441     /* Examine each GPE Register within the block */
442
443     for (i = 0; i < GpeBlock->RegisterCount; i++)
444     {
445         GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
446         if (!GpeRegisterInfo->EnableForRun)
447         {
448             continue;
449         }
450
451         /* Enable all "runtime" GPEs in this register */
452
453         Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForRun,
454                     GpeRegisterInfo);
455         if (ACPI_FAILURE (Status))
456         {
457             return (Status);
458         }
459     }
460
461     return (AE_OK);
462 }
463
464
465 /******************************************************************************
466  *
467  * FUNCTION:    AcpiHwEnableWakeupGpeBlock
468  *
469  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
470  *              GpeBlock            - Gpe Block info
471  *
472  * RETURN:      Status
473  *
474  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
475  *              combination wake/run GPEs.
476  *
477  ******************************************************************************/
478
479 static ACPI_STATUS
480 AcpiHwEnableWakeupGpeBlock (
481     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
482     ACPI_GPE_BLOCK_INFO     *GpeBlock,
483     void                    *Context)
484 {
485     UINT32                  i;
486     ACPI_STATUS             Status;
487     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
488
489
490     /* Examine each GPE Register within the block */
491
492     for (i = 0; i < GpeBlock->RegisterCount; i++)
493     {
494         GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
495
496         /*
497          * Enable all "wake" GPEs in this register and disable the
498          * remaining ones.
499          */
500         Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForWake,
501                     GpeRegisterInfo);
502         if (ACPI_FAILURE (Status))
503         {
504             return (Status);
505         }
506     }
507
508     return (AE_OK);
509 }
510
511
512 /******************************************************************************
513  *
514  * FUNCTION:    AcpiHwDisableAllGpes
515  *
516  * PARAMETERS:  None
517  *
518  * RETURN:      Status
519  *
520  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
521  *
522  ******************************************************************************/
523
524 ACPI_STATUS
525 AcpiHwDisableAllGpes (
526     void)
527 {
528     ACPI_STATUS             Status;
529
530
531     ACPI_FUNCTION_TRACE (HwDisableAllGpes);
532
533
534     Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
535     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
536     return_ACPI_STATUS (Status);
537 }
538
539
540 /******************************************************************************
541  *
542  * FUNCTION:    AcpiHwEnableAllRuntimeGpes
543  *
544  * PARAMETERS:  None
545  *
546  * RETURN:      Status
547  *
548  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
549  *
550  ******************************************************************************/
551
552 ACPI_STATUS
553 AcpiHwEnableAllRuntimeGpes (
554     void)
555 {
556     ACPI_STATUS             Status;
557
558
559     ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
560
561
562     Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
563     return_ACPI_STATUS (Status);
564 }
565
566
567 /******************************************************************************
568  *
569  * FUNCTION:    AcpiHwEnableAllWakeupGpes
570  *
571  * PARAMETERS:  None
572  *
573  * RETURN:      Status
574  *
575  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
576  *
577  ******************************************************************************/
578
579 ACPI_STATUS
580 AcpiHwEnableAllWakeupGpes (
581     void)
582 {
583     ACPI_STATUS             Status;
584
585
586     ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
587
588
589     Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
590     return_ACPI_STATUS (Status);
591 }
592
593 #endif /* !ACPI_REDUCED_HARDWARE */