Merge branch 'vendor/OPENSSL'
[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 enabled (enable bit == 1)? */
284
285     Status = AcpiHwRead (&InByte, &GpeRegisterInfo->EnableAddress);
286     if (ACPI_FAILURE (Status))
287     {
288         return (Status);
289     }
290
291     if (RegisterBit & InByte)
292     {
293         LocalEventStatus |= ACPI_EVENT_FLAG_ENABLE_SET;
294     }
295
296     /* GPE currently active (status bit == 1)? */
297
298     Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
299     if (ACPI_FAILURE (Status))
300     {
301         return (Status);
302     }
303
304     if (RegisterBit & InByte)
305     {
306         LocalEventStatus |= ACPI_EVENT_FLAG_STATUS_SET;
307     }
308
309     /* Set return value */
310
311     (*EventStatus) = LocalEventStatus;
312     return (AE_OK);
313 }
314
315
316 /******************************************************************************
317  *
318  * FUNCTION:    AcpiHwGpeEnableWrite
319  *
320  * PARAMETERS:  EnableMask          - Bit mask to write to the GPE register
321  *              GpeRegisterInfo     - Gpe Register info
322  *
323  * RETURN:      Status
324  *
325  * DESCRIPTION: Write the enable mask byte to the given GPE register.
326  *
327  ******************************************************************************/
328
329 static ACPI_STATUS
330 AcpiHwGpeEnableWrite (
331     UINT8                   EnableMask,
332     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo)
333 {
334     ACPI_STATUS             Status;
335
336
337     Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
338     if (ACPI_SUCCESS (Status))
339     {
340         GpeRegisterInfo->EnableMask = EnableMask;
341     }
342
343     return (Status);
344 }
345
346
347 /******************************************************************************
348  *
349  * FUNCTION:    AcpiHwDisableGpeBlock
350  *
351  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
352  *              GpeBlock            - Gpe Block info
353  *
354  * RETURN:      Status
355  *
356  * DESCRIPTION: Disable all GPEs within a single GPE block
357  *
358  ******************************************************************************/
359
360 ACPI_STATUS
361 AcpiHwDisableGpeBlock (
362     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
363     ACPI_GPE_BLOCK_INFO     *GpeBlock,
364     void                    *Context)
365 {
366     UINT32                  i;
367     ACPI_STATUS             Status;
368
369
370     /* Examine each GPE Register within the block */
371
372     for (i = 0; i < GpeBlock->RegisterCount; i++)
373     {
374         /* Disable all GPEs in this register */
375
376         Status = AcpiHwGpeEnableWrite (0x00, &GpeBlock->RegisterInfo[i]);
377         if (ACPI_FAILURE (Status))
378         {
379             return (Status);
380         }
381     }
382
383     return (AE_OK);
384 }
385
386
387 /******************************************************************************
388  *
389  * FUNCTION:    AcpiHwClearGpeBlock
390  *
391  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
392  *              GpeBlock            - Gpe Block info
393  *
394  * RETURN:      Status
395  *
396  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
397  *
398  ******************************************************************************/
399
400 ACPI_STATUS
401 AcpiHwClearGpeBlock (
402     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
403     ACPI_GPE_BLOCK_INFO     *GpeBlock,
404     void                    *Context)
405 {
406     UINT32                  i;
407     ACPI_STATUS             Status;
408
409
410     /* Examine each GPE Register within the block */
411
412     for (i = 0; i < GpeBlock->RegisterCount; i++)
413     {
414         /* Clear status on all GPEs in this register */
415
416         Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
417         if (ACPI_FAILURE (Status))
418         {
419             return (Status);
420         }
421     }
422
423     return (AE_OK);
424 }
425
426
427 /******************************************************************************
428  *
429  * FUNCTION:    AcpiHwEnableRuntimeGpeBlock
430  *
431  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
432  *              GpeBlock            - Gpe Block info
433  *
434  * RETURN:      Status
435  *
436  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
437  *              combination wake/run GPEs.
438  *
439  ******************************************************************************/
440
441 ACPI_STATUS
442 AcpiHwEnableRuntimeGpeBlock (
443     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
444     ACPI_GPE_BLOCK_INFO     *GpeBlock,
445     void                    *Context)
446 {
447     UINT32                  i;
448     ACPI_STATUS             Status;
449     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
450
451
452     /* NOTE: assumes that all GPEs are currently disabled */
453
454     /* Examine each GPE Register within the block */
455
456     for (i = 0; i < GpeBlock->RegisterCount; i++)
457     {
458         GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
459         if (!GpeRegisterInfo->EnableForRun)
460         {
461             continue;
462         }
463
464         /* Enable all "runtime" GPEs in this register */
465
466         Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForRun,
467                     GpeRegisterInfo);
468         if (ACPI_FAILURE (Status))
469         {
470             return (Status);
471         }
472     }
473
474     return (AE_OK);
475 }
476
477
478 /******************************************************************************
479  *
480  * FUNCTION:    AcpiHwEnableWakeupGpeBlock
481  *
482  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
483  *              GpeBlock            - Gpe Block info
484  *
485  * RETURN:      Status
486  *
487  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
488  *              combination wake/run GPEs.
489  *
490  ******************************************************************************/
491
492 static ACPI_STATUS
493 AcpiHwEnableWakeupGpeBlock (
494     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
495     ACPI_GPE_BLOCK_INFO     *GpeBlock,
496     void                    *Context)
497 {
498     UINT32                  i;
499     ACPI_STATUS             Status;
500     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
501
502
503     /* Examine each GPE Register within the block */
504
505     for (i = 0; i < GpeBlock->RegisterCount; i++)
506     {
507         GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
508
509         /*
510          * Enable all "wake" GPEs in this register and disable the
511          * remaining ones.
512          */
513         Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForWake,
514                     GpeRegisterInfo);
515         if (ACPI_FAILURE (Status))
516         {
517             return (Status);
518         }
519     }
520
521     return (AE_OK);
522 }
523
524
525 /******************************************************************************
526  *
527  * FUNCTION:    AcpiHwDisableAllGpes
528  *
529  * PARAMETERS:  None
530  *
531  * RETURN:      Status
532  *
533  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
534  *
535  ******************************************************************************/
536
537 ACPI_STATUS
538 AcpiHwDisableAllGpes (
539     void)
540 {
541     ACPI_STATUS             Status;
542
543
544     ACPI_FUNCTION_TRACE (HwDisableAllGpes);
545
546
547     Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
548     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
549     return_ACPI_STATUS (Status);
550 }
551
552
553 /******************************************************************************
554  *
555  * FUNCTION:    AcpiHwEnableAllRuntimeGpes
556  *
557  * PARAMETERS:  None
558  *
559  * RETURN:      Status
560  *
561  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
562  *
563  ******************************************************************************/
564
565 ACPI_STATUS
566 AcpiHwEnableAllRuntimeGpes (
567     void)
568 {
569     ACPI_STATUS             Status;
570
571
572     ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
573
574
575     Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
576     return_ACPI_STATUS (Status);
577 }
578
579
580 /******************************************************************************
581  *
582  * FUNCTION:    AcpiHwEnableAllWakeupGpes
583  *
584  * PARAMETERS:  None
585  *
586  * RETURN:      Status
587  *
588  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
589  *
590  ******************************************************************************/
591
592 ACPI_STATUS
593 AcpiHwEnableAllWakeupGpes (
594     void)
595 {
596     ACPI_STATUS             Status;
597
598
599     ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
600
601
602     Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
603     return_ACPI_STATUS (Status);
604 }
605
606 #endif /* !ACPI_REDUCED_HARDWARE */