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