xref: /freebsd/sys/contrib/dev/acpica/components/hardware/hwgpe.c (revision 87c1627502a5dde91e5284118eec8682b60f27a2)
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 <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/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         ACPI_SET_BIT (EnableMask, RegisterBit);
146         break;
147 
148     case ACPI_GPE_DISABLE:
149         ACPI_CLEAR_BIT (EnableMask, RegisterBit);
150         break;
151 
152     default:
153         ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u", Action));
154         return (AE_BAD_PARAMETER);
155     }
156 
157     /* Write the updated enable mask */
158 
159     Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
160     return (Status);
161 }
162 
163 
164 /******************************************************************************
165  *
166  * FUNCTION:    AcpiHwClearGpe
167  *
168  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be cleared
169  *
170  * RETURN:      Status
171  *
172  * DESCRIPTION: Clear the status bit for a single GPE.
173  *
174  ******************************************************************************/
175 
176 ACPI_STATUS
177 AcpiHwClearGpe (
178     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
179 {
180     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
181     ACPI_STATUS             Status;
182     UINT32                  RegisterBit;
183 
184 
185     ACPI_FUNCTION_ENTRY ();
186 
187     /* Get the info block for the entire GPE register */
188 
189     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
190     if (!GpeRegisterInfo)
191     {
192         return (AE_NOT_EXIST);
193     }
194 
195     /*
196      * Write a one to the appropriate bit in the status register to
197      * clear this GPE.
198      */
199     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
200 
201     Status = AcpiHwWrite (RegisterBit,
202                     &GpeRegisterInfo->StatusAddress);
203 
204     return (Status);
205 }
206 
207 
208 /******************************************************************************
209  *
210  * FUNCTION:    AcpiHwGetGpeStatus
211  *
212  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to queried
213  *              EventStatus         - Where the GPE status is returned
214  *
215  * RETURN:      Status
216  *
217  * DESCRIPTION: Return the status of a single GPE.
218  *
219  ******************************************************************************/
220 
221 ACPI_STATUS
222 AcpiHwGetGpeStatus (
223     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
224     ACPI_EVENT_STATUS       *EventStatus)
225 {
226     UINT32                  InByte;
227     UINT32                  RegisterBit;
228     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
229     ACPI_EVENT_STATUS       LocalEventStatus = 0;
230     ACPI_STATUS             Status;
231 
232 
233     ACPI_FUNCTION_ENTRY ();
234 
235 
236     if (!EventStatus)
237     {
238         return (AE_BAD_PARAMETER);
239     }
240 
241     /* Get the info block for the entire GPE register */
242 
243     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
244 
245     /* Get the register bitmask for this GPE */
246 
247     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
248 
249     /* GPE currently enabled? (enabled for runtime?) */
250 
251     if (RegisterBit & GpeRegisterInfo->EnableForRun)
252     {
253         LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
254     }
255 
256     /* GPE enabled for wake? */
257 
258     if (RegisterBit & GpeRegisterInfo->EnableForWake)
259     {
260         LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
261     }
262 
263     /* GPE currently active (status bit == 1)? */
264 
265     Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
266     if (ACPI_FAILURE (Status))
267     {
268         return (Status);
269     }
270 
271     if (RegisterBit & InByte)
272     {
273         LocalEventStatus |= ACPI_EVENT_FLAG_SET;
274     }
275 
276     /* Set return value */
277 
278     (*EventStatus) = LocalEventStatus;
279     return (AE_OK);
280 }
281 
282 
283 /******************************************************************************
284  *
285  * FUNCTION:    AcpiHwDisableGpeBlock
286  *
287  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
288  *              GpeBlock            - Gpe Block info
289  *
290  * RETURN:      Status
291  *
292  * DESCRIPTION: Disable all GPEs within a single GPE block
293  *
294  ******************************************************************************/
295 
296 ACPI_STATUS
297 AcpiHwDisableGpeBlock (
298     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
299     ACPI_GPE_BLOCK_INFO     *GpeBlock,
300     void                    *Context)
301 {
302     UINT32                  i;
303     ACPI_STATUS             Status;
304 
305 
306     /* Examine each GPE Register within the block */
307 
308     for (i = 0; i < GpeBlock->RegisterCount; i++)
309     {
310         /* Disable all GPEs in this register */
311 
312         Status = AcpiHwWrite (0x00, &GpeBlock->RegisterInfo[i].EnableAddress);
313         if (ACPI_FAILURE (Status))
314         {
315             return (Status);
316         }
317     }
318 
319     return (AE_OK);
320 }
321 
322 
323 /******************************************************************************
324  *
325  * FUNCTION:    AcpiHwClearGpeBlock
326  *
327  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
328  *              GpeBlock            - Gpe Block info
329  *
330  * RETURN:      Status
331  *
332  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
333  *
334  ******************************************************************************/
335 
336 ACPI_STATUS
337 AcpiHwClearGpeBlock (
338     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
339     ACPI_GPE_BLOCK_INFO     *GpeBlock,
340     void                    *Context)
341 {
342     UINT32                  i;
343     ACPI_STATUS             Status;
344 
345 
346     /* Examine each GPE Register within the block */
347 
348     for (i = 0; i < GpeBlock->RegisterCount; i++)
349     {
350         /* Clear status on all GPEs in this register */
351 
352         Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
353         if (ACPI_FAILURE (Status))
354         {
355             return (Status);
356         }
357     }
358 
359     return (AE_OK);
360 }
361 
362 
363 /******************************************************************************
364  *
365  * FUNCTION:    AcpiHwEnableRuntimeGpeBlock
366  *
367  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
368  *              GpeBlock            - Gpe Block info
369  *
370  * RETURN:      Status
371  *
372  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
373  *              combination wake/run GPEs.
374  *
375  ******************************************************************************/
376 
377 ACPI_STATUS
378 AcpiHwEnableRuntimeGpeBlock (
379     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
380     ACPI_GPE_BLOCK_INFO     *GpeBlock,
381     void                    *Context)
382 {
383     UINT32                  i;
384     ACPI_STATUS             Status;
385 
386 
387     /* NOTE: assumes that all GPEs are currently disabled */
388 
389     /* Examine each GPE Register within the block */
390 
391     for (i = 0; i < GpeBlock->RegisterCount; i++)
392     {
393         if (!GpeBlock->RegisterInfo[i].EnableForRun)
394         {
395             continue;
396         }
397 
398         /* Enable all "runtime" GPEs in this register */
399 
400         Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun,
401                     &GpeBlock->RegisterInfo[i].EnableAddress);
402         if (ACPI_FAILURE (Status))
403         {
404             return (Status);
405         }
406     }
407 
408     return (AE_OK);
409 }
410 
411 
412 /******************************************************************************
413  *
414  * FUNCTION:    AcpiHwEnableWakeupGpeBlock
415  *
416  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
417  *              GpeBlock            - Gpe Block info
418  *
419  * RETURN:      Status
420  *
421  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
422  *              combination wake/run GPEs.
423  *
424  ******************************************************************************/
425 
426 static ACPI_STATUS
427 AcpiHwEnableWakeupGpeBlock (
428     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
429     ACPI_GPE_BLOCK_INFO     *GpeBlock,
430     void                    *Context)
431 {
432     UINT32                  i;
433     ACPI_STATUS             Status;
434 
435 
436     /* Examine each GPE Register within the block */
437 
438     for (i = 0; i < GpeBlock->RegisterCount; i++)
439     {
440         if (!GpeBlock->RegisterInfo[i].EnableForWake)
441         {
442             continue;
443         }
444 
445         /* Enable all "wake" GPEs in this register */
446 
447         Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake,
448                     &GpeBlock->RegisterInfo[i].EnableAddress);
449         if (ACPI_FAILURE (Status))
450         {
451             return (Status);
452         }
453     }
454 
455     return (AE_OK);
456 }
457 
458 
459 /******************************************************************************
460  *
461  * FUNCTION:    AcpiHwDisableAllGpes
462  *
463  * PARAMETERS:  None
464  *
465  * RETURN:      Status
466  *
467  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
468  *
469  ******************************************************************************/
470 
471 ACPI_STATUS
472 AcpiHwDisableAllGpes (
473     void)
474 {
475     ACPI_STATUS             Status;
476 
477 
478     ACPI_FUNCTION_TRACE (HwDisableAllGpes);
479 
480 
481     Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
482     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
483     return_ACPI_STATUS (Status);
484 }
485 
486 
487 /******************************************************************************
488  *
489  * FUNCTION:    AcpiHwEnableAllRuntimeGpes
490  *
491  * PARAMETERS:  None
492  *
493  * RETURN:      Status
494  *
495  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
496  *
497  ******************************************************************************/
498 
499 ACPI_STATUS
500 AcpiHwEnableAllRuntimeGpes (
501     void)
502 {
503     ACPI_STATUS             Status;
504 
505 
506     ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
507 
508 
509     Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
510     return_ACPI_STATUS (Status);
511 }
512 
513 
514 /******************************************************************************
515  *
516  * FUNCTION:    AcpiHwEnableAllWakeupGpes
517  *
518  * PARAMETERS:  None
519  *
520  * RETURN:      Status
521  *
522  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
523  *
524  ******************************************************************************/
525 
526 ACPI_STATUS
527 AcpiHwEnableAllWakeupGpes (
528     void)
529 {
530     ACPI_STATUS             Status;
531 
532 
533     ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
534 
535 
536     Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
537     return_ACPI_STATUS (Status);
538 }
539 
540 #endif /* !ACPI_REDUCED_HARDWARE */
541