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