126f3cdf0SGordon Ross /******************************************************************************
226f3cdf0SGordon Ross *
326f3cdf0SGordon Ross * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
426f3cdf0SGordon Ross *
526f3cdf0SGordon Ross *****************************************************************************/
626f3cdf0SGordon Ross
726f3cdf0SGordon Ross /*
8*cb565728SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp.
926f3cdf0SGordon Ross * All rights reserved.
1026f3cdf0SGordon Ross *
1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross * are met:
1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross * without modification.
1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross * binary redistribution.
2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross * from this software without specific prior written permission.
2526f3cdf0SGordon Ross *
2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross * Software Foundation.
2926f3cdf0SGordon Ross *
3026f3cdf0SGordon Ross * NO WARRANTY
3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross */
4326f3cdf0SGordon Ross
44*cb565728SJerry Jelinek #define EXPORT_ACPI_INTERFACES
4526f3cdf0SGordon Ross
4626f3cdf0SGordon Ross #include "acpi.h"
4726f3cdf0SGordon Ross #include "accommon.h"
4826f3cdf0SGordon Ross #include "acevents.h"
4926f3cdf0SGordon Ross #include "acnamesp.h"
5026f3cdf0SGordon Ross
5126f3cdf0SGordon Ross #define _COMPONENT ACPI_EVENTS
5226f3cdf0SGordon Ross ACPI_MODULE_NAME ("evxfgpe")
5326f3cdf0SGordon Ross
5426f3cdf0SGordon Ross
55*cb565728SJerry Jelinek #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
5626f3cdf0SGordon Ross /*******************************************************************************
5726f3cdf0SGordon Ross *
5826f3cdf0SGordon Ross * FUNCTION: AcpiUpdateAllGpes
5926f3cdf0SGordon Ross *
6026f3cdf0SGordon Ross * PARAMETERS: None
6126f3cdf0SGordon Ross *
6226f3cdf0SGordon Ross * RETURN: Status
6326f3cdf0SGordon Ross *
6426f3cdf0SGordon Ross * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
6526f3cdf0SGordon Ross * associated _Lxx or _Exx methods and are not pointed to by any
6626f3cdf0SGordon Ross * device _PRW methods (this indicates that these GPEs are
6726f3cdf0SGordon Ross * generally intended for system or device wakeup. Such GPEs
6826f3cdf0SGordon Ross * have to be enabled directly when the devices whose _PRW
6926f3cdf0SGordon Ross * methods point to them are set up for wakeup signaling.)
7026f3cdf0SGordon Ross *
7126f3cdf0SGordon Ross * NOTE: Should be called after any GPEs are added to the system. Primarily,
7226f3cdf0SGordon Ross * after the system _PRW methods have been run, but also after a GPE Block
7326f3cdf0SGordon Ross * Device has been added or if any new GPE methods have been added via a
7426f3cdf0SGordon Ross * dynamic table load.
7526f3cdf0SGordon Ross *
7626f3cdf0SGordon Ross ******************************************************************************/
7726f3cdf0SGordon Ross
7826f3cdf0SGordon Ross ACPI_STATUS
AcpiUpdateAllGpes(void)7926f3cdf0SGordon Ross AcpiUpdateAllGpes (
8026f3cdf0SGordon Ross void)
8126f3cdf0SGordon Ross {
8226f3cdf0SGordon Ross ACPI_STATUS Status;
8326f3cdf0SGordon Ross
8426f3cdf0SGordon Ross
85*cb565728SJerry Jelinek ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
8626f3cdf0SGordon Ross
8726f3cdf0SGordon Ross
8826f3cdf0SGordon Ross Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
8926f3cdf0SGordon Ross if (ACPI_FAILURE (Status))
9026f3cdf0SGordon Ross {
9126f3cdf0SGordon Ross return_ACPI_STATUS (Status);
9226f3cdf0SGordon Ross }
9326f3cdf0SGordon Ross
9426f3cdf0SGordon Ross if (AcpiGbl_AllGpesInitialized)
9526f3cdf0SGordon Ross {
9626f3cdf0SGordon Ross goto UnlockAndExit;
9726f3cdf0SGordon Ross }
9826f3cdf0SGordon Ross
9926f3cdf0SGordon Ross Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL);
10026f3cdf0SGordon Ross if (ACPI_SUCCESS (Status))
10126f3cdf0SGordon Ross {
10226f3cdf0SGordon Ross AcpiGbl_AllGpesInitialized = TRUE;
10326f3cdf0SGordon Ross }
10426f3cdf0SGordon Ross
10526f3cdf0SGordon Ross UnlockAndExit:
10626f3cdf0SGordon Ross (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
10726f3cdf0SGordon Ross return_ACPI_STATUS (Status);
10826f3cdf0SGordon Ross }
10926f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiUpdateAllGpes)11026f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
11126f3cdf0SGordon Ross
11226f3cdf0SGordon Ross
11326f3cdf0SGordon Ross /*******************************************************************************
11426f3cdf0SGordon Ross *
11526f3cdf0SGordon Ross * FUNCTION: AcpiEnableGpe
11626f3cdf0SGordon Ross *
11726f3cdf0SGordon Ross * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
11826f3cdf0SGordon Ross * GpeNumber - GPE level within the GPE block
11926f3cdf0SGordon Ross *
12026f3cdf0SGordon Ross * RETURN: Status
12126f3cdf0SGordon Ross *
12226f3cdf0SGordon Ross * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
12326f3cdf0SGordon Ross * hardware-enabled.
12426f3cdf0SGordon Ross *
12526f3cdf0SGordon Ross ******************************************************************************/
12626f3cdf0SGordon Ross
12726f3cdf0SGordon Ross ACPI_STATUS
12826f3cdf0SGordon Ross AcpiEnableGpe (
12926f3cdf0SGordon Ross ACPI_HANDLE GpeDevice,
13026f3cdf0SGordon Ross UINT32 GpeNumber)
13126f3cdf0SGordon Ross {
13226f3cdf0SGordon Ross ACPI_STATUS Status = AE_BAD_PARAMETER;
13326f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *GpeEventInfo;
13426f3cdf0SGordon Ross ACPI_CPU_FLAGS Flags;
13526f3cdf0SGordon Ross
13626f3cdf0SGordon Ross
13726f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiEnableGpe);
13826f3cdf0SGordon Ross
13926f3cdf0SGordon Ross
14026f3cdf0SGordon Ross Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
14126f3cdf0SGordon Ross
142*cb565728SJerry Jelinek /*
143*cb565728SJerry Jelinek * Ensure that we have a valid GPE number and that there is some way
144*cb565728SJerry Jelinek * of handling the GPE (handler or a GPE method). In other words, we
145*cb565728SJerry Jelinek * won't allow a valid GPE to be enabled if there is no way to handle it.
146*cb565728SJerry Jelinek */
14726f3cdf0SGordon Ross GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
14826f3cdf0SGordon Ross if (GpeEventInfo)
14926f3cdf0SGordon Ross {
150*cb565728SJerry Jelinek if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
151*cb565728SJerry Jelinek ACPI_GPE_DISPATCH_NONE)
152*cb565728SJerry Jelinek {
15326f3cdf0SGordon Ross Status = AcpiEvAddGpeReference (GpeEventInfo);
15426f3cdf0SGordon Ross }
155*cb565728SJerry Jelinek else
156*cb565728SJerry Jelinek {
157*cb565728SJerry Jelinek Status = AE_NO_HANDLER;
158*cb565728SJerry Jelinek }
159*cb565728SJerry Jelinek }
16026f3cdf0SGordon Ross
16126f3cdf0SGordon Ross AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
16226f3cdf0SGordon Ross return_ACPI_STATUS (Status);
16326f3cdf0SGordon Ross }
16426f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiEnableGpe)16526f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiEnableGpe)
16626f3cdf0SGordon Ross
16726f3cdf0SGordon Ross
16826f3cdf0SGordon Ross /*******************************************************************************
16926f3cdf0SGordon Ross *
17026f3cdf0SGordon Ross * FUNCTION: AcpiDisableGpe
17126f3cdf0SGordon Ross *
17226f3cdf0SGordon Ross * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
17326f3cdf0SGordon Ross * GpeNumber - GPE level within the GPE block
17426f3cdf0SGordon Ross *
17526f3cdf0SGordon Ross * RETURN: Status
17626f3cdf0SGordon Ross *
17726f3cdf0SGordon Ross * DESCRIPTION: Remove a reference to a GPE. When the last reference is
17826f3cdf0SGordon Ross * removed, only then is the GPE disabled (for runtime GPEs), or
17926f3cdf0SGordon Ross * the GPE mask bit disabled (for wake GPEs)
18026f3cdf0SGordon Ross *
18126f3cdf0SGordon Ross ******************************************************************************/
18226f3cdf0SGordon Ross
18326f3cdf0SGordon Ross ACPI_STATUS
18426f3cdf0SGordon Ross AcpiDisableGpe (
18526f3cdf0SGordon Ross ACPI_HANDLE GpeDevice,
18626f3cdf0SGordon Ross UINT32 GpeNumber)
18726f3cdf0SGordon Ross {
18826f3cdf0SGordon Ross ACPI_STATUS Status = AE_BAD_PARAMETER;
18926f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *GpeEventInfo;
19026f3cdf0SGordon Ross ACPI_CPU_FLAGS Flags;
19126f3cdf0SGordon Ross
19226f3cdf0SGordon Ross
19326f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiDisableGpe);
19426f3cdf0SGordon Ross
19526f3cdf0SGordon Ross
19626f3cdf0SGordon Ross Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
19726f3cdf0SGordon Ross
19826f3cdf0SGordon Ross /* Ensure that we have a valid GPE number */
19926f3cdf0SGordon Ross
20026f3cdf0SGordon Ross GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
20126f3cdf0SGordon Ross if (GpeEventInfo)
20226f3cdf0SGordon Ross {
20326f3cdf0SGordon Ross Status = AcpiEvRemoveGpeReference (GpeEventInfo);
20426f3cdf0SGordon Ross }
20526f3cdf0SGordon Ross
20626f3cdf0SGordon Ross AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
20726f3cdf0SGordon Ross return_ACPI_STATUS (Status);
20826f3cdf0SGordon Ross }
20926f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiDisableGpe)21026f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiDisableGpe)
21126f3cdf0SGordon Ross
21226f3cdf0SGordon Ross
21326f3cdf0SGordon Ross /*******************************************************************************
21426f3cdf0SGordon Ross *
21526f3cdf0SGordon Ross * FUNCTION: AcpiSetGpe
21626f3cdf0SGordon Ross *
21726f3cdf0SGordon Ross * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
21826f3cdf0SGordon Ross * GpeNumber - GPE level within the GPE block
21926f3cdf0SGordon Ross * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
22026f3cdf0SGordon Ross *
22126f3cdf0SGordon Ross * RETURN: Status
22226f3cdf0SGordon Ross *
22326f3cdf0SGordon Ross * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
224*cb565728SJerry Jelinek * the reference count mechanism used in the AcpiEnableGpe(),
225*cb565728SJerry Jelinek * AcpiDisableGpe() interfaces.
226*cb565728SJerry Jelinek * This API is typically used by the GPE raw handler mode driver
227*cb565728SJerry Jelinek * to switch between the polling mode and the interrupt mode after
228*cb565728SJerry Jelinek * the driver has enabled the GPE.
229*cb565728SJerry Jelinek * The APIs should be invoked in this order:
230*cb565728SJerry Jelinek * AcpiEnableGpe() <- Ensure the reference count > 0
231*cb565728SJerry Jelinek * AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode
232*cb565728SJerry Jelinek * AcpiSetGpe(ACPI_GPE_ENABLE) <- Leave polling mode
233*cb565728SJerry Jelinek * AcpiDisableGpe() <- Decrease the reference count
23426f3cdf0SGordon Ross *
235*cb565728SJerry Jelinek * Note: If a GPE is shared by 2 silicon components, then both the drivers
236*cb565728SJerry Jelinek * should support GPE polling mode or disabling the GPE for long period
237*cb565728SJerry Jelinek * for one driver may break the other. So use it with care since all
238*cb565728SJerry Jelinek * firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
23926f3cdf0SGordon Ross *
24026f3cdf0SGordon Ross ******************************************************************************/
24126f3cdf0SGordon Ross
24226f3cdf0SGordon Ross ACPI_STATUS
24326f3cdf0SGordon Ross AcpiSetGpe (
24426f3cdf0SGordon Ross ACPI_HANDLE GpeDevice,
24526f3cdf0SGordon Ross UINT32 GpeNumber,
24626f3cdf0SGordon Ross UINT8 Action)
24726f3cdf0SGordon Ross {
24826f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *GpeEventInfo;
24926f3cdf0SGordon Ross ACPI_STATUS Status;
25026f3cdf0SGordon Ross ACPI_CPU_FLAGS Flags;
25126f3cdf0SGordon Ross
25226f3cdf0SGordon Ross
25326f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiSetGpe);
25426f3cdf0SGordon Ross
25526f3cdf0SGordon Ross
25626f3cdf0SGordon Ross Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
25726f3cdf0SGordon Ross
25826f3cdf0SGordon Ross /* Ensure that we have a valid GPE number */
25926f3cdf0SGordon Ross
26026f3cdf0SGordon Ross GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
26126f3cdf0SGordon Ross if (!GpeEventInfo)
26226f3cdf0SGordon Ross {
26326f3cdf0SGordon Ross Status = AE_BAD_PARAMETER;
26426f3cdf0SGordon Ross goto UnlockAndExit;
26526f3cdf0SGordon Ross }
26626f3cdf0SGordon Ross
26726f3cdf0SGordon Ross /* Perform the action */
26826f3cdf0SGordon Ross
26926f3cdf0SGordon Ross switch (Action)
27026f3cdf0SGordon Ross {
27126f3cdf0SGordon Ross case ACPI_GPE_ENABLE:
272*cb565728SJerry Jelinek
273*cb565728SJerry Jelinek Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
27426f3cdf0SGordon Ross break;
27526f3cdf0SGordon Ross
27626f3cdf0SGordon Ross case ACPI_GPE_DISABLE:
277*cb565728SJerry Jelinek
27826f3cdf0SGordon Ross Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
27926f3cdf0SGordon Ross break;
28026f3cdf0SGordon Ross
28126f3cdf0SGordon Ross default:
282*cb565728SJerry Jelinek
28326f3cdf0SGordon Ross Status = AE_BAD_PARAMETER;
28426f3cdf0SGordon Ross break;
28526f3cdf0SGordon Ross }
28626f3cdf0SGordon Ross
28726f3cdf0SGordon Ross UnlockAndExit:
28826f3cdf0SGordon Ross AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
28926f3cdf0SGordon Ross return_ACPI_STATUS (Status);
29026f3cdf0SGordon Ross }
29126f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiSetGpe)29226f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiSetGpe)
29326f3cdf0SGordon Ross
29426f3cdf0SGordon Ross
29526f3cdf0SGordon Ross /*******************************************************************************
29626f3cdf0SGordon Ross *
297*cb565728SJerry Jelinek * FUNCTION: AcpiMarkGpeForWake
298*cb565728SJerry Jelinek *
299*cb565728SJerry Jelinek * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
300*cb565728SJerry Jelinek * GpeNumber - GPE level within the GPE block
301*cb565728SJerry Jelinek *
302*cb565728SJerry Jelinek * RETURN: Status
303*cb565728SJerry Jelinek *
304*cb565728SJerry Jelinek * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
305*cb565728SJerry Jelinek * sets the ACPI_GPE_CAN_WAKE flag.
306*cb565728SJerry Jelinek *
307*cb565728SJerry Jelinek * Some potential callers of AcpiSetupGpeForWake may know in advance that
308*cb565728SJerry Jelinek * there won't be any notify handlers installed for device wake notifications
309*cb565728SJerry Jelinek * from the given GPE (one example is a button GPE in Linux). For these cases,
310*cb565728SJerry Jelinek * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.
311*cb565728SJerry Jelinek * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
312*cb565728SJerry Jelinek * setup implicit wake notification for it (since there's no handler method).
313*cb565728SJerry Jelinek *
314*cb565728SJerry Jelinek ******************************************************************************/
315*cb565728SJerry Jelinek
316*cb565728SJerry Jelinek ACPI_STATUS
317*cb565728SJerry Jelinek AcpiMarkGpeForWake (
318*cb565728SJerry Jelinek ACPI_HANDLE GpeDevice,
319*cb565728SJerry Jelinek UINT32 GpeNumber)
320*cb565728SJerry Jelinek {
321*cb565728SJerry Jelinek ACPI_GPE_EVENT_INFO *GpeEventInfo;
322*cb565728SJerry Jelinek ACPI_STATUS Status = AE_BAD_PARAMETER;
323*cb565728SJerry Jelinek ACPI_CPU_FLAGS Flags;
324*cb565728SJerry Jelinek
325*cb565728SJerry Jelinek
326*cb565728SJerry Jelinek ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);
327*cb565728SJerry Jelinek
328*cb565728SJerry Jelinek
329*cb565728SJerry Jelinek Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
330*cb565728SJerry Jelinek
331*cb565728SJerry Jelinek /* Ensure that we have a valid GPE number */
332*cb565728SJerry Jelinek
333*cb565728SJerry Jelinek GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
334*cb565728SJerry Jelinek if (GpeEventInfo)
335*cb565728SJerry Jelinek {
336*cb565728SJerry Jelinek /* Mark the GPE as a possible wake event */
337*cb565728SJerry Jelinek
338*cb565728SJerry Jelinek GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
339*cb565728SJerry Jelinek Status = AE_OK;
340*cb565728SJerry Jelinek }
341*cb565728SJerry Jelinek
342*cb565728SJerry Jelinek AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
343*cb565728SJerry Jelinek return_ACPI_STATUS (Status);
344*cb565728SJerry Jelinek }
345*cb565728SJerry Jelinek
ACPI_EXPORT_SYMBOL(AcpiMarkGpeForWake)346*cb565728SJerry Jelinek ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)
347*cb565728SJerry Jelinek
348*cb565728SJerry Jelinek
349*cb565728SJerry Jelinek /*******************************************************************************
350*cb565728SJerry Jelinek *
35126f3cdf0SGordon Ross * FUNCTION: AcpiSetupGpeForWake
35226f3cdf0SGordon Ross *
35326f3cdf0SGordon Ross * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW)
35426f3cdf0SGordon Ross * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
35526f3cdf0SGordon Ross * GpeNumber - GPE level within the GPE block
35626f3cdf0SGordon Ross *
35726f3cdf0SGordon Ross * RETURN: Status
35826f3cdf0SGordon Ross *
35926f3cdf0SGordon Ross * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
36026f3cdf0SGordon Ross * interface is intended to be used as the host executes the
36126f3cdf0SGordon Ross * _PRW methods (Power Resources for Wake) in the system tables.
36226f3cdf0SGordon Ross * Each _PRW appears under a Device Object (The WakeDevice), and
36326f3cdf0SGordon Ross * contains the info for the wake GPE associated with the
36426f3cdf0SGordon Ross * WakeDevice.
36526f3cdf0SGordon Ross *
36626f3cdf0SGordon Ross ******************************************************************************/
36726f3cdf0SGordon Ross
36826f3cdf0SGordon Ross ACPI_STATUS
36926f3cdf0SGordon Ross AcpiSetupGpeForWake (
37026f3cdf0SGordon Ross ACPI_HANDLE WakeDevice,
37126f3cdf0SGordon Ross ACPI_HANDLE GpeDevice,
37226f3cdf0SGordon Ross UINT32 GpeNumber)
37326f3cdf0SGordon Ross {
374*cb565728SJerry Jelinek ACPI_STATUS Status;
37526f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *GpeEventInfo;
37626f3cdf0SGordon Ross ACPI_NAMESPACE_NODE *DeviceNode;
377*cb565728SJerry Jelinek ACPI_GPE_NOTIFY_INFO *Notify;
378*cb565728SJerry Jelinek ACPI_GPE_NOTIFY_INFO *NewNotify;
37926f3cdf0SGordon Ross ACPI_CPU_FLAGS Flags;
38026f3cdf0SGordon Ross
38126f3cdf0SGordon Ross
38226f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
38326f3cdf0SGordon Ross
38426f3cdf0SGordon Ross
38526f3cdf0SGordon Ross /* Parameter Validation */
38626f3cdf0SGordon Ross
38726f3cdf0SGordon Ross if (!WakeDevice)
38826f3cdf0SGordon Ross {
38926f3cdf0SGordon Ross /*
39026f3cdf0SGordon Ross * By forcing WakeDevice to be valid, we automatically enable the
39126f3cdf0SGordon Ross * implicit notify feature on all hosts.
39226f3cdf0SGordon Ross */
39326f3cdf0SGordon Ross return_ACPI_STATUS (AE_BAD_PARAMETER);
39426f3cdf0SGordon Ross }
39526f3cdf0SGordon Ross
39626f3cdf0SGordon Ross /* Handle root object case */
39726f3cdf0SGordon Ross
39826f3cdf0SGordon Ross if (WakeDevice == ACPI_ROOT_OBJECT)
39926f3cdf0SGordon Ross {
40026f3cdf0SGordon Ross DeviceNode = AcpiGbl_RootNode;
40126f3cdf0SGordon Ross }
40226f3cdf0SGordon Ross else
40326f3cdf0SGordon Ross {
40426f3cdf0SGordon Ross DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
40526f3cdf0SGordon Ross }
40626f3cdf0SGordon Ross
40726f3cdf0SGordon Ross /* Validate WakeDevice is of type Device */
40826f3cdf0SGordon Ross
40926f3cdf0SGordon Ross if (DeviceNode->Type != ACPI_TYPE_DEVICE)
41026f3cdf0SGordon Ross {
41126f3cdf0SGordon Ross return_ACPI_STATUS (AE_BAD_PARAMETER);
41226f3cdf0SGordon Ross }
41326f3cdf0SGordon Ross
414*cb565728SJerry Jelinek /*
415*cb565728SJerry Jelinek * Allocate a new notify object up front, in case it is needed.
416*cb565728SJerry Jelinek * Memory allocation while holding a spinlock is a big no-no
417*cb565728SJerry Jelinek * on some hosts.
418*cb565728SJerry Jelinek */
419*cb565728SJerry Jelinek NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
420*cb565728SJerry Jelinek if (!NewNotify)
421*cb565728SJerry Jelinek {
422*cb565728SJerry Jelinek return_ACPI_STATUS (AE_NO_MEMORY);
423*cb565728SJerry Jelinek }
424*cb565728SJerry Jelinek
42526f3cdf0SGordon Ross Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
42626f3cdf0SGordon Ross
42726f3cdf0SGordon Ross /* Ensure that we have a valid GPE number */
42826f3cdf0SGordon Ross
42926f3cdf0SGordon Ross GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
430*cb565728SJerry Jelinek if (!GpeEventInfo)
43126f3cdf0SGordon Ross {
432*cb565728SJerry Jelinek Status = AE_BAD_PARAMETER;
433*cb565728SJerry Jelinek goto UnlockAndExit;
434*cb565728SJerry Jelinek }
435*cb565728SJerry Jelinek
43626f3cdf0SGordon Ross /*
43726f3cdf0SGordon Ross * If there is no method or handler for this GPE, then the
438*cb565728SJerry Jelinek * WakeDevice will be notified whenever this GPE fires. This is
439*cb565728SJerry Jelinek * known as an "implicit notify". Note: The GPE is assumed to be
44026f3cdf0SGordon Ross * level-triggered (for windows compatibility).
44126f3cdf0SGordon Ross */
442*cb565728SJerry Jelinek if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
44326f3cdf0SGordon Ross ACPI_GPE_DISPATCH_NONE)
44426f3cdf0SGordon Ross {
445*cb565728SJerry Jelinek /*
446*cb565728SJerry Jelinek * This is the first device for implicit notify on this GPE.
447*cb565728SJerry Jelinek * Just set the flags here, and enter the NOTIFY block below.
448*cb565728SJerry Jelinek */
44926f3cdf0SGordon Ross GpeEventInfo->Flags =
45026f3cdf0SGordon Ross (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
45126f3cdf0SGordon Ross }
45226f3cdf0SGordon Ross
453*cb565728SJerry Jelinek /*
454*cb565728SJerry Jelinek * If we already have an implicit notify on this GPE, add
455*cb565728SJerry Jelinek * this device to the notify list.
456*cb565728SJerry Jelinek */
457*cb565728SJerry Jelinek if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
458*cb565728SJerry Jelinek ACPI_GPE_DISPATCH_NOTIFY)
459*cb565728SJerry Jelinek {
460*cb565728SJerry Jelinek /* Ensure that the device is not already in the list */
461*cb565728SJerry Jelinek
462*cb565728SJerry Jelinek Notify = GpeEventInfo->Dispatch.NotifyList;
463*cb565728SJerry Jelinek while (Notify)
464*cb565728SJerry Jelinek {
465*cb565728SJerry Jelinek if (Notify->DeviceNode == DeviceNode)
466*cb565728SJerry Jelinek {
467*cb565728SJerry Jelinek Status = AE_ALREADY_EXISTS;
468*cb565728SJerry Jelinek goto UnlockAndExit;
469*cb565728SJerry Jelinek }
470*cb565728SJerry Jelinek Notify = Notify->Next;
471*cb565728SJerry Jelinek }
472*cb565728SJerry Jelinek
473*cb565728SJerry Jelinek /* Add this device to the notify list for this GPE */
474*cb565728SJerry Jelinek
475*cb565728SJerry Jelinek NewNotify->DeviceNode = DeviceNode;
476*cb565728SJerry Jelinek NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
477*cb565728SJerry Jelinek GpeEventInfo->Dispatch.NotifyList = NewNotify;
478*cb565728SJerry Jelinek NewNotify = NULL;
479*cb565728SJerry Jelinek }
480*cb565728SJerry Jelinek
481*cb565728SJerry Jelinek /* Mark the GPE as a possible wake event */
482*cb565728SJerry Jelinek
48326f3cdf0SGordon Ross GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
48426f3cdf0SGordon Ross Status = AE_OK;
48526f3cdf0SGordon Ross
486*cb565728SJerry Jelinek
487*cb565728SJerry Jelinek UnlockAndExit:
48826f3cdf0SGordon Ross AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
489*cb565728SJerry Jelinek
490*cb565728SJerry Jelinek /* Delete the notify object if it was not used above */
491*cb565728SJerry Jelinek
492*cb565728SJerry Jelinek if (NewNotify)
493*cb565728SJerry Jelinek {
494*cb565728SJerry Jelinek ACPI_FREE (NewNotify);
495*cb565728SJerry Jelinek }
49626f3cdf0SGordon Ross return_ACPI_STATUS (Status);
49726f3cdf0SGordon Ross }
49826f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiSetupGpeForWake)49926f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
50026f3cdf0SGordon Ross
50126f3cdf0SGordon Ross
50226f3cdf0SGordon Ross /*******************************************************************************
50326f3cdf0SGordon Ross *
50426f3cdf0SGordon Ross * FUNCTION: AcpiSetGpeWakeMask
50526f3cdf0SGordon Ross *
50626f3cdf0SGordon Ross * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
50726f3cdf0SGordon Ross * GpeNumber - GPE level within the GPE block
50826f3cdf0SGordon Ross * Action - Enable or Disable
50926f3cdf0SGordon Ross *
51026f3cdf0SGordon Ross * RETURN: Status
51126f3cdf0SGordon Ross *
51226f3cdf0SGordon Ross * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
51326f3cdf0SGordon Ross * already be marked as a WAKE GPE.
51426f3cdf0SGordon Ross *
51526f3cdf0SGordon Ross ******************************************************************************/
51626f3cdf0SGordon Ross
51726f3cdf0SGordon Ross ACPI_STATUS
51826f3cdf0SGordon Ross AcpiSetGpeWakeMask (
51926f3cdf0SGordon Ross ACPI_HANDLE GpeDevice,
52026f3cdf0SGordon Ross UINT32 GpeNumber,
52126f3cdf0SGordon Ross UINT8 Action)
52226f3cdf0SGordon Ross {
52326f3cdf0SGordon Ross ACPI_STATUS Status = AE_OK;
52426f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *GpeEventInfo;
52526f3cdf0SGordon Ross ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
52626f3cdf0SGordon Ross ACPI_CPU_FLAGS Flags;
52726f3cdf0SGordon Ross UINT32 RegisterBit;
52826f3cdf0SGordon Ross
52926f3cdf0SGordon Ross
53026f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
53126f3cdf0SGordon Ross
53226f3cdf0SGordon Ross
53326f3cdf0SGordon Ross Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
53426f3cdf0SGordon Ross
53526f3cdf0SGordon Ross /*
53626f3cdf0SGordon Ross * Ensure that we have a valid GPE number and that this GPE is in
53726f3cdf0SGordon Ross * fact a wake GPE
53826f3cdf0SGordon Ross */
53926f3cdf0SGordon Ross GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
54026f3cdf0SGordon Ross if (!GpeEventInfo)
54126f3cdf0SGordon Ross {
54226f3cdf0SGordon Ross Status = AE_BAD_PARAMETER;
54326f3cdf0SGordon Ross goto UnlockAndExit;
54426f3cdf0SGordon Ross }
54526f3cdf0SGordon Ross
54626f3cdf0SGordon Ross if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
54726f3cdf0SGordon Ross {
54826f3cdf0SGordon Ross Status = AE_TYPE;
54926f3cdf0SGordon Ross goto UnlockAndExit;
55026f3cdf0SGordon Ross }
55126f3cdf0SGordon Ross
55226f3cdf0SGordon Ross GpeRegisterInfo = GpeEventInfo->RegisterInfo;
55326f3cdf0SGordon Ross if (!GpeRegisterInfo)
55426f3cdf0SGordon Ross {
55526f3cdf0SGordon Ross Status = AE_NOT_EXIST;
55626f3cdf0SGordon Ross goto UnlockAndExit;
55726f3cdf0SGordon Ross }
55826f3cdf0SGordon Ross
559*cb565728SJerry Jelinek RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
56026f3cdf0SGordon Ross
56126f3cdf0SGordon Ross /* Perform the action */
56226f3cdf0SGordon Ross
56326f3cdf0SGordon Ross switch (Action)
56426f3cdf0SGordon Ross {
56526f3cdf0SGordon Ross case ACPI_GPE_ENABLE:
566*cb565728SJerry Jelinek
56726f3cdf0SGordon Ross ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
56826f3cdf0SGordon Ross break;
56926f3cdf0SGordon Ross
57026f3cdf0SGordon Ross case ACPI_GPE_DISABLE:
571*cb565728SJerry Jelinek
57226f3cdf0SGordon Ross ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
57326f3cdf0SGordon Ross break;
57426f3cdf0SGordon Ross
57526f3cdf0SGordon Ross default:
576*cb565728SJerry Jelinek
57726f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
57826f3cdf0SGordon Ross Status = AE_BAD_PARAMETER;
57926f3cdf0SGordon Ross break;
58026f3cdf0SGordon Ross }
58126f3cdf0SGordon Ross
58226f3cdf0SGordon Ross UnlockAndExit:
58326f3cdf0SGordon Ross AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
58426f3cdf0SGordon Ross return_ACPI_STATUS (Status);
58526f3cdf0SGordon Ross }
58626f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiSetGpeWakeMask)58726f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
58826f3cdf0SGordon Ross
58926f3cdf0SGordon Ross
59026f3cdf0SGordon Ross /*******************************************************************************
59126f3cdf0SGordon Ross *
59226f3cdf0SGordon Ross * FUNCTION: AcpiClearGpe
59326f3cdf0SGordon Ross *
59426f3cdf0SGordon Ross * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
59526f3cdf0SGordon Ross * GpeNumber - GPE level within the GPE block
59626f3cdf0SGordon Ross *
59726f3cdf0SGordon Ross * RETURN: Status
59826f3cdf0SGordon Ross *
59926f3cdf0SGordon Ross * DESCRIPTION: Clear an ACPI event (general purpose)
60026f3cdf0SGordon Ross *
60126f3cdf0SGordon Ross ******************************************************************************/
60226f3cdf0SGordon Ross
60326f3cdf0SGordon Ross ACPI_STATUS
60426f3cdf0SGordon Ross AcpiClearGpe (
60526f3cdf0SGordon Ross ACPI_HANDLE GpeDevice,
60626f3cdf0SGordon Ross UINT32 GpeNumber)
60726f3cdf0SGordon Ross {
60826f3cdf0SGordon Ross ACPI_STATUS Status = AE_OK;
60926f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *GpeEventInfo;
61026f3cdf0SGordon Ross ACPI_CPU_FLAGS Flags;
61126f3cdf0SGordon Ross
61226f3cdf0SGordon Ross
61326f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiClearGpe);
61426f3cdf0SGordon Ross
61526f3cdf0SGordon Ross
61626f3cdf0SGordon Ross Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
61726f3cdf0SGordon Ross
61826f3cdf0SGordon Ross /* Ensure that we have a valid GPE number */
61926f3cdf0SGordon Ross
62026f3cdf0SGordon Ross GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
62126f3cdf0SGordon Ross if (!GpeEventInfo)
62226f3cdf0SGordon Ross {
62326f3cdf0SGordon Ross Status = AE_BAD_PARAMETER;
62426f3cdf0SGordon Ross goto UnlockAndExit;
62526f3cdf0SGordon Ross }
62626f3cdf0SGordon Ross
62726f3cdf0SGordon Ross Status = AcpiHwClearGpe (GpeEventInfo);
62826f3cdf0SGordon Ross
62926f3cdf0SGordon Ross UnlockAndExit:
63026f3cdf0SGordon Ross AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
63126f3cdf0SGordon Ross return_ACPI_STATUS (Status);
63226f3cdf0SGordon Ross }
63326f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiClearGpe)63426f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiClearGpe)
63526f3cdf0SGordon Ross
63626f3cdf0SGordon Ross
63726f3cdf0SGordon Ross /*******************************************************************************
63826f3cdf0SGordon Ross *
63926f3cdf0SGordon Ross * FUNCTION: AcpiGetGpeStatus
64026f3cdf0SGordon Ross *
64126f3cdf0SGordon Ross * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
64226f3cdf0SGordon Ross * GpeNumber - GPE level within the GPE block
64326f3cdf0SGordon Ross * EventStatus - Where the current status of the event
64426f3cdf0SGordon Ross * will be returned
64526f3cdf0SGordon Ross *
64626f3cdf0SGordon Ross * RETURN: Status
64726f3cdf0SGordon Ross *
64826f3cdf0SGordon Ross * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
64926f3cdf0SGordon Ross *
65026f3cdf0SGordon Ross ******************************************************************************/
65126f3cdf0SGordon Ross
65226f3cdf0SGordon Ross ACPI_STATUS
65326f3cdf0SGordon Ross AcpiGetGpeStatus (
65426f3cdf0SGordon Ross ACPI_HANDLE GpeDevice,
65526f3cdf0SGordon Ross UINT32 GpeNumber,
65626f3cdf0SGordon Ross ACPI_EVENT_STATUS *EventStatus)
65726f3cdf0SGordon Ross {
65826f3cdf0SGordon Ross ACPI_STATUS Status = AE_OK;
65926f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *GpeEventInfo;
66026f3cdf0SGordon Ross ACPI_CPU_FLAGS Flags;
66126f3cdf0SGordon Ross
66226f3cdf0SGordon Ross
66326f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);
66426f3cdf0SGordon Ross
66526f3cdf0SGordon Ross
66626f3cdf0SGordon Ross Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
66726f3cdf0SGordon Ross
66826f3cdf0SGordon Ross /* Ensure that we have a valid GPE number */
66926f3cdf0SGordon Ross
67026f3cdf0SGordon Ross GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
67126f3cdf0SGordon Ross if (!GpeEventInfo)
67226f3cdf0SGordon Ross {
67326f3cdf0SGordon Ross Status = AE_BAD_PARAMETER;
67426f3cdf0SGordon Ross goto UnlockAndExit;
67526f3cdf0SGordon Ross }
67626f3cdf0SGordon Ross
67726f3cdf0SGordon Ross /* Obtain status on the requested GPE number */
67826f3cdf0SGordon Ross
67926f3cdf0SGordon Ross Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);
68026f3cdf0SGordon Ross
68126f3cdf0SGordon Ross UnlockAndExit:
68226f3cdf0SGordon Ross AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
68326f3cdf0SGordon Ross return_ACPI_STATUS (Status);
68426f3cdf0SGordon Ross }
68526f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiGetGpeStatus)68626f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)
68726f3cdf0SGordon Ross
68826f3cdf0SGordon Ross
68926f3cdf0SGordon Ross /*******************************************************************************
69026f3cdf0SGordon Ross *
69126f3cdf0SGordon Ross * FUNCTION: AcpiFinishGpe
69226f3cdf0SGordon Ross *
69326f3cdf0SGordon Ross * PARAMETERS: GpeDevice - Namespace node for the GPE Block
69426f3cdf0SGordon Ross * (NULL for FADT defined GPEs)
69526f3cdf0SGordon Ross * GpeNumber - GPE level within the GPE block
69626f3cdf0SGordon Ross *
69726f3cdf0SGordon Ross * RETURN: Status
69826f3cdf0SGordon Ross *
69926f3cdf0SGordon Ross * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
70026f3cdf0SGordon Ross * processing. Intended for use by asynchronous host-installed
70126f3cdf0SGordon Ross * GPE handlers. The GPE is only reenabled if the EnableForRun bit
70226f3cdf0SGordon Ross * is set in the GPE info.
70326f3cdf0SGordon Ross *
70426f3cdf0SGordon Ross ******************************************************************************/
70526f3cdf0SGordon Ross
70626f3cdf0SGordon Ross ACPI_STATUS
70726f3cdf0SGordon Ross AcpiFinishGpe (
70826f3cdf0SGordon Ross ACPI_HANDLE GpeDevice,
70926f3cdf0SGordon Ross UINT32 GpeNumber)
71026f3cdf0SGordon Ross {
71126f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *GpeEventInfo;
71226f3cdf0SGordon Ross ACPI_STATUS Status;
71326f3cdf0SGordon Ross ACPI_CPU_FLAGS Flags;
71426f3cdf0SGordon Ross
71526f3cdf0SGordon Ross
71626f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiFinishGpe);
71726f3cdf0SGordon Ross
71826f3cdf0SGordon Ross
71926f3cdf0SGordon Ross Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
72026f3cdf0SGordon Ross
72126f3cdf0SGordon Ross /* Ensure that we have a valid GPE number */
72226f3cdf0SGordon Ross
72326f3cdf0SGordon Ross GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
72426f3cdf0SGordon Ross if (!GpeEventInfo)
72526f3cdf0SGordon Ross {
72626f3cdf0SGordon Ross Status = AE_BAD_PARAMETER;
72726f3cdf0SGordon Ross goto UnlockAndExit;
72826f3cdf0SGordon Ross }
72926f3cdf0SGordon Ross
73026f3cdf0SGordon Ross Status = AcpiEvFinishGpe (GpeEventInfo);
73126f3cdf0SGordon Ross
73226f3cdf0SGordon Ross UnlockAndExit:
73326f3cdf0SGordon Ross AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
73426f3cdf0SGordon Ross return_ACPI_STATUS (Status);
73526f3cdf0SGordon Ross }
73626f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiFinishGpe)73726f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
73826f3cdf0SGordon Ross
73926f3cdf0SGordon Ross
74026f3cdf0SGordon Ross /******************************************************************************
74126f3cdf0SGordon Ross *
74226f3cdf0SGordon Ross * FUNCTION: AcpiDisableAllGpes
74326f3cdf0SGordon Ross *
74426f3cdf0SGordon Ross * PARAMETERS: None
74526f3cdf0SGordon Ross *
74626f3cdf0SGordon Ross * RETURN: Status
74726f3cdf0SGordon Ross *
74826f3cdf0SGordon Ross * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
74926f3cdf0SGordon Ross *
75026f3cdf0SGordon Ross ******************************************************************************/
75126f3cdf0SGordon Ross
75226f3cdf0SGordon Ross ACPI_STATUS
75326f3cdf0SGordon Ross AcpiDisableAllGpes (
75426f3cdf0SGordon Ross void)
75526f3cdf0SGordon Ross {
75626f3cdf0SGordon Ross ACPI_STATUS Status;
75726f3cdf0SGordon Ross
75826f3cdf0SGordon Ross
75926f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);
76026f3cdf0SGordon Ross
76126f3cdf0SGordon Ross
76226f3cdf0SGordon Ross Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
76326f3cdf0SGordon Ross if (ACPI_FAILURE (Status))
76426f3cdf0SGordon Ross {
76526f3cdf0SGordon Ross return_ACPI_STATUS (Status);
76626f3cdf0SGordon Ross }
76726f3cdf0SGordon Ross
76826f3cdf0SGordon Ross Status = AcpiHwDisableAllGpes ();
76926f3cdf0SGordon Ross (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
77026f3cdf0SGordon Ross
77126f3cdf0SGordon Ross return_ACPI_STATUS (Status);
77226f3cdf0SGordon Ross }
77326f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiDisableAllGpes)77426f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
77526f3cdf0SGordon Ross
77626f3cdf0SGordon Ross
77726f3cdf0SGordon Ross /******************************************************************************
77826f3cdf0SGordon Ross *
77926f3cdf0SGordon Ross * FUNCTION: AcpiEnableAllRuntimeGpes
78026f3cdf0SGordon Ross *
78126f3cdf0SGordon Ross * PARAMETERS: None
78226f3cdf0SGordon Ross *
78326f3cdf0SGordon Ross * RETURN: Status
78426f3cdf0SGordon Ross *
78526f3cdf0SGordon Ross * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
78626f3cdf0SGordon Ross *
78726f3cdf0SGordon Ross ******************************************************************************/
78826f3cdf0SGordon Ross
78926f3cdf0SGordon Ross ACPI_STATUS
79026f3cdf0SGordon Ross AcpiEnableAllRuntimeGpes (
79126f3cdf0SGordon Ross void)
79226f3cdf0SGordon Ross {
79326f3cdf0SGordon Ross ACPI_STATUS Status;
79426f3cdf0SGordon Ross
79526f3cdf0SGordon Ross
79626f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);
79726f3cdf0SGordon Ross
79826f3cdf0SGordon Ross
79926f3cdf0SGordon Ross Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
80026f3cdf0SGordon Ross if (ACPI_FAILURE (Status))
80126f3cdf0SGordon Ross {
80226f3cdf0SGordon Ross return_ACPI_STATUS (Status);
80326f3cdf0SGordon Ross }
80426f3cdf0SGordon Ross
80526f3cdf0SGordon Ross Status = AcpiHwEnableAllRuntimeGpes ();
80626f3cdf0SGordon Ross (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
80726f3cdf0SGordon Ross
80826f3cdf0SGordon Ross return_ACPI_STATUS (Status);
80926f3cdf0SGordon Ross }
81026f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiEnableAllRuntimeGpes)81126f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
81226f3cdf0SGordon Ross
81326f3cdf0SGordon Ross
814*cb565728SJerry Jelinek /******************************************************************************
815*cb565728SJerry Jelinek *
816*cb565728SJerry Jelinek * FUNCTION: AcpiEnableAllWakeupGpes
817*cb565728SJerry Jelinek *
818*cb565728SJerry Jelinek * PARAMETERS: None
819*cb565728SJerry Jelinek *
820*cb565728SJerry Jelinek * RETURN: Status
821*cb565728SJerry Jelinek *
822*cb565728SJerry Jelinek * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
823*cb565728SJerry Jelinek * all GPE blocks.
824*cb565728SJerry Jelinek *
825*cb565728SJerry Jelinek ******************************************************************************/
826*cb565728SJerry Jelinek
827*cb565728SJerry Jelinek ACPI_STATUS
828*cb565728SJerry Jelinek AcpiEnableAllWakeupGpes (
829*cb565728SJerry Jelinek void)
830*cb565728SJerry Jelinek {
831*cb565728SJerry Jelinek ACPI_STATUS Status;
832*cb565728SJerry Jelinek
833*cb565728SJerry Jelinek
834*cb565728SJerry Jelinek ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);
835*cb565728SJerry Jelinek
836*cb565728SJerry Jelinek
837*cb565728SJerry Jelinek Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
838*cb565728SJerry Jelinek if (ACPI_FAILURE (Status))
839*cb565728SJerry Jelinek {
840*cb565728SJerry Jelinek return_ACPI_STATUS (Status);
841*cb565728SJerry Jelinek }
842*cb565728SJerry Jelinek
843*cb565728SJerry Jelinek Status = AcpiHwEnableAllWakeupGpes ();
844*cb565728SJerry Jelinek (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
845*cb565728SJerry Jelinek
846*cb565728SJerry Jelinek return_ACPI_STATUS (Status);
847*cb565728SJerry Jelinek }
848*cb565728SJerry Jelinek
ACPI_EXPORT_SYMBOL(AcpiEnableAllWakeupGpes)849*cb565728SJerry Jelinek ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)
850*cb565728SJerry Jelinek
851*cb565728SJerry Jelinek
85226f3cdf0SGordon Ross /*******************************************************************************
85326f3cdf0SGordon Ross *
85426f3cdf0SGordon Ross * FUNCTION: AcpiInstallGpeBlock
85526f3cdf0SGordon Ross *
85626f3cdf0SGordon Ross * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device
85726f3cdf0SGordon Ross * GpeBlockAddress - Address and SpaceID
85826f3cdf0SGordon Ross * RegisterCount - Number of GPE register pairs in the block
85926f3cdf0SGordon Ross * InterruptNumber - H/W interrupt for the block
86026f3cdf0SGordon Ross *
86126f3cdf0SGordon Ross * RETURN: Status
86226f3cdf0SGordon Ross *
86326f3cdf0SGordon Ross * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
86426f3cdf0SGordon Ross * enabled here.
86526f3cdf0SGordon Ross *
86626f3cdf0SGordon Ross ******************************************************************************/
86726f3cdf0SGordon Ross
86826f3cdf0SGordon Ross ACPI_STATUS
86926f3cdf0SGordon Ross AcpiInstallGpeBlock (
87026f3cdf0SGordon Ross ACPI_HANDLE GpeDevice,
87126f3cdf0SGordon Ross ACPI_GENERIC_ADDRESS *GpeBlockAddress,
87226f3cdf0SGordon Ross UINT32 RegisterCount,
87326f3cdf0SGordon Ross UINT32 InterruptNumber)
87426f3cdf0SGordon Ross {
87526f3cdf0SGordon Ross ACPI_STATUS Status;
87626f3cdf0SGordon Ross ACPI_OPERAND_OBJECT *ObjDesc;
87726f3cdf0SGordon Ross ACPI_NAMESPACE_NODE *Node;
87826f3cdf0SGordon Ross ACPI_GPE_BLOCK_INFO *GpeBlock;
87926f3cdf0SGordon Ross
88026f3cdf0SGordon Ross
88126f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);
88226f3cdf0SGordon Ross
88326f3cdf0SGordon Ross
88426f3cdf0SGordon Ross if ((!GpeDevice) ||
88526f3cdf0SGordon Ross (!GpeBlockAddress) ||
88626f3cdf0SGordon Ross (!RegisterCount))
88726f3cdf0SGordon Ross {
88826f3cdf0SGordon Ross return_ACPI_STATUS (AE_BAD_PARAMETER);
88926f3cdf0SGordon Ross }
89026f3cdf0SGordon Ross
89126f3cdf0SGordon Ross Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
89226f3cdf0SGordon Ross if (ACPI_FAILURE (Status))
89326f3cdf0SGordon Ross {
894*cb565728SJerry Jelinek return_ACPI_STATUS (Status);
89526f3cdf0SGordon Ross }
89626f3cdf0SGordon Ross
89726f3cdf0SGordon Ross Node = AcpiNsValidateHandle (GpeDevice);
89826f3cdf0SGordon Ross if (!Node)
89926f3cdf0SGordon Ross {
90026f3cdf0SGordon Ross Status = AE_BAD_PARAMETER;
90126f3cdf0SGordon Ross goto UnlockAndExit;
90226f3cdf0SGordon Ross }
90326f3cdf0SGordon Ross
904*cb565728SJerry Jelinek /* Validate the parent device */
905*cb565728SJerry Jelinek
906*cb565728SJerry Jelinek if (Node->Type != ACPI_TYPE_DEVICE)
907*cb565728SJerry Jelinek {
908*cb565728SJerry Jelinek Status = AE_TYPE;
909*cb565728SJerry Jelinek goto UnlockAndExit;
910*cb565728SJerry Jelinek }
911*cb565728SJerry Jelinek
912*cb565728SJerry Jelinek if (Node->Object)
913*cb565728SJerry Jelinek {
914*cb565728SJerry Jelinek Status = AE_ALREADY_EXISTS;
915*cb565728SJerry Jelinek goto UnlockAndExit;
916*cb565728SJerry Jelinek }
917*cb565728SJerry Jelinek
91826f3cdf0SGordon Ross /*
91926f3cdf0SGordon Ross * For user-installed GPE Block Devices, the GpeBlockBaseNumber
92026f3cdf0SGordon Ross * is always zero
92126f3cdf0SGordon Ross */
922*cb565728SJerry Jelinek Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
923*cb565728SJerry Jelinek GpeBlockAddress->SpaceId, RegisterCount,
92426f3cdf0SGordon Ross 0, InterruptNumber, &GpeBlock);
92526f3cdf0SGordon Ross if (ACPI_FAILURE (Status))
92626f3cdf0SGordon Ross {
92726f3cdf0SGordon Ross goto UnlockAndExit;
92826f3cdf0SGordon Ross }
92926f3cdf0SGordon Ross
93026f3cdf0SGordon Ross /* Install block in the DeviceObject attached to the node */
93126f3cdf0SGordon Ross
93226f3cdf0SGordon Ross ObjDesc = AcpiNsGetAttachedObject (Node);
93326f3cdf0SGordon Ross if (!ObjDesc)
93426f3cdf0SGordon Ross {
93526f3cdf0SGordon Ross /*
93626f3cdf0SGordon Ross * No object, create a new one (Device nodes do not always have
93726f3cdf0SGordon Ross * an attached object)
93826f3cdf0SGordon Ross */
93926f3cdf0SGordon Ross ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
94026f3cdf0SGordon Ross if (!ObjDesc)
94126f3cdf0SGordon Ross {
94226f3cdf0SGordon Ross Status = AE_NO_MEMORY;
94326f3cdf0SGordon Ross goto UnlockAndExit;
94426f3cdf0SGordon Ross }
94526f3cdf0SGordon Ross
94626f3cdf0SGordon Ross Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);
94726f3cdf0SGordon Ross
94826f3cdf0SGordon Ross /* Remove local reference to the object */
94926f3cdf0SGordon Ross
95026f3cdf0SGordon Ross AcpiUtRemoveReference (ObjDesc);
95126f3cdf0SGordon Ross if (ACPI_FAILURE (Status))
95226f3cdf0SGordon Ross {
95326f3cdf0SGordon Ross goto UnlockAndExit;
95426f3cdf0SGordon Ross }
95526f3cdf0SGordon Ross }
95626f3cdf0SGordon Ross
95726f3cdf0SGordon Ross /* Now install the GPE block in the DeviceObject */
95826f3cdf0SGordon Ross
95926f3cdf0SGordon Ross ObjDesc->Device.GpeBlock = GpeBlock;
96026f3cdf0SGordon Ross
96126f3cdf0SGordon Ross
96226f3cdf0SGordon Ross UnlockAndExit:
96326f3cdf0SGordon Ross (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
96426f3cdf0SGordon Ross return_ACPI_STATUS (Status);
96526f3cdf0SGordon Ross }
96626f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiInstallGpeBlock)96726f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)
96826f3cdf0SGordon Ross
96926f3cdf0SGordon Ross
97026f3cdf0SGordon Ross /*******************************************************************************
97126f3cdf0SGordon Ross *
97226f3cdf0SGordon Ross * FUNCTION: AcpiRemoveGpeBlock
97326f3cdf0SGordon Ross *
97426f3cdf0SGordon Ross * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device
97526f3cdf0SGordon Ross *
97626f3cdf0SGordon Ross * RETURN: Status
97726f3cdf0SGordon Ross *
97826f3cdf0SGordon Ross * DESCRIPTION: Remove a previously installed block of GPE registers
97926f3cdf0SGordon Ross *
98026f3cdf0SGordon Ross ******************************************************************************/
98126f3cdf0SGordon Ross
98226f3cdf0SGordon Ross ACPI_STATUS
98326f3cdf0SGordon Ross AcpiRemoveGpeBlock (
98426f3cdf0SGordon Ross ACPI_HANDLE GpeDevice)
98526f3cdf0SGordon Ross {
98626f3cdf0SGordon Ross ACPI_OPERAND_OBJECT *ObjDesc;
98726f3cdf0SGordon Ross ACPI_STATUS Status;
98826f3cdf0SGordon Ross ACPI_NAMESPACE_NODE *Node;
98926f3cdf0SGordon Ross
99026f3cdf0SGordon Ross
99126f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);
99226f3cdf0SGordon Ross
99326f3cdf0SGordon Ross
99426f3cdf0SGordon Ross if (!GpeDevice)
99526f3cdf0SGordon Ross {
99626f3cdf0SGordon Ross return_ACPI_STATUS (AE_BAD_PARAMETER);
99726f3cdf0SGordon Ross }
99826f3cdf0SGordon Ross
99926f3cdf0SGordon Ross Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
100026f3cdf0SGordon Ross if (ACPI_FAILURE (Status))
100126f3cdf0SGordon Ross {
1002*cb565728SJerry Jelinek return_ACPI_STATUS (Status);
100326f3cdf0SGordon Ross }
100426f3cdf0SGordon Ross
100526f3cdf0SGordon Ross Node = AcpiNsValidateHandle (GpeDevice);
100626f3cdf0SGordon Ross if (!Node)
100726f3cdf0SGordon Ross {
100826f3cdf0SGordon Ross Status = AE_BAD_PARAMETER;
100926f3cdf0SGordon Ross goto UnlockAndExit;
101026f3cdf0SGordon Ross }
101126f3cdf0SGordon Ross
1012*cb565728SJerry Jelinek /* Validate the parent device */
1013*cb565728SJerry Jelinek
1014*cb565728SJerry Jelinek if (Node->Type != ACPI_TYPE_DEVICE)
1015*cb565728SJerry Jelinek {
1016*cb565728SJerry Jelinek Status = AE_TYPE;
1017*cb565728SJerry Jelinek goto UnlockAndExit;
1018*cb565728SJerry Jelinek }
1019*cb565728SJerry Jelinek
102026f3cdf0SGordon Ross /* Get the DeviceObject attached to the node */
102126f3cdf0SGordon Ross
102226f3cdf0SGordon Ross ObjDesc = AcpiNsGetAttachedObject (Node);
102326f3cdf0SGordon Ross if (!ObjDesc ||
102426f3cdf0SGordon Ross !ObjDesc->Device.GpeBlock)
102526f3cdf0SGordon Ross {
102626f3cdf0SGordon Ross return_ACPI_STATUS (AE_NULL_OBJECT);
102726f3cdf0SGordon Ross }
102826f3cdf0SGordon Ross
102926f3cdf0SGordon Ross /* Delete the GPE block (but not the DeviceObject) */
103026f3cdf0SGordon Ross
103126f3cdf0SGordon Ross Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);
103226f3cdf0SGordon Ross if (ACPI_SUCCESS (Status))
103326f3cdf0SGordon Ross {
103426f3cdf0SGordon Ross ObjDesc->Device.GpeBlock = NULL;
103526f3cdf0SGordon Ross }
103626f3cdf0SGordon Ross
103726f3cdf0SGordon Ross UnlockAndExit:
103826f3cdf0SGordon Ross (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
103926f3cdf0SGordon Ross return_ACPI_STATUS (Status);
104026f3cdf0SGordon Ross }
104126f3cdf0SGordon Ross
ACPI_EXPORT_SYMBOL(AcpiRemoveGpeBlock)104226f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)
104326f3cdf0SGordon Ross
104426f3cdf0SGordon Ross
104526f3cdf0SGordon Ross /*******************************************************************************
104626f3cdf0SGordon Ross *
104726f3cdf0SGordon Ross * FUNCTION: AcpiGetGpeDevice
104826f3cdf0SGordon Ross *
104926f3cdf0SGordon Ross * PARAMETERS: Index - System GPE index (0-CurrentGpeCount)
105026f3cdf0SGordon Ross * GpeDevice - Where the parent GPE Device is returned
105126f3cdf0SGordon Ross *
105226f3cdf0SGordon Ross * RETURN: Status
105326f3cdf0SGordon Ross *
105426f3cdf0SGordon Ross * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
105526f3cdf0SGordon Ross * gpe device indicates that the gpe number is contained in one of
105626f3cdf0SGordon Ross * the FADT-defined gpe blocks. Otherwise, the GPE block device.
105726f3cdf0SGordon Ross *
105826f3cdf0SGordon Ross ******************************************************************************/
105926f3cdf0SGordon Ross
106026f3cdf0SGordon Ross ACPI_STATUS
106126f3cdf0SGordon Ross AcpiGetGpeDevice (
106226f3cdf0SGordon Ross UINT32 Index,
106326f3cdf0SGordon Ross ACPI_HANDLE *GpeDevice)
106426f3cdf0SGordon Ross {
106526f3cdf0SGordon Ross ACPI_GPE_DEVICE_INFO Info;
106626f3cdf0SGordon Ross ACPI_STATUS Status;
106726f3cdf0SGordon Ross
106826f3cdf0SGordon Ross
106926f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);
107026f3cdf0SGordon Ross
107126f3cdf0SGordon Ross
107226f3cdf0SGordon Ross if (!GpeDevice)
107326f3cdf0SGordon Ross {
107426f3cdf0SGordon Ross return_ACPI_STATUS (AE_BAD_PARAMETER);
107526f3cdf0SGordon Ross }
107626f3cdf0SGordon Ross
107726f3cdf0SGordon Ross if (Index >= AcpiCurrentGpeCount)
107826f3cdf0SGordon Ross {
107926f3cdf0SGordon Ross return_ACPI_STATUS (AE_NOT_EXIST);
108026f3cdf0SGordon Ross }
108126f3cdf0SGordon Ross
108226f3cdf0SGordon Ross /* Setup and walk the GPE list */
108326f3cdf0SGordon Ross
108426f3cdf0SGordon Ross Info.Index = Index;
108526f3cdf0SGordon Ross Info.Status = AE_NOT_EXIST;
108626f3cdf0SGordon Ross Info.GpeDevice = NULL;
108726f3cdf0SGordon Ross Info.NextBlockBaseIndex = 0;
108826f3cdf0SGordon Ross
108926f3cdf0SGordon Ross Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);
109026f3cdf0SGordon Ross if (ACPI_FAILURE (Status))
109126f3cdf0SGordon Ross {
109226f3cdf0SGordon Ross return_ACPI_STATUS (Status);
109326f3cdf0SGordon Ross }
109426f3cdf0SGordon Ross
109526f3cdf0SGordon Ross *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
109626f3cdf0SGordon Ross return_ACPI_STATUS (Info.Status);
109726f3cdf0SGordon Ross }
109826f3cdf0SGordon Ross
109926f3cdf0SGordon Ross ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
1100*cb565728SJerry Jelinek
1101*cb565728SJerry Jelinek #endif /* !ACPI_REDUCED_HARDWARE */
1102