hwgpe.c revision 245582
191671Sume/******************************************************************************
291671Sume *
391671Sume * Module Name: hwgpe - Low level GPE enable/disable/clear functions
491671Sume *
591671Sume *****************************************************************************/
691671Sume
791671Sume/*
891671Sume * Copyright (C) 2000 - 2013, Intel Corp.
991671Sume * All rights reserved.
1091671Sume *
1191671Sume * Redistribution and use in source and binary forms, with or without
1291671Sume * modification, are permitted provided that the following conditions
13137784Sjhb * are met:
1491671Sume * 1. Redistributions of source code must retain the above copyright
1591671Sume *    notice, this list of conditions, and the following disclaimer,
1691671Sume *    without modification.
1791671Sume * 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
55static ACPI_STATUS
56AcpiHwEnableWakeupGpeBlock (
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
75UINT32
76AcpiHwGetGpeRegisterBit (
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
98ACPI_STATUS
99AcpiHwLowSetGpe (
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
176ACPI_STATUS
177AcpiHwClearGpe (
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
221ACPI_STATUS
222AcpiHwGetGpeStatus (
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
296ACPI_STATUS
297AcpiHwDisableGpeBlock (
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
336ACPI_STATUS
337AcpiHwClearGpeBlock (
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
377ACPI_STATUS
378AcpiHwEnableRuntimeGpeBlock (
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
426static ACPI_STATUS
427AcpiHwEnableWakeupGpeBlock (
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
471ACPI_STATUS
472AcpiHwDisableAllGpes (
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
499ACPI_STATUS
500AcpiHwEnableAllRuntimeGpes (
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
526ACPI_STATUS
527AcpiHwEnableAllWakeupGpes (
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