1216331Sjkim/******************************************************************************
2216331Sjkim *
3216331Sjkim * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4216331Sjkim *
5216331Sjkim *****************************************************************************/
6216331Sjkim
7217365Sjkim/*
8217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp.
9216331Sjkim * All rights reserved.
10216331Sjkim *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25216331Sjkim *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29216331Sjkim *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43216331Sjkim
44216331Sjkim
45216331Sjkim#define __EVXFGPE_C__
46216331Sjkim
47216471Sjkim#include <contrib/dev/acpica/include/acpi.h>
48216471Sjkim#include <contrib/dev/acpica/include/accommon.h>
49216471Sjkim#include <contrib/dev/acpica/include/acevents.h>
50216471Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
51216331Sjkim
52216331Sjkim#define _COMPONENT          ACPI_EVENTS
53216331Sjkim        ACPI_MODULE_NAME    ("evxfgpe")
54216331Sjkim
55216331Sjkim
56216331Sjkim/*******************************************************************************
57216331Sjkim *
58216331Sjkim * FUNCTION:    AcpiUpdateAllGpes
59216331Sjkim *
60216331Sjkim * PARAMETERS:  None
61216331Sjkim *
62216331Sjkim * RETURN:      Status
63216331Sjkim *
64216331Sjkim * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
65216331Sjkim *              associated _Lxx or _Exx methods and are not pointed to by any
66216331Sjkim *              device _PRW methods (this indicates that these GPEs are
67216331Sjkim *              generally intended for system or device wakeup. Such GPEs
68216331Sjkim *              have to be enabled directly when the devices whose _PRW
69216331Sjkim *              methods point to them are set up for wakeup signaling.)
70216331Sjkim *
71216331Sjkim * NOTE: Should be called after any GPEs are added to the system. Primarily,
72216331Sjkim * after the system _PRW methods have been run, but also after a GPE Block
73216331Sjkim * Device has been added or if any new GPE methods have been added via a
74216331Sjkim * dynamic table load.
75216331Sjkim *
76216331Sjkim ******************************************************************************/
77216331Sjkim
78216331SjkimACPI_STATUS
79216331SjkimAcpiUpdateAllGpes (
80216331Sjkim    void)
81216331Sjkim{
82216331Sjkim    ACPI_STATUS             Status;
83216331Sjkim
84216331Sjkim
85216331Sjkim    ACPI_FUNCTION_TRACE (AcpiUpdateGpes);
86216331Sjkim
87216331Sjkim
88216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
89216331Sjkim    if (ACPI_FAILURE (Status))
90216331Sjkim    {
91216331Sjkim        return_ACPI_STATUS (Status);
92216331Sjkim    }
93216331Sjkim
94216331Sjkim    if (AcpiGbl_AllGpesInitialized)
95216331Sjkim    {
96216331Sjkim        goto UnlockAndExit;
97216331Sjkim    }
98216331Sjkim
99216331Sjkim    Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL);
100216331Sjkim    if (ACPI_SUCCESS (Status))
101216331Sjkim    {
102216331Sjkim        AcpiGbl_AllGpesInitialized = TRUE;
103216331Sjkim    }
104216331Sjkim
105216331SjkimUnlockAndExit:
106216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
107216331Sjkim    return_ACPI_STATUS (Status);
108216331Sjkim}
109216331Sjkim
110216331SjkimACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
111216331Sjkim
112216331Sjkim
113216331Sjkim/*******************************************************************************
114216331Sjkim *
115216331Sjkim * FUNCTION:    AcpiEnableGpe
116216331Sjkim *
117216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
118216331Sjkim *              GpeNumber           - GPE level within the GPE block
119216331Sjkim *
120216331Sjkim * RETURN:      Status
121216331Sjkim *
122216331Sjkim * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
123216331Sjkim *              hardware-enabled.
124216331Sjkim *
125216331Sjkim ******************************************************************************/
126216331Sjkim
127216331SjkimACPI_STATUS
128216331SjkimAcpiEnableGpe (
129216331Sjkim    ACPI_HANDLE             GpeDevice,
130216331Sjkim    UINT32                  GpeNumber)
131216331Sjkim{
132216331Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
133216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
134216331Sjkim    ACPI_CPU_FLAGS          Flags;
135216331Sjkim
136216331Sjkim
137216331Sjkim    ACPI_FUNCTION_TRACE (AcpiEnableGpe);
138216331Sjkim
139216331Sjkim
140216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
141216331Sjkim
142216331Sjkim    /* Ensure that we have a valid GPE number */
143216331Sjkim
144216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
145216331Sjkim    if (GpeEventInfo)
146216331Sjkim    {
147216331Sjkim        Status = AcpiEvAddGpeReference (GpeEventInfo);
148216331Sjkim    }
149216331Sjkim
150216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
151216331Sjkim    return_ACPI_STATUS (Status);
152216331Sjkim}
153216331Sjkim
154216331SjkimACPI_EXPORT_SYMBOL (AcpiEnableGpe)
155216331Sjkim
156216331Sjkim
157216331Sjkim/*******************************************************************************
158216331Sjkim *
159216331Sjkim * FUNCTION:    AcpiDisableGpe
160216331Sjkim *
161216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
162216331Sjkim *              GpeNumber           - GPE level within the GPE block
163216331Sjkim *
164216331Sjkim * RETURN:      Status
165216331Sjkim *
166216331Sjkim * DESCRIPTION: Remove a reference to a GPE. When the last reference is
167216331Sjkim *              removed, only then is the GPE disabled (for runtime GPEs), or
168216331Sjkim *              the GPE mask bit disabled (for wake GPEs)
169216331Sjkim *
170216331Sjkim ******************************************************************************/
171216331Sjkim
172216331SjkimACPI_STATUS
173216331SjkimAcpiDisableGpe (
174216331Sjkim    ACPI_HANDLE             GpeDevice,
175216331Sjkim    UINT32                  GpeNumber)
176216331Sjkim{
177216331Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
178216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
179216331Sjkim    ACPI_CPU_FLAGS          Flags;
180216331Sjkim
181216331Sjkim
182216331Sjkim    ACPI_FUNCTION_TRACE (AcpiDisableGpe);
183216331Sjkim
184216331Sjkim
185216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
186216331Sjkim
187216331Sjkim    /* Ensure that we have a valid GPE number */
188216331Sjkim
189216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
190216331Sjkim    if (GpeEventInfo)
191216331Sjkim    {
192216331Sjkim        Status = AcpiEvRemoveGpeReference (GpeEventInfo);
193216331Sjkim    }
194216331Sjkim
195216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
196216331Sjkim    return_ACPI_STATUS (Status);
197216331Sjkim}
198216331Sjkim
199216331SjkimACPI_EXPORT_SYMBOL (AcpiDisableGpe)
200216331Sjkim
201216331Sjkim
202216331Sjkim/*******************************************************************************
203216331Sjkim *
204216331Sjkim * FUNCTION:    AcpiSetGpe
205216331Sjkim *
206216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
207216331Sjkim *              GpeNumber           - GPE level within the GPE block
208216331Sjkim *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
209216331Sjkim *
210216331Sjkim * RETURN:      Status
211216331Sjkim *
212216331Sjkim * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
213216331Sjkim *              the reference count mechanism used in the AcpiEnableGpe and
214216331Sjkim *              AcpiDisableGpe interfaces -- and should be used with care.
215216331Sjkim *
216216331Sjkim * Note: Typically used to disable a runtime GPE for short period of time,
217216331Sjkim * then re-enable it, without disturbing the existing reference counts. This
218216331Sjkim * is useful, for example, in the Embedded Controller (EC) driver.
219216331Sjkim *
220216331Sjkim ******************************************************************************/
221216331Sjkim
222216331SjkimACPI_STATUS
223216331SjkimAcpiSetGpe (
224216331Sjkim    ACPI_HANDLE             GpeDevice,
225216331Sjkim    UINT32                  GpeNumber,
226216331Sjkim    UINT8                   Action)
227216331Sjkim{
228216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
229216331Sjkim    ACPI_STATUS             Status;
230216331Sjkim    ACPI_CPU_FLAGS          Flags;
231216331Sjkim
232216331Sjkim
233216331Sjkim    ACPI_FUNCTION_TRACE (AcpiSetGpe);
234216331Sjkim
235216331Sjkim
236216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
237216331Sjkim
238216331Sjkim    /* Ensure that we have a valid GPE number */
239216331Sjkim
240216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
241216331Sjkim    if (!GpeEventInfo)
242216331Sjkim    {
243216331Sjkim        Status = AE_BAD_PARAMETER;
244216331Sjkim        goto UnlockAndExit;
245216331Sjkim    }
246216331Sjkim
247216331Sjkim    /* Perform the action */
248216331Sjkim
249216331Sjkim    switch (Action)
250216331Sjkim    {
251216331Sjkim    case ACPI_GPE_ENABLE:
252216331Sjkim        Status = AcpiEvEnableGpe (GpeEventInfo);
253216331Sjkim        break;
254216331Sjkim
255216331Sjkim    case ACPI_GPE_DISABLE:
256216331Sjkim        Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
257216331Sjkim        break;
258216331Sjkim
259216331Sjkim    default:
260216331Sjkim        Status = AE_BAD_PARAMETER;
261216331Sjkim        break;
262216331Sjkim    }
263216331Sjkim
264216331SjkimUnlockAndExit:
265216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
266216331Sjkim    return_ACPI_STATUS (Status);
267216331Sjkim}
268216331Sjkim
269216331SjkimACPI_EXPORT_SYMBOL (AcpiSetGpe)
270216331Sjkim
271216331Sjkim
272216331Sjkim/*******************************************************************************
273216331Sjkim *
274216331Sjkim * FUNCTION:    AcpiSetupGpeForWake
275216331Sjkim *
276216331Sjkim * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
277216331Sjkim *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
278216331Sjkim *              GpeNumber           - GPE level within the GPE block
279216331Sjkim *
280216331Sjkim * RETURN:      Status
281216331Sjkim *
282216331Sjkim * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
283216331Sjkim *              interface is intended to be used as the host executes the
284216331Sjkim *              _PRW methods (Power Resources for Wake) in the system tables.
285216331Sjkim *              Each _PRW appears under a Device Object (The WakeDevice), and
286216331Sjkim *              contains the info for the wake GPE associated with the
287216331Sjkim *              WakeDevice.
288216331Sjkim *
289216331Sjkim ******************************************************************************/
290216331Sjkim
291216331SjkimACPI_STATUS
292216331SjkimAcpiSetupGpeForWake (
293216331Sjkim    ACPI_HANDLE             WakeDevice,
294216331Sjkim    ACPI_HANDLE             GpeDevice,
295216331Sjkim    UINT32                  GpeNumber)
296216331Sjkim{
297216331Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
298216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
299216331Sjkim    ACPI_NAMESPACE_NODE     *DeviceNode;
300216331Sjkim    ACPI_CPU_FLAGS          Flags;
301216331Sjkim
302216331Sjkim
303216331Sjkim    ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
304216331Sjkim
305216331Sjkim
306216331Sjkim    /* Parameter Validation */
307216331Sjkim
308216331Sjkim    if (!WakeDevice)
309216331Sjkim    {
310216331Sjkim        /*
311216331Sjkim         * By forcing WakeDevice to be valid, we automatically enable the
312216331Sjkim         * implicit notify feature on all hosts.
313216331Sjkim         */
314216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
315216331Sjkim    }
316216331Sjkim
317219707Sjkim    /* Handle root object case */
318219707Sjkim
319219707Sjkim    if (WakeDevice == ACPI_ROOT_OBJECT)
320219707Sjkim    {
321219707Sjkim        DeviceNode = AcpiGbl_RootNode;
322219707Sjkim    }
323219707Sjkim    else
324219707Sjkim    {
325219707Sjkim        DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
326219707Sjkim    }
327219707Sjkim
328216331Sjkim    /* Validate WakeDevice is of type Device */
329216331Sjkim
330216331Sjkim    if (DeviceNode->Type != ACPI_TYPE_DEVICE)
331216331Sjkim    {
332216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
333216331Sjkim    }
334216331Sjkim
335216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
336216331Sjkim
337216331Sjkim    /* Ensure that we have a valid GPE number */
338216331Sjkim
339216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
340216331Sjkim    if (GpeEventInfo)
341216331Sjkim    {
342216331Sjkim        /*
343216331Sjkim         * If there is no method or handler for this GPE, then the
344216331Sjkim         * WakeDevice will be notified whenever this GPE fires (aka
345216331Sjkim         * "implicit notify") Note: The GPE is assumed to be
346216331Sjkim         * level-triggered (for windows compatibility).
347216331Sjkim         */
348216331Sjkim        if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
349216331Sjkim                ACPI_GPE_DISPATCH_NONE)
350216331Sjkim        {
351216331Sjkim            GpeEventInfo->Flags =
352216331Sjkim                (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
353216331Sjkim            GpeEventInfo->Dispatch.DeviceNode = DeviceNode;
354216331Sjkim        }
355216331Sjkim
356216331Sjkim        GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
357216331Sjkim        Status = AE_OK;
358216331Sjkim    }
359216331Sjkim
360216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
361216331Sjkim    return_ACPI_STATUS (Status);
362216331Sjkim}
363216331Sjkim
364216331SjkimACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
365216331Sjkim
366216331Sjkim
367216331Sjkim/*******************************************************************************
368216331Sjkim *
369216331Sjkim * FUNCTION:    AcpiSetGpeWakeMask
370216331Sjkim *
371216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
372216331Sjkim *              GpeNumber           - GPE level within the GPE block
373216331Sjkim *              Action              - Enable or Disable
374216331Sjkim *
375216331Sjkim * RETURN:      Status
376216331Sjkim *
377216331Sjkim * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
378216331Sjkim *              already be marked as a WAKE GPE.
379216331Sjkim *
380216331Sjkim ******************************************************************************/
381216331Sjkim
382216331SjkimACPI_STATUS
383216331SjkimAcpiSetGpeWakeMask (
384216331Sjkim    ACPI_HANDLE             GpeDevice,
385216331Sjkim    UINT32                  GpeNumber,
386216331Sjkim    UINT8                   Action)
387216331Sjkim{
388216331Sjkim    ACPI_STATUS             Status = AE_OK;
389216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
390216331Sjkim    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
391216331Sjkim    ACPI_CPU_FLAGS          Flags;
392216331Sjkim    UINT32                  RegisterBit;
393216331Sjkim
394216331Sjkim
395216331Sjkim    ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
396216331Sjkim
397216331Sjkim
398216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
399216331Sjkim
400216331Sjkim    /*
401216331Sjkim     * Ensure that we have a valid GPE number and that this GPE is in
402216331Sjkim     * fact a wake GPE
403216331Sjkim     */
404216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
405216331Sjkim    if (!GpeEventInfo)
406216331Sjkim    {
407216331Sjkim        Status = AE_BAD_PARAMETER;
408216331Sjkim        goto UnlockAndExit;
409216331Sjkim    }
410216331Sjkim
411216331Sjkim    if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
412216331Sjkim    {
413216331Sjkim        Status = AE_TYPE;
414216331Sjkim        goto UnlockAndExit;
415216331Sjkim    }
416216331Sjkim
417216331Sjkim    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
418216331Sjkim    if (!GpeRegisterInfo)
419216331Sjkim    {
420216331Sjkim        Status = AE_NOT_EXIST;
421216331Sjkim        goto UnlockAndExit;
422216331Sjkim    }
423216331Sjkim
424216331Sjkim    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
425216331Sjkim
426216331Sjkim    /* Perform the action */
427216331Sjkim
428216331Sjkim    switch (Action)
429216331Sjkim    {
430216331Sjkim    case ACPI_GPE_ENABLE:
431216331Sjkim        ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
432216331Sjkim        break;
433216331Sjkim
434216331Sjkim    case ACPI_GPE_DISABLE:
435216331Sjkim        ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
436216331Sjkim        break;
437216331Sjkim
438216331Sjkim    default:
439216331Sjkim        ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
440216331Sjkim        Status = AE_BAD_PARAMETER;
441216331Sjkim        break;
442216331Sjkim    }
443216331Sjkim
444216331SjkimUnlockAndExit:
445216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
446216331Sjkim    return_ACPI_STATUS (Status);
447216331Sjkim}
448216331Sjkim
449216331SjkimACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
450216331Sjkim
451216331Sjkim
452216331Sjkim/*******************************************************************************
453216331Sjkim *
454216331Sjkim * FUNCTION:    AcpiClearGpe
455216331Sjkim *
456216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
457216331Sjkim *              GpeNumber           - GPE level within the GPE block
458216331Sjkim *
459216331Sjkim * RETURN:      Status
460216331Sjkim *
461216331Sjkim * DESCRIPTION: Clear an ACPI event (general purpose)
462216331Sjkim *
463216331Sjkim ******************************************************************************/
464216331Sjkim
465216331SjkimACPI_STATUS
466216331SjkimAcpiClearGpe (
467216331Sjkim    ACPI_HANDLE             GpeDevice,
468216331Sjkim    UINT32                  GpeNumber)
469216331Sjkim{
470216331Sjkim    ACPI_STATUS             Status = AE_OK;
471216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
472216331Sjkim    ACPI_CPU_FLAGS          Flags;
473216331Sjkim
474216331Sjkim
475216331Sjkim    ACPI_FUNCTION_TRACE (AcpiClearGpe);
476216331Sjkim
477216331Sjkim
478216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
479216331Sjkim
480216331Sjkim    /* Ensure that we have a valid GPE number */
481216331Sjkim
482216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
483216331Sjkim    if (!GpeEventInfo)
484216331Sjkim    {
485216331Sjkim        Status = AE_BAD_PARAMETER;
486216331Sjkim        goto UnlockAndExit;
487216331Sjkim    }
488216331Sjkim
489216331Sjkim    Status = AcpiHwClearGpe (GpeEventInfo);
490216331Sjkim
491216331SjkimUnlockAndExit:
492216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
493216331Sjkim    return_ACPI_STATUS (Status);
494216331Sjkim}
495216331Sjkim
496216331SjkimACPI_EXPORT_SYMBOL (AcpiClearGpe)
497216331Sjkim
498216331Sjkim
499216331Sjkim/*******************************************************************************
500216331Sjkim *
501216331Sjkim * FUNCTION:    AcpiGetGpeStatus
502216331Sjkim *
503216331Sjkim * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
504216331Sjkim *              GpeNumber           - GPE level within the GPE block
505216331Sjkim *              EventStatus         - Where the current status of the event
506216331Sjkim *                                    will be returned
507216331Sjkim *
508216331Sjkim * RETURN:      Status
509216331Sjkim *
510216331Sjkim * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
511216331Sjkim *
512216331Sjkim ******************************************************************************/
513216331Sjkim
514216331SjkimACPI_STATUS
515216331SjkimAcpiGetGpeStatus (
516216331Sjkim    ACPI_HANDLE             GpeDevice,
517216331Sjkim    UINT32                  GpeNumber,
518216331Sjkim    ACPI_EVENT_STATUS       *EventStatus)
519216331Sjkim{
520216331Sjkim    ACPI_STATUS             Status = AE_OK;
521216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
522216331Sjkim    ACPI_CPU_FLAGS          Flags;
523216331Sjkim
524216331Sjkim
525216331Sjkim    ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
526216331Sjkim
527216331Sjkim
528216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
529216331Sjkim
530216331Sjkim    /* Ensure that we have a valid GPE number */
531216331Sjkim
532216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
533216331Sjkim    if (!GpeEventInfo)
534216331Sjkim    {
535216331Sjkim        Status = AE_BAD_PARAMETER;
536216331Sjkim        goto UnlockAndExit;
537216331Sjkim    }
538216331Sjkim
539216331Sjkim    /* Obtain status on the requested GPE number */
540216331Sjkim
541216331Sjkim    Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
542216331Sjkim
543216331SjkimUnlockAndExit:
544216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
545216331Sjkim    return_ACPI_STATUS (Status);
546216331Sjkim}
547216331Sjkim
548216331SjkimACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
549216331Sjkim
550216331Sjkim
551216331Sjkim/*******************************************************************************
552216331Sjkim *
553216331Sjkim * FUNCTION:    AcpiFinishGpe
554216331Sjkim *
555216331Sjkim * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
556216331Sjkim *                                    (NULL for FADT defined GPEs)
557216331Sjkim *              GpeNumber           - GPE level within the GPE block
558216331Sjkim *
559216331Sjkim * RETURN:      Status
560216331Sjkim *
561216331Sjkim * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
562216331Sjkim *              processing. Intended for use by asynchronous host-installed
563216331Sjkim *              GPE handlers. The GPE is only reenabled if the EnableForRun bit
564216331Sjkim *              is set in the GPE info.
565216331Sjkim *
566216331Sjkim ******************************************************************************/
567216331Sjkim
568216331SjkimACPI_STATUS
569216331SjkimAcpiFinishGpe (
570216331Sjkim    ACPI_HANDLE             GpeDevice,
571216331Sjkim    UINT32                  GpeNumber)
572216331Sjkim{
573216331Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
574216331Sjkim    ACPI_STATUS             Status;
575216331Sjkim    ACPI_CPU_FLAGS          Flags;
576216331Sjkim
577216331Sjkim
578216331Sjkim    ACPI_FUNCTION_TRACE (AcpiFinishGpe);
579216331Sjkim
580216331Sjkim
581216331Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
582216331Sjkim
583216331Sjkim    /* Ensure that we have a valid GPE number */
584216331Sjkim
585216331Sjkim    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
586216331Sjkim    if (!GpeEventInfo)
587216331Sjkim    {
588216331Sjkim        Status = AE_BAD_PARAMETER;
589216331Sjkim        goto UnlockAndExit;
590216331Sjkim    }
591216331Sjkim
592216331Sjkim    Status = AcpiEvFinishGpe (GpeEventInfo);
593216331Sjkim
594216331SjkimUnlockAndExit:
595216331Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
596216331Sjkim    return_ACPI_STATUS (Status);
597216331Sjkim}
598216331Sjkim
599216331SjkimACPI_EXPORT_SYMBOL (AcpiFinishGpe)
600216331Sjkim
601216331Sjkim
602216331Sjkim/******************************************************************************
603216331Sjkim *
604216331Sjkim * FUNCTION:    AcpiDisableAllGpes
605216331Sjkim *
606216331Sjkim * PARAMETERS:  None
607216331Sjkim *
608216331Sjkim * RETURN:      Status
609216331Sjkim *
610216331Sjkim * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
611216331Sjkim *
612216331Sjkim ******************************************************************************/
613216331Sjkim
614216331SjkimACPI_STATUS
615216331SjkimAcpiDisableAllGpes (
616216331Sjkim    void)
617216331Sjkim{
618216331Sjkim    ACPI_STATUS             Status;
619216331Sjkim
620216331Sjkim
621216331Sjkim    ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
622216331Sjkim
623216331Sjkim
624216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
625216331Sjkim    if (ACPI_FAILURE (Status))
626216331Sjkim    {
627216331Sjkim        return_ACPI_STATUS (Status);
628216331Sjkim    }
629216331Sjkim
630216331Sjkim    Status = AcpiHwDisableAllGpes ();
631216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
632216331Sjkim
633216331Sjkim    return_ACPI_STATUS (Status);
634216331Sjkim}
635216331Sjkim
636216331SjkimACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
637216331Sjkim
638216331Sjkim
639216331Sjkim/******************************************************************************
640216331Sjkim *
641216331Sjkim * FUNCTION:    AcpiEnableAllRuntimeGpes
642216331Sjkim *
643216331Sjkim * PARAMETERS:  None
644216331Sjkim *
645216331Sjkim * RETURN:      Status
646216331Sjkim *
647216331Sjkim * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
648216331Sjkim *
649216331Sjkim ******************************************************************************/
650216331Sjkim
651216331SjkimACPI_STATUS
652216331SjkimAcpiEnableAllRuntimeGpes (
653216331Sjkim    void)
654216331Sjkim{
655216331Sjkim    ACPI_STATUS             Status;
656216331Sjkim
657216331Sjkim
658216331Sjkim    ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
659216331Sjkim
660216331Sjkim
661216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
662216331Sjkim    if (ACPI_FAILURE (Status))
663216331Sjkim    {
664216331Sjkim        return_ACPI_STATUS (Status);
665216331Sjkim    }
666216331Sjkim
667216331Sjkim    Status = AcpiHwEnableAllRuntimeGpes ();
668216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
669216331Sjkim
670216331Sjkim    return_ACPI_STATUS (Status);
671216331Sjkim}
672216331Sjkim
673216331SjkimACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
674216331Sjkim
675216331Sjkim
676216331Sjkim/*******************************************************************************
677216331Sjkim *
678216331Sjkim * FUNCTION:    AcpiInstallGpeBlock
679216331Sjkim *
680216331Sjkim * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
681216331Sjkim *              GpeBlockAddress     - Address and SpaceID
682216331Sjkim *              RegisterCount       - Number of GPE register pairs in the block
683216331Sjkim *              InterruptNumber     - H/W interrupt for the block
684216331Sjkim *
685216331Sjkim * RETURN:      Status
686216331Sjkim *
687216331Sjkim * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
688216331Sjkim *              enabled here.
689216331Sjkim *
690216331Sjkim ******************************************************************************/
691216331Sjkim
692216331SjkimACPI_STATUS
693216331SjkimAcpiInstallGpeBlock (
694216331Sjkim    ACPI_HANDLE             GpeDevice,
695216331Sjkim    ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
696216331Sjkim    UINT32                  RegisterCount,
697216331Sjkim    UINT32                  InterruptNumber)
698216331Sjkim{
699216331Sjkim    ACPI_STATUS             Status;
700216331Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
701216331Sjkim    ACPI_NAMESPACE_NODE     *Node;
702216331Sjkim    ACPI_GPE_BLOCK_INFO     *GpeBlock;
703216331Sjkim
704216331Sjkim
705216331Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
706216331Sjkim
707216331Sjkim
708216331Sjkim    if ((!GpeDevice)       ||
709216331Sjkim        (!GpeBlockAddress) ||
710216331Sjkim        (!RegisterCount))
711216331Sjkim    {
712216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
713216331Sjkim    }
714216331Sjkim
715216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
716216331Sjkim    if (ACPI_FAILURE (Status))
717216331Sjkim    {
718216331Sjkim        return (Status);
719216331Sjkim    }
720216331Sjkim
721216331Sjkim    Node = AcpiNsValidateHandle (GpeDevice);
722216331Sjkim    if (!Node)
723216331Sjkim    {
724216331Sjkim        Status = AE_BAD_PARAMETER;
725216331Sjkim        goto UnlockAndExit;
726216331Sjkim    }
727216331Sjkim
728216331Sjkim    /*
729216331Sjkim     * For user-installed GPE Block Devices, the GpeBlockBaseNumber
730216331Sjkim     * is always zero
731216331Sjkim     */
732216331Sjkim    Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount,
733216331Sjkim                0, InterruptNumber, &GpeBlock);
734216331Sjkim    if (ACPI_FAILURE (Status))
735216331Sjkim    {
736216331Sjkim        goto UnlockAndExit;
737216331Sjkim    }
738216331Sjkim
739216331Sjkim    /* Install block in the DeviceObject attached to the node */
740216331Sjkim
741216331Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
742216331Sjkim    if (!ObjDesc)
743216331Sjkim    {
744216331Sjkim        /*
745216331Sjkim         * No object, create a new one (Device nodes do not always have
746216331Sjkim         * an attached object)
747216331Sjkim         */
748216331Sjkim        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
749216331Sjkim        if (!ObjDesc)
750216331Sjkim        {
751216331Sjkim            Status = AE_NO_MEMORY;
752216331Sjkim            goto UnlockAndExit;
753216331Sjkim        }
754216331Sjkim
755216331Sjkim        Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
756216331Sjkim
757216331Sjkim        /* Remove local reference to the object */
758216331Sjkim
759216331Sjkim        AcpiUtRemoveReference (ObjDesc);
760216331Sjkim        if (ACPI_FAILURE (Status))
761216331Sjkim        {
762216331Sjkim            goto UnlockAndExit;
763216331Sjkim        }
764216331Sjkim    }
765216331Sjkim
766216331Sjkim    /* Now install the GPE block in the DeviceObject */
767216331Sjkim
768216331Sjkim    ObjDesc->Device.GpeBlock = GpeBlock;
769216331Sjkim
770216331Sjkim
771216331SjkimUnlockAndExit:
772216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
773216331Sjkim    return_ACPI_STATUS (Status);
774216331Sjkim}
775216331Sjkim
776216331SjkimACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
777216331Sjkim
778216331Sjkim
779216331Sjkim/*******************************************************************************
780216331Sjkim *
781216331Sjkim * FUNCTION:    AcpiRemoveGpeBlock
782216331Sjkim *
783216331Sjkim * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
784216331Sjkim *
785216331Sjkim * RETURN:      Status
786216331Sjkim *
787216331Sjkim * DESCRIPTION: Remove a previously installed block of GPE registers
788216331Sjkim *
789216331Sjkim ******************************************************************************/
790216331Sjkim
791216331SjkimACPI_STATUS
792216331SjkimAcpiRemoveGpeBlock (
793216331Sjkim    ACPI_HANDLE             GpeDevice)
794216331Sjkim{
795216331Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
796216331Sjkim    ACPI_STATUS             Status;
797216331Sjkim    ACPI_NAMESPACE_NODE     *Node;
798216331Sjkim
799216331Sjkim
800216331Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
801216331Sjkim
802216331Sjkim
803216331Sjkim    if (!GpeDevice)
804216331Sjkim    {
805216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
806216331Sjkim    }
807216331Sjkim
808216331Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
809216331Sjkim    if (ACPI_FAILURE (Status))
810216331Sjkim    {
811216331Sjkim        return (Status);
812216331Sjkim    }
813216331Sjkim
814216331Sjkim    Node = AcpiNsValidateHandle (GpeDevice);
815216331Sjkim    if (!Node)
816216331Sjkim    {
817216331Sjkim        Status = AE_BAD_PARAMETER;
818216331Sjkim        goto UnlockAndExit;
819216331Sjkim    }
820216331Sjkim
821216331Sjkim    /* Get the DeviceObject attached to the node */
822216331Sjkim
823216331Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
824216331Sjkim    if (!ObjDesc ||
825216331Sjkim        !ObjDesc->Device.GpeBlock)
826216331Sjkim    {
827216331Sjkim        return_ACPI_STATUS (AE_NULL_OBJECT);
828216331Sjkim    }
829216331Sjkim
830216331Sjkim    /* Delete the GPE block (but not the DeviceObject) */
831216331Sjkim
832216331Sjkim    Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
833216331Sjkim    if (ACPI_SUCCESS (Status))
834216331Sjkim    {
835216331Sjkim        ObjDesc->Device.GpeBlock = NULL;
836216331Sjkim    }
837216331Sjkim
838216331SjkimUnlockAndExit:
839216331Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
840216331Sjkim    return_ACPI_STATUS (Status);
841216331Sjkim}
842216331Sjkim
843216331SjkimACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
844216331Sjkim
845216331Sjkim
846216331Sjkim/*******************************************************************************
847216331Sjkim *
848216331Sjkim * FUNCTION:    AcpiGetGpeDevice
849216331Sjkim *
850216331Sjkim * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
851216331Sjkim *              GpeDevice           - Where the parent GPE Device is returned
852216331Sjkim *
853216331Sjkim * RETURN:      Status
854216331Sjkim *
855216331Sjkim * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
856216331Sjkim *              gpe device indicates that the gpe number is contained in one of
857216331Sjkim *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
858216331Sjkim *
859216331Sjkim ******************************************************************************/
860216331Sjkim
861216331SjkimACPI_STATUS
862216331SjkimAcpiGetGpeDevice (
863216331Sjkim    UINT32                  Index,
864216331Sjkim    ACPI_HANDLE             *GpeDevice)
865216331Sjkim{
866216331Sjkim    ACPI_GPE_DEVICE_INFO    Info;
867216331Sjkim    ACPI_STATUS             Status;
868216331Sjkim
869216331Sjkim
870216331Sjkim    ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
871216331Sjkim
872216331Sjkim
873216331Sjkim    if (!GpeDevice)
874216331Sjkim    {
875216331Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
876216331Sjkim    }
877216331Sjkim
878216331Sjkim    if (Index >= AcpiCurrentGpeCount)
879216331Sjkim    {
880216331Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
881216331Sjkim    }
882216331Sjkim
883216331Sjkim    /* Setup and walk the GPE list */
884216331Sjkim
885216331Sjkim    Info.Index = Index;
886216331Sjkim    Info.Status = AE_NOT_EXIST;
887216331Sjkim    Info.GpeDevice = NULL;
888216331Sjkim    Info.NextBlockBaseIndex = 0;
889216331Sjkim
890216331Sjkim    Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
891216331Sjkim    if (ACPI_FAILURE (Status))
892216331Sjkim    {
893216331Sjkim        return_ACPI_STATUS (Status);
894216331Sjkim    }
895216331Sjkim
896216331Sjkim    *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
897216331Sjkim    return_ACPI_STATUS (Info.Status);
898216331Sjkim}
899216331Sjkim
900216331SjkimACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
901