xref: /reactos/drivers/bus/acpi/acpica/events/evxfgpe.c (revision 9d53c935)
1c2c66affSColin Finck /******************************************************************************
2c2c66affSColin Finck  *
3c2c66affSColin Finck  * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4c2c66affSColin Finck  *
5c2c66affSColin Finck  *****************************************************************************/
6c2c66affSColin Finck 
7c2c66affSColin Finck /*
8363f5f26SThomas Faber  * Copyright (C) 2000 - 2019, Intel Corp.
9c2c66affSColin Finck  * All rights reserved.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * Redistribution and use in source and binary forms, with or without
12c2c66affSColin Finck  * modification, are permitted provided that the following conditions
13c2c66affSColin Finck  * are met:
14c2c66affSColin Finck  * 1. Redistributions of source code must retain the above copyright
15c2c66affSColin Finck  *    notice, this list of conditions, and the following disclaimer,
16c2c66affSColin Finck  *    without modification.
17c2c66affSColin Finck  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18c2c66affSColin Finck  *    substantially similar to the "NO WARRANTY" disclaimer below
19c2c66affSColin Finck  *    ("Disclaimer") and any redistribution must be conditioned upon
20c2c66affSColin Finck  *    including a substantially similar Disclaimer requirement for further
21c2c66affSColin Finck  *    binary redistribution.
22c2c66affSColin Finck  * 3. Neither the names of the above-listed copyright holders nor the names
23c2c66affSColin Finck  *    of any contributors may be used to endorse or promote products derived
24c2c66affSColin Finck  *    from this software without specific prior written permission.
25c2c66affSColin Finck  *
26c2c66affSColin Finck  * Alternatively, this software may be distributed under the terms of the
27c2c66affSColin Finck  * GNU General Public License ("GPL") version 2 as published by the Free
28c2c66affSColin Finck  * Software Foundation.
29c2c66affSColin Finck  *
30c2c66affSColin Finck  * NO WARRANTY
31c2c66affSColin Finck  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32c2c66affSColin Finck  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33c2c66affSColin Finck  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34c2c66affSColin Finck  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35c2c66affSColin Finck  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36c2c66affSColin Finck  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37c2c66affSColin Finck  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38c2c66affSColin Finck  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39c2c66affSColin Finck  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40c2c66affSColin Finck  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41c2c66affSColin Finck  * POSSIBILITY OF SUCH DAMAGES.
42c2c66affSColin Finck  */
43c2c66affSColin Finck 
44c2c66affSColin Finck #define EXPORT_ACPI_INTERFACES
45c2c66affSColin Finck 
46c2c66affSColin Finck #include "acpi.h"
47c2c66affSColin Finck #include "accommon.h"
48c2c66affSColin Finck #include "acevents.h"
49c2c66affSColin Finck #include "acnamesp.h"
50c2c66affSColin Finck 
51c2c66affSColin Finck #define _COMPONENT          ACPI_EVENTS
52c2c66affSColin Finck         ACPI_MODULE_NAME    ("evxfgpe")
53c2c66affSColin Finck 
54c2c66affSColin Finck 
55c2c66affSColin Finck #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
56c2c66affSColin Finck /*******************************************************************************
57c2c66affSColin Finck  *
58c2c66affSColin Finck  * FUNCTION:    AcpiUpdateAllGpes
59c2c66affSColin Finck  *
60c2c66affSColin Finck  * PARAMETERS:  None
61c2c66affSColin Finck  *
62c2c66affSColin Finck  * RETURN:      Status
63c2c66affSColin Finck  *
64c2c66affSColin Finck  * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
65c2c66affSColin Finck  *              associated _Lxx or _Exx methods and are not pointed to by any
66c2c66affSColin Finck  *              device _PRW methods (this indicates that these GPEs are
67c2c66affSColin Finck  *              generally intended for system or device wakeup. Such GPEs
68c2c66affSColin Finck  *              have to be enabled directly when the devices whose _PRW
69c2c66affSColin Finck  *              methods point to them are set up for wakeup signaling.)
70c2c66affSColin Finck  *
71c2c66affSColin Finck  * NOTE: Should be called after any GPEs are added to the system. Primarily,
72c2c66affSColin Finck  * after the system _PRW methods have been run, but also after a GPE Block
73c2c66affSColin Finck  * Device has been added or if any new GPE methods have been added via a
74c2c66affSColin Finck  * dynamic table load.
75c2c66affSColin Finck  *
76c2c66affSColin Finck  ******************************************************************************/
77c2c66affSColin Finck 
78c2c66affSColin Finck ACPI_STATUS
79c2c66affSColin Finck AcpiUpdateAllGpes (
80c2c66affSColin Finck     void)
81c2c66affSColin Finck {
82c2c66affSColin Finck     ACPI_STATUS             Status;
836847cc3aSThomas Faber     BOOLEAN                 IsPollingNeeded = FALSE;
84c2c66affSColin Finck 
85c2c66affSColin Finck 
86c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
87c2c66affSColin Finck 
88c2c66affSColin Finck 
89c2c66affSColin Finck     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
90c2c66affSColin Finck     if (ACPI_FAILURE (Status))
91c2c66affSColin Finck     {
92c2c66affSColin Finck         return_ACPI_STATUS (Status);
93c2c66affSColin Finck     }
94c2c66affSColin Finck 
95c2c66affSColin Finck     if (AcpiGbl_AllGpesInitialized)
96c2c66affSColin Finck     {
97c2c66affSColin Finck         goto UnlockAndExit;
98c2c66affSColin Finck     }
99c2c66affSColin Finck 
1006847cc3aSThomas Faber     Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock,
1016847cc3aSThomas Faber         &IsPollingNeeded);
102c2c66affSColin Finck     if (ACPI_SUCCESS (Status))
103c2c66affSColin Finck     {
104c2c66affSColin Finck         AcpiGbl_AllGpesInitialized = TRUE;
105c2c66affSColin Finck     }
106c2c66affSColin Finck 
107c2c66affSColin Finck UnlockAndExit:
108c2c66affSColin Finck     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1096847cc3aSThomas Faber 
1106847cc3aSThomas Faber     if (IsPollingNeeded && AcpiGbl_AllGpesInitialized)
1116847cc3aSThomas Faber     {
1126847cc3aSThomas Faber         /* Poll GPEs to handle already triggered events */
1136847cc3aSThomas Faber 
1146847cc3aSThomas Faber         AcpiEvGpeDetect (AcpiGbl_GpeXruptListHead);
1156847cc3aSThomas Faber     }
116c2c66affSColin Finck     return_ACPI_STATUS (Status);
117c2c66affSColin Finck }
118c2c66affSColin Finck 
119c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
120c2c66affSColin Finck 
121c2c66affSColin Finck 
122c2c66affSColin Finck /*******************************************************************************
123c2c66affSColin Finck  *
124c2c66affSColin Finck  * FUNCTION:    AcpiEnableGpe
125c2c66affSColin Finck  *
126c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
127c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
128c2c66affSColin Finck  *
129c2c66affSColin Finck  * RETURN:      Status
130c2c66affSColin Finck  *
131c2c66affSColin Finck  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
132c2c66affSColin Finck  *              hardware-enabled.
133c2c66affSColin Finck  *
134c2c66affSColin Finck  ******************************************************************************/
135c2c66affSColin Finck 
136c2c66affSColin Finck ACPI_STATUS
137c2c66affSColin Finck AcpiEnableGpe (
138c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
139c2c66affSColin Finck     UINT32                  GpeNumber)
140c2c66affSColin Finck {
141c2c66affSColin Finck     ACPI_STATUS             Status = AE_BAD_PARAMETER;
142c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
143c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
144c2c66affSColin Finck 
145c2c66affSColin Finck 
146c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiEnableGpe);
147c2c66affSColin Finck 
148c2c66affSColin Finck 
149c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
150c2c66affSColin Finck 
151c2c66affSColin Finck     /*
152c2c66affSColin Finck      * Ensure that we have a valid GPE number and that there is some way
153c2c66affSColin Finck      * of handling the GPE (handler or a GPE method). In other words, we
154c2c66affSColin Finck      * won't allow a valid GPE to be enabled if there is no way to handle it.
155c2c66affSColin Finck      */
156c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
157c2c66affSColin Finck     if (GpeEventInfo)
158c2c66affSColin Finck     {
159c2c66affSColin Finck         if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
160c2c66affSColin Finck             ACPI_GPE_DISPATCH_NONE)
161c2c66affSColin Finck         {
162c2c66affSColin Finck             Status = AcpiEvAddGpeReference (GpeEventInfo);
1636847cc3aSThomas Faber             if (ACPI_SUCCESS (Status) &&
1646847cc3aSThomas Faber                 ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo))
1656847cc3aSThomas Faber             {
1666847cc3aSThomas Faber                 /* Poll edge-triggered GPEs to handle existing events */
1676847cc3aSThomas Faber 
1686847cc3aSThomas Faber                 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1696847cc3aSThomas Faber                 (void) AcpiEvDetectGpe (
1706847cc3aSThomas Faber                     GpeDevice, GpeEventInfo, GpeNumber);
1716847cc3aSThomas Faber                 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
1726847cc3aSThomas Faber             }
173c2c66affSColin Finck         }
174c2c66affSColin Finck         else
175c2c66affSColin Finck         {
176c2c66affSColin Finck             Status = AE_NO_HANDLER;
177c2c66affSColin Finck         }
178c2c66affSColin Finck     }
179c2c66affSColin Finck 
180c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
181c2c66affSColin Finck     return_ACPI_STATUS (Status);
182c2c66affSColin Finck }
183c2c66affSColin Finck 
184c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
185c2c66affSColin Finck 
186c2c66affSColin Finck 
187c2c66affSColin Finck /*******************************************************************************
188c2c66affSColin Finck  *
189c2c66affSColin Finck  * FUNCTION:    AcpiDisableGpe
190c2c66affSColin Finck  *
191c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
192c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
193c2c66affSColin Finck  *
194c2c66affSColin Finck  * RETURN:      Status
195c2c66affSColin Finck  *
196c2c66affSColin Finck  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
197c2c66affSColin Finck  *              removed, only then is the GPE disabled (for runtime GPEs), or
198c2c66affSColin Finck  *              the GPE mask bit disabled (for wake GPEs)
199c2c66affSColin Finck  *
200c2c66affSColin Finck  ******************************************************************************/
201c2c66affSColin Finck 
202c2c66affSColin Finck ACPI_STATUS
203c2c66affSColin Finck AcpiDisableGpe (
204c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
205c2c66affSColin Finck     UINT32                  GpeNumber)
206c2c66affSColin Finck {
207c2c66affSColin Finck     ACPI_STATUS             Status = AE_BAD_PARAMETER;
208c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
209c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
210c2c66affSColin Finck 
211c2c66affSColin Finck 
212c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiDisableGpe);
213c2c66affSColin Finck 
214c2c66affSColin Finck 
215c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
216c2c66affSColin Finck 
217c2c66affSColin Finck     /* Ensure that we have a valid GPE number */
218c2c66affSColin Finck 
219c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
220c2c66affSColin Finck     if (GpeEventInfo)
221c2c66affSColin Finck     {
222c2c66affSColin Finck         Status = AcpiEvRemoveGpeReference (GpeEventInfo);
223c2c66affSColin Finck     }
224c2c66affSColin Finck 
225c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
226c2c66affSColin Finck     return_ACPI_STATUS (Status);
227c2c66affSColin Finck }
228c2c66affSColin Finck 
229c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
230c2c66affSColin Finck 
231c2c66affSColin Finck 
232c2c66affSColin Finck /*******************************************************************************
233c2c66affSColin Finck  *
234c2c66affSColin Finck  * FUNCTION:    AcpiSetGpe
235c2c66affSColin Finck  *
236c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
237c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
238c2c66affSColin Finck  *              Action              - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
239c2c66affSColin Finck  *
240c2c66affSColin Finck  * RETURN:      Status
241c2c66affSColin Finck  *
242c2c66affSColin Finck  * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
243c2c66affSColin Finck  *              the reference count mechanism used in the AcpiEnableGpe(),
244c2c66affSColin Finck  *              AcpiDisableGpe() interfaces.
245c2c66affSColin Finck  *              This API is typically used by the GPE raw handler mode driver
246c2c66affSColin Finck  *              to switch between the polling mode and the interrupt mode after
247c2c66affSColin Finck  *              the driver has enabled the GPE.
248c2c66affSColin Finck  *              The APIs should be invoked in this order:
249c2c66affSColin Finck  *               AcpiEnableGpe()              <- Ensure the reference count > 0
250c2c66affSColin Finck  *               AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode
251c2c66affSColin Finck  *               AcpiSetGpe(ACPI_GPE_ENABLE)  <- Leave polling mode
252c2c66affSColin Finck  *               AcpiDisableGpe()             <- Decrease the reference count
253c2c66affSColin Finck  *
254c2c66affSColin Finck  * Note: If a GPE is shared by 2 silicon components, then both the drivers
255c2c66affSColin Finck  *       should support GPE polling mode or disabling the GPE for long period
256c2c66affSColin Finck  *       for one driver may break the other. So use it with care since all
257c2c66affSColin Finck  *       firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
258c2c66affSColin Finck  *
259c2c66affSColin Finck  ******************************************************************************/
260c2c66affSColin Finck 
261c2c66affSColin Finck ACPI_STATUS
262c2c66affSColin Finck AcpiSetGpe (
263c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
264c2c66affSColin Finck     UINT32                  GpeNumber,
265c2c66affSColin Finck     UINT8                   Action)
266c2c66affSColin Finck {
267c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
268c2c66affSColin Finck     ACPI_STATUS             Status;
269c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
270c2c66affSColin Finck 
271c2c66affSColin Finck 
272c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiSetGpe);
273c2c66affSColin Finck 
274c2c66affSColin Finck 
275c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
276c2c66affSColin Finck 
277c2c66affSColin Finck     /* Ensure that we have a valid GPE number */
278c2c66affSColin Finck 
279c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
280c2c66affSColin Finck     if (!GpeEventInfo)
281c2c66affSColin Finck     {
282c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
283c2c66affSColin Finck         goto UnlockAndExit;
284c2c66affSColin Finck     }
285c2c66affSColin Finck 
286c2c66affSColin Finck     /* Perform the action */
287c2c66affSColin Finck 
288c2c66affSColin Finck     switch (Action)
289c2c66affSColin Finck     {
290c2c66affSColin Finck     case ACPI_GPE_ENABLE:
291c2c66affSColin Finck 
292c2c66affSColin Finck         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
293c2c66affSColin Finck         GpeEventInfo->DisableForDispatch = FALSE;
294c2c66affSColin Finck         break;
295c2c66affSColin Finck 
296c2c66affSColin Finck     case ACPI_GPE_DISABLE:
297c2c66affSColin Finck 
298c2c66affSColin Finck         Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
299c2c66affSColin Finck         GpeEventInfo->DisableForDispatch = TRUE;
300c2c66affSColin Finck         break;
301c2c66affSColin Finck 
302c2c66affSColin Finck     default:
303c2c66affSColin Finck 
304c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
305c2c66affSColin Finck         break;
306c2c66affSColin Finck     }
307c2c66affSColin Finck 
308c2c66affSColin Finck UnlockAndExit:
309c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
310c2c66affSColin Finck     return_ACPI_STATUS (Status);
311c2c66affSColin Finck }
312c2c66affSColin Finck 
313c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiSetGpe)
314c2c66affSColin Finck 
315c2c66affSColin Finck 
316c2c66affSColin Finck /*******************************************************************************
317c2c66affSColin Finck  *
318c2c66affSColin Finck  * FUNCTION:    AcpiMaskGpe
319c2c66affSColin Finck  *
320c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
321c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
322c2c66affSColin Finck  *              IsMasked            - Whether the GPE is masked or not
323c2c66affSColin Finck  *
324c2c66affSColin Finck  * RETURN:      Status
325c2c66affSColin Finck  *
326c2c66affSColin Finck  * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to
327c2c66affSColin Finck  *              prevent a GPE flooding.
328c2c66affSColin Finck  *
329c2c66affSColin Finck  ******************************************************************************/
330c2c66affSColin Finck 
331c2c66affSColin Finck ACPI_STATUS
332c2c66affSColin Finck AcpiMaskGpe (
333c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
334c2c66affSColin Finck     UINT32                  GpeNumber,
335c2c66affSColin Finck     BOOLEAN                 IsMasked)
336c2c66affSColin Finck {
337c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
338c2c66affSColin Finck     ACPI_STATUS             Status;
339c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
340c2c66affSColin Finck 
341c2c66affSColin Finck 
342c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiMaskGpe);
343c2c66affSColin Finck 
344c2c66affSColin Finck 
345c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
346c2c66affSColin Finck 
347c2c66affSColin Finck     /* Ensure that we have a valid GPE number */
348c2c66affSColin Finck 
349c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
350c2c66affSColin Finck     if (!GpeEventInfo)
351c2c66affSColin Finck     {
352c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
353c2c66affSColin Finck         goto UnlockAndExit;
354c2c66affSColin Finck     }
355c2c66affSColin Finck 
356c2c66affSColin Finck     Status = AcpiEvMaskGpe (GpeEventInfo, IsMasked);
357c2c66affSColin Finck 
358c2c66affSColin Finck UnlockAndExit:
359c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
360c2c66affSColin Finck     return_ACPI_STATUS (Status);
361c2c66affSColin Finck }
362c2c66affSColin Finck 
363c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiMaskGpe)
364c2c66affSColin Finck 
365c2c66affSColin Finck 
366c2c66affSColin Finck /*******************************************************************************
367c2c66affSColin Finck  *
368c2c66affSColin Finck  * FUNCTION:    AcpiMarkGpeForWake
369c2c66affSColin Finck  *
370c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
371c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
372c2c66affSColin Finck  *
373c2c66affSColin Finck  * RETURN:      Status
374c2c66affSColin Finck  *
375c2c66affSColin Finck  * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
376c2c66affSColin Finck  *              sets the ACPI_GPE_CAN_WAKE flag.
377c2c66affSColin Finck  *
378c2c66affSColin Finck  * Some potential callers of AcpiSetupGpeForWake may know in advance that
379c2c66affSColin Finck  * there won't be any notify handlers installed for device wake notifications
380c2c66affSColin Finck  * from the given GPE (one example is a button GPE in Linux). For these cases,
381c2c66affSColin Finck  * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
382c2c66affSColin Finck  * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
383c2c66affSColin Finck  * setup implicit wake notification for it (since there's no handler method).
384c2c66affSColin Finck  *
385c2c66affSColin Finck  ******************************************************************************/
386c2c66affSColin Finck 
387c2c66affSColin Finck ACPI_STATUS
388c2c66affSColin Finck AcpiMarkGpeForWake (
389c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
390c2c66affSColin Finck     UINT32                  GpeNumber)
391c2c66affSColin Finck {
392c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
393c2c66affSColin Finck     ACPI_STATUS             Status = AE_BAD_PARAMETER;
394c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
395c2c66affSColin Finck 
396c2c66affSColin Finck 
397c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
398c2c66affSColin Finck 
399c2c66affSColin Finck 
400c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
401c2c66affSColin Finck 
402c2c66affSColin Finck     /* Ensure that we have a valid GPE number */
403c2c66affSColin Finck 
404c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
405c2c66affSColin Finck     if (GpeEventInfo)
406c2c66affSColin Finck     {
407c2c66affSColin Finck         /* Mark the GPE as a possible wake event */
408c2c66affSColin Finck 
409c2c66affSColin Finck         GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
410c2c66affSColin Finck         Status = AE_OK;
411c2c66affSColin Finck     }
412c2c66affSColin Finck 
413c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
414c2c66affSColin Finck     return_ACPI_STATUS (Status);
415c2c66affSColin Finck }
416c2c66affSColin Finck 
417c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
418c2c66affSColin Finck 
419c2c66affSColin Finck 
420c2c66affSColin Finck /*******************************************************************************
421c2c66affSColin Finck  *
422c2c66affSColin Finck  * FUNCTION:    AcpiSetupGpeForWake
423c2c66affSColin Finck  *
424c2c66affSColin Finck  * PARAMETERS:  WakeDevice          - Device associated with the GPE (via _PRW)
425c2c66affSColin Finck  *              GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
426c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
427c2c66affSColin Finck  *
428c2c66affSColin Finck  * RETURN:      Status
429c2c66affSColin Finck  *
430c2c66affSColin Finck  * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
431c2c66affSColin Finck  *              interface is intended to be used as the host executes the
432c2c66affSColin Finck  *              _PRW methods (Power Resources for Wake) in the system tables.
433c2c66affSColin Finck  *              Each _PRW appears under a Device Object (The WakeDevice), and
434c2c66affSColin Finck  *              contains the info for the wake GPE associated with the
435c2c66affSColin Finck  *              WakeDevice.
436c2c66affSColin Finck  *
437c2c66affSColin Finck  ******************************************************************************/
438c2c66affSColin Finck 
439c2c66affSColin Finck ACPI_STATUS
440c2c66affSColin Finck AcpiSetupGpeForWake (
441c2c66affSColin Finck     ACPI_HANDLE             WakeDevice,
442c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
443c2c66affSColin Finck     UINT32                  GpeNumber)
444c2c66affSColin Finck {
445c2c66affSColin Finck     ACPI_STATUS             Status;
446c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
447c2c66affSColin Finck     ACPI_NAMESPACE_NODE     *DeviceNode;
448c2c66affSColin Finck     ACPI_GPE_NOTIFY_INFO    *Notify;
449c2c66affSColin Finck     ACPI_GPE_NOTIFY_INFO    *NewNotify;
450c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
451c2c66affSColin Finck 
452c2c66affSColin Finck 
453c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
454c2c66affSColin Finck 
455c2c66affSColin Finck 
456c2c66affSColin Finck     /* Parameter Validation */
457c2c66affSColin Finck 
458c2c66affSColin Finck     if (!WakeDevice)
459c2c66affSColin Finck     {
460c2c66affSColin Finck         /*
461c2c66affSColin Finck          * By forcing WakeDevice to be valid, we automatically enable the
462c2c66affSColin Finck          * implicit notify feature on all hosts.
463c2c66affSColin Finck          */
464c2c66affSColin Finck         return_ACPI_STATUS (AE_BAD_PARAMETER);
465c2c66affSColin Finck     }
466c2c66affSColin Finck 
467c2c66affSColin Finck     /* Handle root object case */
468c2c66affSColin Finck 
469c2c66affSColin Finck     if (WakeDevice == ACPI_ROOT_OBJECT)
470c2c66affSColin Finck     {
471c2c66affSColin Finck         DeviceNode = AcpiGbl_RootNode;
472c2c66affSColin Finck     }
473c2c66affSColin Finck     else
474c2c66affSColin Finck     {
475c2c66affSColin Finck         DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
476c2c66affSColin Finck     }
477c2c66affSColin Finck 
478c2c66affSColin Finck     /* Validate WakeDevice is of type Device */
479c2c66affSColin Finck 
480c2c66affSColin Finck     if (DeviceNode->Type != ACPI_TYPE_DEVICE)
481c2c66affSColin Finck     {
482c2c66affSColin Finck         return_ACPI_STATUS (AE_BAD_PARAMETER);
483c2c66affSColin Finck     }
484c2c66affSColin Finck 
485c2c66affSColin Finck     /*
486c2c66affSColin Finck      * Allocate a new notify object up front, in case it is needed.
487c2c66affSColin Finck      * Memory allocation while holding a spinlock is a big no-no
488c2c66affSColin Finck      * on some hosts.
489c2c66affSColin Finck      */
490c2c66affSColin Finck     NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
491c2c66affSColin Finck     if (!NewNotify)
492c2c66affSColin Finck     {
493c2c66affSColin Finck         return_ACPI_STATUS (AE_NO_MEMORY);
494c2c66affSColin Finck     }
495c2c66affSColin Finck 
496c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
497c2c66affSColin Finck 
498c2c66affSColin Finck     /* Ensure that we have a valid GPE number */
499c2c66affSColin Finck 
500c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
501c2c66affSColin Finck     if (!GpeEventInfo)
502c2c66affSColin Finck     {
503c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
504c2c66affSColin Finck         goto UnlockAndExit;
505c2c66affSColin Finck     }
506c2c66affSColin Finck 
507c2c66affSColin Finck     /*
508c2c66affSColin Finck      * If there is no method or handler for this GPE, then the
509c2c66affSColin Finck      * WakeDevice will be notified whenever this GPE fires. This is
510c2c66affSColin Finck      * known as an "implicit notify". Note: The GPE is assumed to be
511c2c66affSColin Finck      * level-triggered (for windows compatibility).
512c2c66affSColin Finck      */
513c2c66affSColin Finck     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
514c2c66affSColin Finck         ACPI_GPE_DISPATCH_NONE)
515c2c66affSColin Finck     {
516c2c66affSColin Finck         /*
517c2c66affSColin Finck          * This is the first device for implicit notify on this GPE.
518c2c66affSColin Finck          * Just set the flags here, and enter the NOTIFY block below.
519c2c66affSColin Finck          */
520c2c66affSColin Finck         GpeEventInfo->Flags =
521c2c66affSColin Finck             (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
522c2c66affSColin Finck     }
5236847cc3aSThomas Faber     else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED)
5246847cc3aSThomas Faber     {
5256847cc3aSThomas Faber         /*
5266847cc3aSThomas Faber          * A reference to this GPE has been added during the GPE block
5276847cc3aSThomas Faber          * initialization, so drop it now to prevent the GPE from being
5286847cc3aSThomas Faber          * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.
5296847cc3aSThomas Faber          */
5306847cc3aSThomas Faber         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
5316847cc3aSThomas Faber         GpeEventInfo->Flags &= ~~ACPI_GPE_AUTO_ENABLED;
5326847cc3aSThomas Faber     }
533c2c66affSColin Finck 
534c2c66affSColin Finck     /*
535c2c66affSColin Finck      * If we already have an implicit notify on this GPE, add
536c2c66affSColin Finck      * this device to the notify list.
537c2c66affSColin Finck      */
538c2c66affSColin Finck     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
539c2c66affSColin Finck         ACPI_GPE_DISPATCH_NOTIFY)
540c2c66affSColin Finck     {
541c2c66affSColin Finck         /* Ensure that the device is not already in the list */
542c2c66affSColin Finck 
543c2c66affSColin Finck         Notify = GpeEventInfo->Dispatch.NotifyList;
544c2c66affSColin Finck         while (Notify)
545c2c66affSColin Finck         {
546c2c66affSColin Finck             if (Notify->DeviceNode == DeviceNode)
547c2c66affSColin Finck             {
548c2c66affSColin Finck                 Status = AE_ALREADY_EXISTS;
549c2c66affSColin Finck                 goto UnlockAndExit;
550c2c66affSColin Finck             }
551c2c66affSColin Finck             Notify = Notify->Next;
552c2c66affSColin Finck         }
553c2c66affSColin Finck 
554c2c66affSColin Finck         /* Add this device to the notify list for this GPE */
555c2c66affSColin Finck 
556c2c66affSColin Finck         NewNotify->DeviceNode = DeviceNode;
557c2c66affSColin Finck         NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
558c2c66affSColin Finck         GpeEventInfo->Dispatch.NotifyList = NewNotify;
559c2c66affSColin Finck         NewNotify = NULL;
560c2c66affSColin Finck     }
561c2c66affSColin Finck 
562c2c66affSColin Finck     /* Mark the GPE as a possible wake event */
563c2c66affSColin Finck 
564c2c66affSColin Finck     GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
565c2c66affSColin Finck     Status = AE_OK;
566c2c66affSColin Finck 
567c2c66affSColin Finck 
568c2c66affSColin Finck UnlockAndExit:
569c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
570c2c66affSColin Finck 
571c2c66affSColin Finck     /* Delete the notify object if it was not used above */
572c2c66affSColin Finck 
573c2c66affSColin Finck     if (NewNotify)
574c2c66affSColin Finck     {
575c2c66affSColin Finck         ACPI_FREE (NewNotify);
576c2c66affSColin Finck     }
577c2c66affSColin Finck     return_ACPI_STATUS (Status);
578c2c66affSColin Finck }
579c2c66affSColin Finck 
580c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
581c2c66affSColin Finck 
582c2c66affSColin Finck 
583c2c66affSColin Finck /*******************************************************************************
584c2c66affSColin Finck  *
585c2c66affSColin Finck  * FUNCTION:    AcpiSetGpeWakeMask
586c2c66affSColin Finck  *
587c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
588c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
589c2c66affSColin Finck  *              Action              - Enable or Disable
590c2c66affSColin Finck  *
591c2c66affSColin Finck  * RETURN:      Status
592c2c66affSColin Finck  *
593c2c66affSColin Finck  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
594c2c66affSColin Finck  *              already be marked as a WAKE GPE.
595c2c66affSColin Finck  *
596c2c66affSColin Finck  ******************************************************************************/
597c2c66affSColin Finck 
598c2c66affSColin Finck ACPI_STATUS
599c2c66affSColin Finck AcpiSetGpeWakeMask (
600c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
601c2c66affSColin Finck     UINT32                  GpeNumber,
602c2c66affSColin Finck     UINT8                   Action)
603c2c66affSColin Finck {
604c2c66affSColin Finck     ACPI_STATUS             Status = AE_OK;
605c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
606c2c66affSColin Finck     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
607c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
608c2c66affSColin Finck     UINT32                  RegisterBit;
609c2c66affSColin Finck 
610c2c66affSColin Finck 
611c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
612c2c66affSColin Finck 
613c2c66affSColin Finck 
614c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
615c2c66affSColin Finck 
616c2c66affSColin Finck     /*
617c2c66affSColin Finck      * Ensure that we have a valid GPE number and that this GPE is in
618c2c66affSColin Finck      * fact a wake GPE
619c2c66affSColin Finck      */
620c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
621c2c66affSColin Finck     if (!GpeEventInfo)
622c2c66affSColin Finck     {
623c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
624c2c66affSColin Finck         goto UnlockAndExit;
625c2c66affSColin Finck     }
626c2c66affSColin Finck 
627c2c66affSColin Finck     if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
628c2c66affSColin Finck     {
629c2c66affSColin Finck         Status = AE_TYPE;
630c2c66affSColin Finck         goto UnlockAndExit;
631c2c66affSColin Finck     }
632c2c66affSColin Finck 
633c2c66affSColin Finck     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
634c2c66affSColin Finck     if (!GpeRegisterInfo)
635c2c66affSColin Finck     {
636c2c66affSColin Finck         Status = AE_NOT_EXIST;
637c2c66affSColin Finck         goto UnlockAndExit;
638c2c66affSColin Finck     }
639c2c66affSColin Finck 
640c2c66affSColin Finck     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
641c2c66affSColin Finck 
642c2c66affSColin Finck     /* Perform the action */
643c2c66affSColin Finck 
644c2c66affSColin Finck     switch (Action)
645c2c66affSColin Finck     {
646c2c66affSColin Finck     case ACPI_GPE_ENABLE:
647c2c66affSColin Finck 
648c2c66affSColin Finck         ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
649c2c66affSColin Finck         break;
650c2c66affSColin Finck 
651c2c66affSColin Finck     case ACPI_GPE_DISABLE:
652c2c66affSColin Finck 
653c2c66affSColin Finck         ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
654c2c66affSColin Finck         break;
655c2c66affSColin Finck 
656c2c66affSColin Finck     default:
657c2c66affSColin Finck 
658c2c66affSColin Finck         ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
659c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
660c2c66affSColin Finck         break;
661c2c66affSColin Finck     }
662c2c66affSColin Finck 
663c2c66affSColin Finck UnlockAndExit:
664c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
665c2c66affSColin Finck     return_ACPI_STATUS (Status);
666c2c66affSColin Finck }
667c2c66affSColin Finck 
668c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
669c2c66affSColin Finck 
670c2c66affSColin Finck 
671c2c66affSColin Finck /*******************************************************************************
672c2c66affSColin Finck  *
673c2c66affSColin Finck  * FUNCTION:    AcpiClearGpe
674c2c66affSColin Finck  *
675c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
676c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
677c2c66affSColin Finck  *
678c2c66affSColin Finck  * RETURN:      Status
679c2c66affSColin Finck  *
680c2c66affSColin Finck  * DESCRIPTION: Clear an ACPI event (general purpose)
681c2c66affSColin Finck  *
682c2c66affSColin Finck  ******************************************************************************/
683c2c66affSColin Finck 
684c2c66affSColin Finck ACPI_STATUS
685c2c66affSColin Finck AcpiClearGpe (
686c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
687c2c66affSColin Finck     UINT32                  GpeNumber)
688c2c66affSColin Finck {
689c2c66affSColin Finck     ACPI_STATUS             Status = AE_OK;
690c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
691c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
692c2c66affSColin Finck 
693c2c66affSColin Finck 
694c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiClearGpe);
695c2c66affSColin Finck 
696c2c66affSColin Finck 
697c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
698c2c66affSColin Finck 
699c2c66affSColin Finck     /* Ensure that we have a valid GPE number */
700c2c66affSColin Finck 
701c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
702c2c66affSColin Finck     if (!GpeEventInfo)
703c2c66affSColin Finck     {
704c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
705c2c66affSColin Finck         goto UnlockAndExit;
706c2c66affSColin Finck     }
707c2c66affSColin Finck 
708c2c66affSColin Finck     Status = AcpiHwClearGpe (GpeEventInfo);
709c2c66affSColin Finck 
710c2c66affSColin Finck UnlockAndExit:
711c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
712c2c66affSColin Finck     return_ACPI_STATUS (Status);
713c2c66affSColin Finck }
714c2c66affSColin Finck 
715c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiClearGpe)
716c2c66affSColin Finck 
717c2c66affSColin Finck 
718c2c66affSColin Finck /*******************************************************************************
719c2c66affSColin Finck  *
720c2c66affSColin Finck  * FUNCTION:    AcpiGetGpeStatus
721c2c66affSColin Finck  *
722c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Parent GPE Device. NULL for GPE0/GPE1
723c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
724c2c66affSColin Finck  *              EventStatus         - Where the current status of the event
725c2c66affSColin Finck  *                                    will be returned
726c2c66affSColin Finck  *
727c2c66affSColin Finck  * RETURN:      Status
728c2c66affSColin Finck  *
729c2c66affSColin Finck  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
730c2c66affSColin Finck  *
731c2c66affSColin Finck  ******************************************************************************/
732c2c66affSColin Finck 
733c2c66affSColin Finck ACPI_STATUS
734c2c66affSColin Finck AcpiGetGpeStatus (
735c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
736c2c66affSColin Finck     UINT32                  GpeNumber,
737c2c66affSColin Finck     ACPI_EVENT_STATUS       *EventStatus)
738c2c66affSColin Finck {
739c2c66affSColin Finck     ACPI_STATUS             Status = AE_OK;
740c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
741c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
742c2c66affSColin Finck 
743c2c66affSColin Finck 
744c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
745c2c66affSColin Finck 
746c2c66affSColin Finck 
747c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
748c2c66affSColin Finck 
749c2c66affSColin Finck     /* Ensure that we have a valid GPE number */
750c2c66affSColin Finck 
751c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
752c2c66affSColin Finck     if (!GpeEventInfo)
753c2c66affSColin Finck     {
754c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
755c2c66affSColin Finck         goto UnlockAndExit;
756c2c66affSColin Finck     }
757c2c66affSColin Finck 
758c2c66affSColin Finck     /* Obtain status on the requested GPE number */
759c2c66affSColin Finck 
760c2c66affSColin Finck     Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
761c2c66affSColin Finck 
762c2c66affSColin Finck UnlockAndExit:
763c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
764c2c66affSColin Finck     return_ACPI_STATUS (Status);
765c2c66affSColin Finck }
766c2c66affSColin Finck 
767c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
768c2c66affSColin Finck 
769c2c66affSColin Finck 
770c2c66affSColin Finck /*******************************************************************************
771c2c66affSColin Finck  *
772c2c66affSColin Finck  * FUNCTION:    AcpiFinishGpe
773c2c66affSColin Finck  *
774c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Namespace node for the GPE Block
775c2c66affSColin Finck  *                                    (NULL for FADT defined GPEs)
776c2c66affSColin Finck  *              GpeNumber           - GPE level within the GPE block
777c2c66affSColin Finck  *
778c2c66affSColin Finck  * RETURN:      Status
779c2c66affSColin Finck  *
780*9d53c935SThomas Faber  * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE
781c2c66affSColin Finck  *              processing. Intended for use by asynchronous host-installed
782*9d53c935SThomas Faber  *              GPE handlers. The GPE is only re-enabled if the EnableForRun bit
783c2c66affSColin Finck  *              is set in the GPE info.
784c2c66affSColin Finck  *
785c2c66affSColin Finck  ******************************************************************************/
786c2c66affSColin Finck 
787c2c66affSColin Finck ACPI_STATUS
788c2c66affSColin Finck AcpiFinishGpe (
789c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
790c2c66affSColin Finck     UINT32                  GpeNumber)
791c2c66affSColin Finck {
792c2c66affSColin Finck     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
793c2c66affSColin Finck     ACPI_STATUS             Status;
794c2c66affSColin Finck     ACPI_CPU_FLAGS          Flags;
795c2c66affSColin Finck 
796c2c66affSColin Finck 
797c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiFinishGpe);
798c2c66affSColin Finck 
799c2c66affSColin Finck 
800c2c66affSColin Finck     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
801c2c66affSColin Finck 
802c2c66affSColin Finck     /* Ensure that we have a valid GPE number */
803c2c66affSColin Finck 
804c2c66affSColin Finck     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
805c2c66affSColin Finck     if (!GpeEventInfo)
806c2c66affSColin Finck     {
807c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
808c2c66affSColin Finck         goto UnlockAndExit;
809c2c66affSColin Finck     }
810c2c66affSColin Finck 
811c2c66affSColin Finck     Status = AcpiEvFinishGpe (GpeEventInfo);
812c2c66affSColin Finck 
813c2c66affSColin Finck UnlockAndExit:
814c2c66affSColin Finck     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
815c2c66affSColin Finck     return_ACPI_STATUS (Status);
816c2c66affSColin Finck }
817c2c66affSColin Finck 
818c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
819c2c66affSColin Finck 
820c2c66affSColin Finck 
821c2c66affSColin Finck /******************************************************************************
822c2c66affSColin Finck  *
823c2c66affSColin Finck  * FUNCTION:    AcpiDisableAllGpes
824c2c66affSColin Finck  *
825c2c66affSColin Finck  * PARAMETERS:  None
826c2c66affSColin Finck  *
827c2c66affSColin Finck  * RETURN:      Status
828c2c66affSColin Finck  *
829c2c66affSColin Finck  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
830c2c66affSColin Finck  *
831c2c66affSColin Finck  ******************************************************************************/
832c2c66affSColin Finck 
833c2c66affSColin Finck ACPI_STATUS
834c2c66affSColin Finck AcpiDisableAllGpes (
835c2c66affSColin Finck     void)
836c2c66affSColin Finck {
837c2c66affSColin Finck     ACPI_STATUS             Status;
838c2c66affSColin Finck 
839c2c66affSColin Finck 
840c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
841c2c66affSColin Finck 
842c2c66affSColin Finck 
843c2c66affSColin Finck     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
844c2c66affSColin Finck     if (ACPI_FAILURE (Status))
845c2c66affSColin Finck     {
846c2c66affSColin Finck         return_ACPI_STATUS (Status);
847c2c66affSColin Finck     }
848c2c66affSColin Finck 
849c2c66affSColin Finck     Status = AcpiHwDisableAllGpes ();
850c2c66affSColin Finck     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
851c2c66affSColin Finck 
852c2c66affSColin Finck     return_ACPI_STATUS (Status);
853c2c66affSColin Finck }
854c2c66affSColin Finck 
855c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
856c2c66affSColin Finck 
857c2c66affSColin Finck 
858c2c66affSColin Finck /******************************************************************************
859c2c66affSColin Finck  *
860c2c66affSColin Finck  * FUNCTION:    AcpiEnableAllRuntimeGpes
861c2c66affSColin Finck  *
862c2c66affSColin Finck  * PARAMETERS:  None
863c2c66affSColin Finck  *
864c2c66affSColin Finck  * RETURN:      Status
865c2c66affSColin Finck  *
866c2c66affSColin Finck  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
867c2c66affSColin Finck  *
868c2c66affSColin Finck  ******************************************************************************/
869c2c66affSColin Finck 
870c2c66affSColin Finck ACPI_STATUS
871c2c66affSColin Finck AcpiEnableAllRuntimeGpes (
872c2c66affSColin Finck     void)
873c2c66affSColin Finck {
874c2c66affSColin Finck     ACPI_STATUS             Status;
875c2c66affSColin Finck 
876c2c66affSColin Finck 
877c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
878c2c66affSColin Finck 
879c2c66affSColin Finck 
880c2c66affSColin Finck     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
881c2c66affSColin Finck     if (ACPI_FAILURE (Status))
882c2c66affSColin Finck     {
883c2c66affSColin Finck         return_ACPI_STATUS (Status);
884c2c66affSColin Finck     }
885c2c66affSColin Finck 
886c2c66affSColin Finck     Status = AcpiHwEnableAllRuntimeGpes ();
887c2c66affSColin Finck     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
888c2c66affSColin Finck 
889c2c66affSColin Finck     return_ACPI_STATUS (Status);
890c2c66affSColin Finck }
891c2c66affSColin Finck 
892c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
893c2c66affSColin Finck 
894c2c66affSColin Finck 
895c2c66affSColin Finck /******************************************************************************
896c2c66affSColin Finck  *
897c2c66affSColin Finck  * FUNCTION:    AcpiEnableAllWakeupGpes
898c2c66affSColin Finck  *
899c2c66affSColin Finck  * PARAMETERS:  None
900c2c66affSColin Finck  *
901c2c66affSColin Finck  * RETURN:      Status
902c2c66affSColin Finck  *
903c2c66affSColin Finck  * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
904c2c66affSColin Finck  *              all GPE blocks.
905c2c66affSColin Finck  *
906c2c66affSColin Finck  ******************************************************************************/
907c2c66affSColin Finck 
908c2c66affSColin Finck ACPI_STATUS
909c2c66affSColin Finck AcpiEnableAllWakeupGpes (
910c2c66affSColin Finck     void)
911c2c66affSColin Finck {
912c2c66affSColin Finck     ACPI_STATUS             Status;
913c2c66affSColin Finck 
914c2c66affSColin Finck 
915c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
916c2c66affSColin Finck 
917c2c66affSColin Finck 
918c2c66affSColin Finck     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
919c2c66affSColin Finck     if (ACPI_FAILURE (Status))
920c2c66affSColin Finck     {
921c2c66affSColin Finck         return_ACPI_STATUS (Status);
922c2c66affSColin Finck     }
923c2c66affSColin Finck 
924c2c66affSColin Finck     Status = AcpiHwEnableAllWakeupGpes ();
925c2c66affSColin Finck     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
926c2c66affSColin Finck 
927c2c66affSColin Finck     return_ACPI_STATUS (Status);
928c2c66affSColin Finck }
929c2c66affSColin Finck 
930c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
931c2c66affSColin Finck 
932c2c66affSColin Finck 
933c2c66affSColin Finck /*******************************************************************************
934c2c66affSColin Finck  *
935c2c66affSColin Finck  * FUNCTION:    AcpiInstallGpeBlock
936c2c66affSColin Finck  *
937c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
938c2c66affSColin Finck  *              GpeBlockAddress     - Address and SpaceID
939c2c66affSColin Finck  *              RegisterCount       - Number of GPE register pairs in the block
940c2c66affSColin Finck  *              InterruptNumber     - H/W interrupt for the block
941c2c66affSColin Finck  *
942c2c66affSColin Finck  * RETURN:      Status
943c2c66affSColin Finck  *
944c2c66affSColin Finck  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
945c2c66affSColin Finck  *              enabled here.
946c2c66affSColin Finck  *
947c2c66affSColin Finck  ******************************************************************************/
948c2c66affSColin Finck 
949c2c66affSColin Finck ACPI_STATUS
950c2c66affSColin Finck AcpiInstallGpeBlock (
951c2c66affSColin Finck     ACPI_HANDLE             GpeDevice,
952c2c66affSColin Finck     ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
953c2c66affSColin Finck     UINT32                  RegisterCount,
954c2c66affSColin Finck     UINT32                  InterruptNumber)
955c2c66affSColin Finck {
956c2c66affSColin Finck     ACPI_STATUS             Status;
957c2c66affSColin Finck     ACPI_OPERAND_OBJECT     *ObjDesc;
958c2c66affSColin Finck     ACPI_NAMESPACE_NODE     *Node;
959c2c66affSColin Finck     ACPI_GPE_BLOCK_INFO     *GpeBlock;
960c2c66affSColin Finck 
961c2c66affSColin Finck 
962c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
963c2c66affSColin Finck 
964c2c66affSColin Finck 
965c2c66affSColin Finck     if ((!GpeDevice)       ||
966c2c66affSColin Finck         (!GpeBlockAddress) ||
967c2c66affSColin Finck         (!RegisterCount))
968c2c66affSColin Finck     {
969c2c66affSColin Finck         return_ACPI_STATUS (AE_BAD_PARAMETER);
970c2c66affSColin Finck     }
971c2c66affSColin Finck 
972c2c66affSColin Finck     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
973c2c66affSColin Finck     if (ACPI_FAILURE (Status))
974c2c66affSColin Finck     {
975c2c66affSColin Finck         return_ACPI_STATUS (Status);
976c2c66affSColin Finck     }
977c2c66affSColin Finck 
978c2c66affSColin Finck     Node = AcpiNsValidateHandle (GpeDevice);
979c2c66affSColin Finck     if (!Node)
980c2c66affSColin Finck     {
981c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
982c2c66affSColin Finck         goto UnlockAndExit;
983c2c66affSColin Finck     }
984c2c66affSColin Finck 
985c2c66affSColin Finck     /* Validate the parent device */
986c2c66affSColin Finck 
987c2c66affSColin Finck     if (Node->Type != ACPI_TYPE_DEVICE)
988c2c66affSColin Finck     {
989c2c66affSColin Finck         Status = AE_TYPE;
990c2c66affSColin Finck         goto UnlockAndExit;
991c2c66affSColin Finck     }
992c2c66affSColin Finck 
993c2c66affSColin Finck     if (Node->Object)
994c2c66affSColin Finck     {
995c2c66affSColin Finck         Status = AE_ALREADY_EXISTS;
996c2c66affSColin Finck         goto UnlockAndExit;
997c2c66affSColin Finck     }
998c2c66affSColin Finck 
999c2c66affSColin Finck     /*
1000c2c66affSColin Finck      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
1001c2c66affSColin Finck      * is always zero
1002c2c66affSColin Finck      */
1003c2c66affSColin Finck     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
1004c2c66affSColin Finck         GpeBlockAddress->SpaceId, RegisterCount,
1005c2c66affSColin Finck         0, InterruptNumber, &GpeBlock);
1006c2c66affSColin Finck     if (ACPI_FAILURE (Status))
1007c2c66affSColin Finck     {
1008c2c66affSColin Finck         goto UnlockAndExit;
1009c2c66affSColin Finck     }
1010c2c66affSColin Finck 
1011c2c66affSColin Finck     /* Install block in the DeviceObject attached to the node */
1012c2c66affSColin Finck 
1013c2c66affSColin Finck     ObjDesc = AcpiNsGetAttachedObject (Node);
1014c2c66affSColin Finck     if (!ObjDesc)
1015c2c66affSColin Finck     {
1016c2c66affSColin Finck         /*
1017c2c66affSColin Finck          * No object, create a new one (Device nodes do not always have
1018c2c66affSColin Finck          * an attached object)
1019c2c66affSColin Finck          */
1020c2c66affSColin Finck         ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
1021c2c66affSColin Finck         if (!ObjDesc)
1022c2c66affSColin Finck         {
1023c2c66affSColin Finck             Status = AE_NO_MEMORY;
1024c2c66affSColin Finck             goto UnlockAndExit;
1025c2c66affSColin Finck         }
1026c2c66affSColin Finck 
1027c2c66affSColin Finck         Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
1028c2c66affSColin Finck 
1029c2c66affSColin Finck         /* Remove local reference to the object */
1030c2c66affSColin Finck 
1031c2c66affSColin Finck         AcpiUtRemoveReference (ObjDesc);
1032c2c66affSColin Finck         if (ACPI_FAILURE (Status))
1033c2c66affSColin Finck         {
1034c2c66affSColin Finck             goto UnlockAndExit;
1035c2c66affSColin Finck         }
1036c2c66affSColin Finck     }
1037c2c66affSColin Finck 
1038c2c66affSColin Finck     /* Now install the GPE block in the DeviceObject */
1039c2c66affSColin Finck 
1040c2c66affSColin Finck     ObjDesc->Device.GpeBlock = GpeBlock;
1041c2c66affSColin Finck 
1042c2c66affSColin Finck 
1043c2c66affSColin Finck UnlockAndExit:
1044c2c66affSColin Finck     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1045c2c66affSColin Finck     return_ACPI_STATUS (Status);
1046c2c66affSColin Finck }
1047c2c66affSColin Finck 
1048c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
1049c2c66affSColin Finck 
1050c2c66affSColin Finck 
1051c2c66affSColin Finck /*******************************************************************************
1052c2c66affSColin Finck  *
1053c2c66affSColin Finck  * FUNCTION:    AcpiRemoveGpeBlock
1054c2c66affSColin Finck  *
1055c2c66affSColin Finck  * PARAMETERS:  GpeDevice           - Handle to the parent GPE Block Device
1056c2c66affSColin Finck  *
1057c2c66affSColin Finck  * RETURN:      Status
1058c2c66affSColin Finck  *
1059c2c66affSColin Finck  * DESCRIPTION: Remove a previously installed block of GPE registers
1060c2c66affSColin Finck  *
1061c2c66affSColin Finck  ******************************************************************************/
1062c2c66affSColin Finck 
1063c2c66affSColin Finck ACPI_STATUS
1064c2c66affSColin Finck AcpiRemoveGpeBlock (
1065c2c66affSColin Finck     ACPI_HANDLE             GpeDevice)
1066c2c66affSColin Finck {
1067c2c66affSColin Finck     ACPI_OPERAND_OBJECT     *ObjDesc;
1068c2c66affSColin Finck     ACPI_STATUS             Status;
1069c2c66affSColin Finck     ACPI_NAMESPACE_NODE     *Node;
1070c2c66affSColin Finck 
1071c2c66affSColin Finck 
1072c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
1073c2c66affSColin Finck 
1074c2c66affSColin Finck 
1075c2c66affSColin Finck     if (!GpeDevice)
1076c2c66affSColin Finck     {
1077c2c66affSColin Finck         return_ACPI_STATUS (AE_BAD_PARAMETER);
1078c2c66affSColin Finck     }
1079c2c66affSColin Finck 
1080c2c66affSColin Finck     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1081c2c66affSColin Finck     if (ACPI_FAILURE (Status))
1082c2c66affSColin Finck     {
1083c2c66affSColin Finck         return_ACPI_STATUS (Status);
1084c2c66affSColin Finck     }
1085c2c66affSColin Finck 
1086c2c66affSColin Finck     Node = AcpiNsValidateHandle (GpeDevice);
1087c2c66affSColin Finck     if (!Node)
1088c2c66affSColin Finck     {
1089c2c66affSColin Finck         Status = AE_BAD_PARAMETER;
1090c2c66affSColin Finck         goto UnlockAndExit;
1091c2c66affSColin Finck     }
1092c2c66affSColin Finck 
1093c2c66affSColin Finck     /* Validate the parent device */
1094c2c66affSColin Finck 
1095c2c66affSColin Finck     if (Node->Type != ACPI_TYPE_DEVICE)
1096c2c66affSColin Finck     {
1097c2c66affSColin Finck         Status = AE_TYPE;
1098c2c66affSColin Finck         goto UnlockAndExit;
1099c2c66affSColin Finck     }
1100c2c66affSColin Finck 
1101c2c66affSColin Finck     /* Get the DeviceObject attached to the node */
1102c2c66affSColin Finck 
1103c2c66affSColin Finck     ObjDesc = AcpiNsGetAttachedObject (Node);
1104c2c66affSColin Finck     if (!ObjDesc ||
1105c2c66affSColin Finck         !ObjDesc->Device.GpeBlock)
1106c2c66affSColin Finck     {
1107c2c66affSColin Finck         return_ACPI_STATUS (AE_NULL_OBJECT);
1108c2c66affSColin Finck     }
1109c2c66affSColin Finck 
1110c2c66affSColin Finck     /* Delete the GPE block (but not the DeviceObject) */
1111c2c66affSColin Finck 
1112c2c66affSColin Finck     Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
1113c2c66affSColin Finck     if (ACPI_SUCCESS (Status))
1114c2c66affSColin Finck     {
1115c2c66affSColin Finck         ObjDesc->Device.GpeBlock = NULL;
1116c2c66affSColin Finck     }
1117c2c66affSColin Finck 
1118c2c66affSColin Finck UnlockAndExit:
1119c2c66affSColin Finck     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1120c2c66affSColin Finck     return_ACPI_STATUS (Status);
1121c2c66affSColin Finck }
1122c2c66affSColin Finck 
1123c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
1124c2c66affSColin Finck 
1125c2c66affSColin Finck 
1126c2c66affSColin Finck /*******************************************************************************
1127c2c66affSColin Finck  *
1128c2c66affSColin Finck  * FUNCTION:    AcpiGetGpeDevice
1129c2c66affSColin Finck  *
1130c2c66affSColin Finck  * PARAMETERS:  Index               - System GPE index (0-CurrentGpeCount)
1131c2c66affSColin Finck  *              GpeDevice           - Where the parent GPE Device is returned
1132c2c66affSColin Finck  *
1133c2c66affSColin Finck  * RETURN:      Status
1134c2c66affSColin Finck  *
1135c2c66affSColin Finck  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1136c2c66affSColin Finck  *              gpe device indicates that the gpe number is contained in one of
1137c2c66affSColin Finck  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
1138c2c66affSColin Finck  *
1139c2c66affSColin Finck  ******************************************************************************/
1140c2c66affSColin Finck 
1141c2c66affSColin Finck ACPI_STATUS
1142c2c66affSColin Finck AcpiGetGpeDevice (
1143c2c66affSColin Finck     UINT32                  Index,
1144c2c66affSColin Finck     ACPI_HANDLE             *GpeDevice)
1145c2c66affSColin Finck {
1146c2c66affSColin Finck     ACPI_GPE_DEVICE_INFO    Info;
1147c2c66affSColin Finck     ACPI_STATUS             Status;
1148c2c66affSColin Finck 
1149c2c66affSColin Finck 
1150c2c66affSColin Finck     ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
1151c2c66affSColin Finck 
1152c2c66affSColin Finck 
1153c2c66affSColin Finck     if (!GpeDevice)
1154c2c66affSColin Finck     {
1155c2c66affSColin Finck         return_ACPI_STATUS (AE_BAD_PARAMETER);
1156c2c66affSColin Finck     }
1157c2c66affSColin Finck 
1158c2c66affSColin Finck     if (Index >= AcpiCurrentGpeCount)
1159c2c66affSColin Finck     {
1160c2c66affSColin Finck         return_ACPI_STATUS (AE_NOT_EXIST);
1161c2c66affSColin Finck     }
1162c2c66affSColin Finck 
1163c2c66affSColin Finck     /* Setup and walk the GPE list */
1164c2c66affSColin Finck 
1165c2c66affSColin Finck     Info.Index = Index;
1166c2c66affSColin Finck     Info.Status = AE_NOT_EXIST;
1167c2c66affSColin Finck     Info.GpeDevice = NULL;
1168c2c66affSColin Finck     Info.NextBlockBaseIndex = 0;
1169c2c66affSColin Finck 
1170c2c66affSColin Finck     Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
1171c2c66affSColin Finck     if (ACPI_FAILURE (Status))
1172c2c66affSColin Finck     {
1173c2c66affSColin Finck         return_ACPI_STATUS (Status);
1174c2c66affSColin Finck     }
1175c2c66affSColin Finck 
1176c2c66affSColin Finck     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
1177c2c66affSColin Finck     return_ACPI_STATUS (Info.Status);
1178c2c66affSColin Finck }
1179c2c66affSColin Finck 
1180c2c66affSColin Finck ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1181c2c66affSColin Finck 
1182c2c66affSColin Finck #endif /* !ACPI_REDUCED_HARDWARE */
1183