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