1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2000 - 2020, Intel Corp.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun *****************************************************************************/
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #define EXPORT_ACPI_INTERFACES
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <acpi/acpi.h>
13*4882a593Smuzhiyun #include "accommon.h"
14*4882a593Smuzhiyun #include "acevents.h"
15*4882a593Smuzhiyun #include "acnamesp.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define _COMPONENT ACPI_EVENTS
18*4882a593Smuzhiyun ACPI_MODULE_NAME("evxfgpe")
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
21*4882a593Smuzhiyun /*******************************************************************************
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * FUNCTION: acpi_update_all_gpes
24*4882a593Smuzhiyun *
25*4882a593Smuzhiyun * PARAMETERS: None
26*4882a593Smuzhiyun *
27*4882a593Smuzhiyun * RETURN: Status
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
30*4882a593Smuzhiyun * associated _Lxx or _Exx methods and are not pointed to by any
31*4882a593Smuzhiyun * device _PRW methods (this indicates that these GPEs are
32*4882a593Smuzhiyun * generally intended for system or device wakeup. Such GPEs
33*4882a593Smuzhiyun * have to be enabled directly when the devices whose _PRW
34*4882a593Smuzhiyun * methods point to them are set up for wakeup signaling.)
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * NOTE: Should be called after any GPEs are added to the system. Primarily,
37*4882a593Smuzhiyun * after the system _PRW methods have been run, but also after a GPE Block
38*4882a593Smuzhiyun * Device has been added or if any new GPE methods have been added via a
39*4882a593Smuzhiyun * dynamic table load.
40*4882a593Smuzhiyun *
41*4882a593Smuzhiyun ******************************************************************************/
42*4882a593Smuzhiyun
acpi_update_all_gpes(void)43*4882a593Smuzhiyun acpi_status acpi_update_all_gpes(void)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun acpi_status status;
46*4882a593Smuzhiyun u8 is_polling_needed = FALSE;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
51*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
52*4882a593Smuzhiyun return_ACPI_STATUS(status);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun if (acpi_gbl_all_gpes_initialized) {
56*4882a593Smuzhiyun goto unlock_and_exit;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block,
60*4882a593Smuzhiyun &is_polling_needed);
61*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
62*4882a593Smuzhiyun acpi_gbl_all_gpes_initialized = TRUE;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun unlock_and_exit:
66*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun if (is_polling_needed && acpi_gbl_all_gpes_initialized) {
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* Poll GPEs to handle already triggered events */
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun acpi_ev_gpe_detect(acpi_gbl_gpe_xrupt_list_head);
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun return_ACPI_STATUS(status);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)77*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /*******************************************************************************
80*4882a593Smuzhiyun *
81*4882a593Smuzhiyun * FUNCTION: acpi_enable_gpe
82*4882a593Smuzhiyun *
83*4882a593Smuzhiyun * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
84*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
85*4882a593Smuzhiyun *
86*4882a593Smuzhiyun * RETURN: Status
87*4882a593Smuzhiyun *
88*4882a593Smuzhiyun * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
89*4882a593Smuzhiyun * hardware-enabled.
90*4882a593Smuzhiyun *
91*4882a593Smuzhiyun ******************************************************************************/
92*4882a593Smuzhiyun acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun acpi_status status = AE_BAD_PARAMETER;
95*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
96*4882a593Smuzhiyun acpi_cpu_flags flags;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_enable_gpe);
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun * Ensure that we have a valid GPE number and that there is some way
104*4882a593Smuzhiyun * of handling the GPE (handler or a GPE method). In other words, we
105*4882a593Smuzhiyun * won't allow a valid GPE to be enabled if there is no way to handle it.
106*4882a593Smuzhiyun */
107*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
108*4882a593Smuzhiyun if (gpe_event_info) {
109*4882a593Smuzhiyun if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
110*4882a593Smuzhiyun ACPI_GPE_DISPATCH_NONE) {
111*4882a593Smuzhiyun status = acpi_ev_add_gpe_reference(gpe_event_info, TRUE);
112*4882a593Smuzhiyun if (ACPI_SUCCESS(status) &&
113*4882a593Smuzhiyun ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* Poll edge-triggered GPEs to handle existing events */
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
118*4882a593Smuzhiyun (void)acpi_ev_detect_gpe(gpe_device,
119*4882a593Smuzhiyun gpe_event_info,
120*4882a593Smuzhiyun gpe_number);
121*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun } else {
124*4882a593Smuzhiyun status = AE_NO_HANDLER;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
129*4882a593Smuzhiyun return_ACPI_STATUS(status);
130*4882a593Smuzhiyun }
ACPI_EXPORT_SYMBOL(acpi_enable_gpe)131*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /*******************************************************************************
134*4882a593Smuzhiyun *
135*4882a593Smuzhiyun * FUNCTION: acpi_disable_gpe
136*4882a593Smuzhiyun *
137*4882a593Smuzhiyun * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
138*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
139*4882a593Smuzhiyun *
140*4882a593Smuzhiyun * RETURN: Status
141*4882a593Smuzhiyun *
142*4882a593Smuzhiyun * DESCRIPTION: Remove a reference to a GPE. When the last reference is
143*4882a593Smuzhiyun * removed, only then is the GPE disabled (for runtime GPEs), or
144*4882a593Smuzhiyun * the GPE mask bit disabled (for wake GPEs)
145*4882a593Smuzhiyun *
146*4882a593Smuzhiyun ******************************************************************************/
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun acpi_status status = AE_BAD_PARAMETER;
151*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
152*4882a593Smuzhiyun acpi_cpu_flags flags;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_disable_gpe);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /* Ensure that we have a valid GPE number */
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
161*4882a593Smuzhiyun if (gpe_event_info) {
162*4882a593Smuzhiyun status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
166*4882a593Smuzhiyun return_ACPI_STATUS(status);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_disable_gpe)169*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun /*******************************************************************************
172*4882a593Smuzhiyun *
173*4882a593Smuzhiyun * FUNCTION: acpi_set_gpe
174*4882a593Smuzhiyun *
175*4882a593Smuzhiyun * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
176*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
177*4882a593Smuzhiyun * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
178*4882a593Smuzhiyun *
179*4882a593Smuzhiyun * RETURN: Status
180*4882a593Smuzhiyun *
181*4882a593Smuzhiyun * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
182*4882a593Smuzhiyun * the reference count mechanism used in the acpi_enable_gpe(),
183*4882a593Smuzhiyun * acpi_disable_gpe() interfaces.
184*4882a593Smuzhiyun * This API is typically used by the GPE raw handler mode driver
185*4882a593Smuzhiyun * to switch between the polling mode and the interrupt mode after
186*4882a593Smuzhiyun * the driver has enabled the GPE.
187*4882a593Smuzhiyun * The APIs should be invoked in this order:
188*4882a593Smuzhiyun * acpi_enable_gpe() <- Ensure the reference count > 0
189*4882a593Smuzhiyun * acpi_set_gpe(ACPI_GPE_DISABLE) <- Enter polling mode
190*4882a593Smuzhiyun * acpi_set_gpe(ACPI_GPE_ENABLE) <- Leave polling mode
191*4882a593Smuzhiyun * acpi_disable_gpe() <- Decrease the reference count
192*4882a593Smuzhiyun *
193*4882a593Smuzhiyun * Note: If a GPE is shared by 2 silicon components, then both the drivers
194*4882a593Smuzhiyun * should support GPE polling mode or disabling the GPE for long period
195*4882a593Smuzhiyun * for one driver may break the other. So use it with care since all
196*4882a593Smuzhiyun * firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
197*4882a593Smuzhiyun *
198*4882a593Smuzhiyun ******************************************************************************/
199*4882a593Smuzhiyun acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
202*4882a593Smuzhiyun acpi_status status;
203*4882a593Smuzhiyun acpi_cpu_flags flags;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_set_gpe);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun /* Ensure that we have a valid GPE number */
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
212*4882a593Smuzhiyun if (!gpe_event_info) {
213*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
214*4882a593Smuzhiyun goto unlock_and_exit;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* Perform the action */
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun switch (action) {
220*4882a593Smuzhiyun case ACPI_GPE_ENABLE:
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
223*4882a593Smuzhiyun gpe_event_info->disable_for_dispatch = FALSE;
224*4882a593Smuzhiyun break;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun case ACPI_GPE_DISABLE:
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
229*4882a593Smuzhiyun gpe_event_info->disable_for_dispatch = TRUE;
230*4882a593Smuzhiyun break;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun default:
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
235*4882a593Smuzhiyun break;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun unlock_and_exit:
239*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
240*4882a593Smuzhiyun return_ACPI_STATUS(status);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_set_gpe)243*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_set_gpe)
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun /*******************************************************************************
246*4882a593Smuzhiyun *
247*4882a593Smuzhiyun * FUNCTION: acpi_mask_gpe
248*4882a593Smuzhiyun *
249*4882a593Smuzhiyun * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
250*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
251*4882a593Smuzhiyun * is_masked - Whether the GPE is masked or not
252*4882a593Smuzhiyun *
253*4882a593Smuzhiyun * RETURN: Status
254*4882a593Smuzhiyun *
255*4882a593Smuzhiyun * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to
256*4882a593Smuzhiyun * prevent a GPE flooding.
257*4882a593Smuzhiyun *
258*4882a593Smuzhiyun ******************************************************************************/
259*4882a593Smuzhiyun acpi_status acpi_mask_gpe(acpi_handle gpe_device, u32 gpe_number, u8 is_masked)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
262*4882a593Smuzhiyun acpi_status status;
263*4882a593Smuzhiyun acpi_cpu_flags flags;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_mask_gpe);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun /* Ensure that we have a valid GPE number */
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
272*4882a593Smuzhiyun if (!gpe_event_info) {
273*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
274*4882a593Smuzhiyun goto unlock_and_exit;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun status = acpi_ev_mask_gpe(gpe_event_info, is_masked);
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun unlock_and_exit:
280*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
281*4882a593Smuzhiyun return_ACPI_STATUS(status);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_mask_gpe)284*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_mask_gpe)
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun /*******************************************************************************
287*4882a593Smuzhiyun *
288*4882a593Smuzhiyun * FUNCTION: acpi_mark_gpe_for_wake
289*4882a593Smuzhiyun *
290*4882a593Smuzhiyun * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
291*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
292*4882a593Smuzhiyun *
293*4882a593Smuzhiyun * RETURN: Status
294*4882a593Smuzhiyun *
295*4882a593Smuzhiyun * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
296*4882a593Smuzhiyun * sets the ACPI_GPE_CAN_WAKE flag.
297*4882a593Smuzhiyun *
298*4882a593Smuzhiyun * Some potential callers of acpi_setup_gpe_for_wake may know in advance that
299*4882a593Smuzhiyun * there won't be any notify handlers installed for device wake notifications
300*4882a593Smuzhiyun * from the given GPE (one example is a button GPE in Linux). For these cases,
301*4882a593Smuzhiyun * acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake.
302*4882a593Smuzhiyun * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
303*4882a593Smuzhiyun * setup implicit wake notification for it (since there's no handler method).
304*4882a593Smuzhiyun *
305*4882a593Smuzhiyun ******************************************************************************/
306*4882a593Smuzhiyun acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
309*4882a593Smuzhiyun acpi_status status = AE_BAD_PARAMETER;
310*4882a593Smuzhiyun acpi_cpu_flags flags;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake);
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun /* Ensure that we have a valid GPE number */
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
319*4882a593Smuzhiyun if (gpe_event_info) {
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* Mark the GPE as a possible wake event */
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
324*4882a593Smuzhiyun status = AE_OK;
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
328*4882a593Smuzhiyun return_ACPI_STATUS(status);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake)331*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake)
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /*******************************************************************************
334*4882a593Smuzhiyun *
335*4882a593Smuzhiyun * FUNCTION: acpi_setup_gpe_for_wake
336*4882a593Smuzhiyun *
337*4882a593Smuzhiyun * PARAMETERS: wake_device - Device associated with the GPE (via _PRW)
338*4882a593Smuzhiyun * gpe_device - Parent GPE Device. NULL for GPE0/GPE1
339*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
340*4882a593Smuzhiyun *
341*4882a593Smuzhiyun * RETURN: Status
342*4882a593Smuzhiyun *
343*4882a593Smuzhiyun * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
344*4882a593Smuzhiyun * interface is intended to be used as the host executes the
345*4882a593Smuzhiyun * _PRW methods (Power Resources for Wake) in the system tables.
346*4882a593Smuzhiyun * Each _PRW appears under a Device Object (The wake_device), and
347*4882a593Smuzhiyun * contains the info for the wake GPE associated with the
348*4882a593Smuzhiyun * wake_device.
349*4882a593Smuzhiyun *
350*4882a593Smuzhiyun ******************************************************************************/
351*4882a593Smuzhiyun acpi_status
352*4882a593Smuzhiyun acpi_setup_gpe_for_wake(acpi_handle wake_device,
353*4882a593Smuzhiyun acpi_handle gpe_device, u32 gpe_number)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun acpi_status status;
356*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
357*4882a593Smuzhiyun struct acpi_namespace_node *device_node;
358*4882a593Smuzhiyun struct acpi_gpe_notify_info *notify;
359*4882a593Smuzhiyun struct acpi_gpe_notify_info *new_notify;
360*4882a593Smuzhiyun acpi_cpu_flags flags;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* Parameter Validation */
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun if (!wake_device) {
367*4882a593Smuzhiyun /*
368*4882a593Smuzhiyun * By forcing wake_device to be valid, we automatically enable the
369*4882a593Smuzhiyun * implicit notify feature on all hosts.
370*4882a593Smuzhiyun */
371*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun /* Handle root object case */
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun if (wake_device == ACPI_ROOT_OBJECT) {
377*4882a593Smuzhiyun device_node = acpi_gbl_root_node;
378*4882a593Smuzhiyun } else {
379*4882a593Smuzhiyun device_node =
380*4882a593Smuzhiyun ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun /* Validate wake_device is of type Device */
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun if (device_node->type != ACPI_TYPE_DEVICE) {
386*4882a593Smuzhiyun return_ACPI_STATUS (AE_BAD_PARAMETER);
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun /*
390*4882a593Smuzhiyun * Allocate a new notify object up front, in case it is needed.
391*4882a593Smuzhiyun * Memory allocation while holding a spinlock is a big no-no
392*4882a593Smuzhiyun * on some hosts.
393*4882a593Smuzhiyun */
394*4882a593Smuzhiyun new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info));
395*4882a593Smuzhiyun if (!new_notify) {
396*4882a593Smuzhiyun return_ACPI_STATUS(AE_NO_MEMORY);
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun /* Ensure that we have a valid GPE number */
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
404*4882a593Smuzhiyun if (!gpe_event_info) {
405*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
406*4882a593Smuzhiyun goto unlock_and_exit;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun /*
410*4882a593Smuzhiyun * If there is no method or handler for this GPE, then the
411*4882a593Smuzhiyun * wake_device will be notified whenever this GPE fires. This is
412*4882a593Smuzhiyun * known as an "implicit notify". Note: The GPE is assumed to be
413*4882a593Smuzhiyun * level-triggered (for windows compatibility).
414*4882a593Smuzhiyun */
415*4882a593Smuzhiyun if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
416*4882a593Smuzhiyun ACPI_GPE_DISPATCH_NONE) {
417*4882a593Smuzhiyun /*
418*4882a593Smuzhiyun * This is the first device for implicit notify on this GPE.
419*4882a593Smuzhiyun * Just set the flags here, and enter the NOTIFY block below.
420*4882a593Smuzhiyun */
421*4882a593Smuzhiyun gpe_event_info->flags =
422*4882a593Smuzhiyun (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
423*4882a593Smuzhiyun } else if (gpe_event_info->flags & ACPI_GPE_AUTO_ENABLED) {
424*4882a593Smuzhiyun /*
425*4882a593Smuzhiyun * A reference to this GPE has been added during the GPE block
426*4882a593Smuzhiyun * initialization, so drop it now to prevent the GPE from being
427*4882a593Smuzhiyun * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.
428*4882a593Smuzhiyun */
429*4882a593Smuzhiyun (void)acpi_ev_remove_gpe_reference(gpe_event_info);
430*4882a593Smuzhiyun gpe_event_info->flags &= ~ACPI_GPE_AUTO_ENABLED;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun /*
434*4882a593Smuzhiyun * If we already have an implicit notify on this GPE, add
435*4882a593Smuzhiyun * this device to the notify list.
436*4882a593Smuzhiyun */
437*4882a593Smuzhiyun if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
438*4882a593Smuzhiyun ACPI_GPE_DISPATCH_NOTIFY) {
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun /* Ensure that the device is not already in the list */
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun notify = gpe_event_info->dispatch.notify_list;
443*4882a593Smuzhiyun while (notify) {
444*4882a593Smuzhiyun if (notify->device_node == device_node) {
445*4882a593Smuzhiyun status = AE_ALREADY_EXISTS;
446*4882a593Smuzhiyun goto unlock_and_exit;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun notify = notify->next;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun /* Add this device to the notify list for this GPE */
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun new_notify->device_node = device_node;
454*4882a593Smuzhiyun new_notify->next = gpe_event_info->dispatch.notify_list;
455*4882a593Smuzhiyun gpe_event_info->dispatch.notify_list = new_notify;
456*4882a593Smuzhiyun new_notify = NULL;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun /* Mark the GPE as a possible wake event */
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
462*4882a593Smuzhiyun status = AE_OK;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun unlock_and_exit:
465*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun /* Delete the notify object if it was not used above */
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun if (new_notify) {
470*4882a593Smuzhiyun ACPI_FREE(new_notify);
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun return_ACPI_STATUS(status);
473*4882a593Smuzhiyun }
ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)474*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun /*******************************************************************************
477*4882a593Smuzhiyun *
478*4882a593Smuzhiyun * FUNCTION: acpi_set_gpe_wake_mask
479*4882a593Smuzhiyun *
480*4882a593Smuzhiyun * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
481*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
482*4882a593Smuzhiyun * action - Enable or Disable
483*4882a593Smuzhiyun *
484*4882a593Smuzhiyun * RETURN: Status
485*4882a593Smuzhiyun *
486*4882a593Smuzhiyun * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
487*4882a593Smuzhiyun * already be marked as a WAKE GPE.
488*4882a593Smuzhiyun *
489*4882a593Smuzhiyun ******************************************************************************/
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun acpi_status
492*4882a593Smuzhiyun acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun acpi_status status = AE_OK;
495*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
496*4882a593Smuzhiyun struct acpi_gpe_register_info *gpe_register_info;
497*4882a593Smuzhiyun acpi_cpu_flags flags;
498*4882a593Smuzhiyun u32 register_bit;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun /*
505*4882a593Smuzhiyun * Ensure that we have a valid GPE number and that this GPE is in
506*4882a593Smuzhiyun * fact a wake GPE
507*4882a593Smuzhiyun */
508*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
509*4882a593Smuzhiyun if (!gpe_event_info) {
510*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
511*4882a593Smuzhiyun goto unlock_and_exit;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
515*4882a593Smuzhiyun status = AE_TYPE;
516*4882a593Smuzhiyun goto unlock_and_exit;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun gpe_register_info = gpe_event_info->register_info;
520*4882a593Smuzhiyun if (!gpe_register_info) {
521*4882a593Smuzhiyun status = AE_NOT_EXIST;
522*4882a593Smuzhiyun goto unlock_and_exit;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun /* Perform the action */
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun switch (action) {
530*4882a593Smuzhiyun case ACPI_GPE_ENABLE:
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun ACPI_SET_BIT(gpe_register_info->enable_for_wake,
533*4882a593Smuzhiyun (u8)register_bit);
534*4882a593Smuzhiyun break;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun case ACPI_GPE_DISABLE:
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
539*4882a593Smuzhiyun (u8)register_bit);
540*4882a593Smuzhiyun break;
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun default:
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
545*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
546*4882a593Smuzhiyun break;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun unlock_and_exit:
550*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
551*4882a593Smuzhiyun return_ACPI_STATUS(status);
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)554*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun /*******************************************************************************
557*4882a593Smuzhiyun *
558*4882a593Smuzhiyun * FUNCTION: acpi_clear_gpe
559*4882a593Smuzhiyun *
560*4882a593Smuzhiyun * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
561*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
562*4882a593Smuzhiyun *
563*4882a593Smuzhiyun * RETURN: Status
564*4882a593Smuzhiyun *
565*4882a593Smuzhiyun * DESCRIPTION: Clear an ACPI event (general purpose)
566*4882a593Smuzhiyun *
567*4882a593Smuzhiyun ******************************************************************************/
568*4882a593Smuzhiyun acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun acpi_status status = AE_OK;
571*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
572*4882a593Smuzhiyun acpi_cpu_flags flags;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_clear_gpe);
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun /* Ensure that we have a valid GPE number */
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
581*4882a593Smuzhiyun if (!gpe_event_info) {
582*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
583*4882a593Smuzhiyun goto unlock_and_exit;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun status = acpi_hw_clear_gpe(gpe_event_info);
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun unlock_and_exit:
589*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
590*4882a593Smuzhiyun return_ACPI_STATUS(status);
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_clear_gpe)593*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun /*******************************************************************************
596*4882a593Smuzhiyun *
597*4882a593Smuzhiyun * FUNCTION: acpi_get_gpe_status
598*4882a593Smuzhiyun *
599*4882a593Smuzhiyun * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
600*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
601*4882a593Smuzhiyun * event_status - Where the current status of the event
602*4882a593Smuzhiyun * will be returned
603*4882a593Smuzhiyun *
604*4882a593Smuzhiyun * RETURN: Status
605*4882a593Smuzhiyun *
606*4882a593Smuzhiyun * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
607*4882a593Smuzhiyun *
608*4882a593Smuzhiyun ******************************************************************************/
609*4882a593Smuzhiyun acpi_status
610*4882a593Smuzhiyun acpi_get_gpe_status(acpi_handle gpe_device,
611*4882a593Smuzhiyun u32 gpe_number, acpi_event_status *event_status)
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun acpi_status status = AE_OK;
614*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
615*4882a593Smuzhiyun acpi_cpu_flags flags;
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun /* Ensure that we have a valid GPE number */
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
624*4882a593Smuzhiyun if (!gpe_event_info) {
625*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
626*4882a593Smuzhiyun goto unlock_and_exit;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun /* Obtain status on the requested GPE number */
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun unlock_and_exit:
634*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
635*4882a593Smuzhiyun return_ACPI_STATUS(status);
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)638*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun /*******************************************************************************
641*4882a593Smuzhiyun *
642*4882a593Smuzhiyun * FUNCTION: acpi_gispatch_gpe
643*4882a593Smuzhiyun *
644*4882a593Smuzhiyun * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
645*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
646*4882a593Smuzhiyun *
647*4882a593Smuzhiyun * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
648*4882a593Smuzhiyun *
649*4882a593Smuzhiyun * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
650*4882a593Smuzhiyun * (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
651*4882a593Smuzhiyun *
652*4882a593Smuzhiyun ******************************************************************************/
653*4882a593Smuzhiyun u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)
654*4882a593Smuzhiyun {
655*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_dispatch_gpe);
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun return acpi_ev_detect_gpe(gpe_device, NULL, gpe_number);
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe)660*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe)
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun /*******************************************************************************
663*4882a593Smuzhiyun *
664*4882a593Smuzhiyun * FUNCTION: acpi_finish_gpe
665*4882a593Smuzhiyun *
666*4882a593Smuzhiyun * PARAMETERS: gpe_device - Namespace node for the GPE Block
667*4882a593Smuzhiyun * (NULL for FADT defined GPEs)
668*4882a593Smuzhiyun * gpe_number - GPE level within the GPE block
669*4882a593Smuzhiyun *
670*4882a593Smuzhiyun * RETURN: Status
671*4882a593Smuzhiyun *
672*4882a593Smuzhiyun * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE
673*4882a593Smuzhiyun * processing. Intended for use by asynchronous host-installed
674*4882a593Smuzhiyun * GPE handlers. The GPE is only re-enabled if the enable_for_run bit
675*4882a593Smuzhiyun * is set in the GPE info.
676*4882a593Smuzhiyun *
677*4882a593Smuzhiyun ******************************************************************************/
678*4882a593Smuzhiyun acpi_status acpi_finish_gpe(acpi_handle gpe_device, u32 gpe_number)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun struct acpi_gpe_event_info *gpe_event_info;
681*4882a593Smuzhiyun acpi_status status;
682*4882a593Smuzhiyun acpi_cpu_flags flags;
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_finish_gpe);
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun /* Ensure that we have a valid GPE number */
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
691*4882a593Smuzhiyun if (!gpe_event_info) {
692*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
693*4882a593Smuzhiyun goto unlock_and_exit;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun status = acpi_ev_finish_gpe(gpe_event_info);
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun unlock_and_exit:
699*4882a593Smuzhiyun acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
700*4882a593Smuzhiyun return_ACPI_STATUS(status);
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_finish_gpe)703*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_finish_gpe)
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun /******************************************************************************
706*4882a593Smuzhiyun *
707*4882a593Smuzhiyun * FUNCTION: acpi_disable_all_gpes
708*4882a593Smuzhiyun *
709*4882a593Smuzhiyun * PARAMETERS: None
710*4882a593Smuzhiyun *
711*4882a593Smuzhiyun * RETURN: Status
712*4882a593Smuzhiyun *
713*4882a593Smuzhiyun * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
714*4882a593Smuzhiyun *
715*4882a593Smuzhiyun ******************************************************************************/
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun acpi_status acpi_disable_all_gpes(void)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun acpi_status status;
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
724*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
725*4882a593Smuzhiyun return_ACPI_STATUS(status);
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun status = acpi_hw_disable_all_gpes();
729*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun return_ACPI_STATUS(status);
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)734*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun /******************************************************************************
737*4882a593Smuzhiyun *
738*4882a593Smuzhiyun * FUNCTION: acpi_enable_all_runtime_gpes
739*4882a593Smuzhiyun *
740*4882a593Smuzhiyun * PARAMETERS: None
741*4882a593Smuzhiyun *
742*4882a593Smuzhiyun * RETURN: Status
743*4882a593Smuzhiyun *
744*4882a593Smuzhiyun * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
745*4882a593Smuzhiyun *
746*4882a593Smuzhiyun ******************************************************************************/
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun acpi_status acpi_enable_all_runtime_gpes(void)
749*4882a593Smuzhiyun {
750*4882a593Smuzhiyun acpi_status status;
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
755*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
756*4882a593Smuzhiyun return_ACPI_STATUS(status);
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun status = acpi_hw_enable_all_runtime_gpes();
760*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun return_ACPI_STATUS(status);
763*4882a593Smuzhiyun }
764*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)765*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun /******************************************************************************
768*4882a593Smuzhiyun *
769*4882a593Smuzhiyun * FUNCTION: acpi_enable_all_wakeup_gpes
770*4882a593Smuzhiyun *
771*4882a593Smuzhiyun * PARAMETERS: None
772*4882a593Smuzhiyun *
773*4882a593Smuzhiyun * RETURN: Status
774*4882a593Smuzhiyun *
775*4882a593Smuzhiyun * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
776*4882a593Smuzhiyun * all GPE blocks.
777*4882a593Smuzhiyun *
778*4882a593Smuzhiyun ******************************************************************************/
779*4882a593Smuzhiyun acpi_status acpi_enable_all_wakeup_gpes(void)
780*4882a593Smuzhiyun {
781*4882a593Smuzhiyun acpi_status status;
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_enable_all_wakeup_gpes);
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
786*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
787*4882a593Smuzhiyun return_ACPI_STATUS(status);
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun status = acpi_hw_enable_all_wakeup_gpes();
791*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun return_ACPI_STATUS(status);
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)796*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun /******************************************************************************
799*4882a593Smuzhiyun *
800*4882a593Smuzhiyun * FUNCTION: acpi_any_gpe_status_set
801*4882a593Smuzhiyun *
802*4882a593Smuzhiyun * PARAMETERS: gpe_skip_number - Number of the GPE to skip
803*4882a593Smuzhiyun *
804*4882a593Smuzhiyun * RETURN: Whether or not the status bit is set for any GPE
805*4882a593Smuzhiyun *
806*4882a593Smuzhiyun * DESCRIPTION: Check the status bits of all enabled GPEs, except for the one
807*4882a593Smuzhiyun * represented by the "skip" argument, and return TRUE if any of
808*4882a593Smuzhiyun * them is set or FALSE otherwise.
809*4882a593Smuzhiyun *
810*4882a593Smuzhiyun ******************************************************************************/
811*4882a593Smuzhiyun u32 acpi_any_gpe_status_set(u32 gpe_skip_number)
812*4882a593Smuzhiyun {
813*4882a593Smuzhiyun acpi_status status;
814*4882a593Smuzhiyun acpi_handle gpe_device;
815*4882a593Smuzhiyun u8 ret;
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_any_gpe_status_set);
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
820*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
821*4882a593Smuzhiyun return (FALSE);
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun status = acpi_get_gpe_device(gpe_skip_number, &gpe_device);
825*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
826*4882a593Smuzhiyun gpe_device = NULL;
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun ret = acpi_hw_check_all_gpes(gpe_device, gpe_skip_number);
830*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun return (ret);
833*4882a593Smuzhiyun }
834*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_any_gpe_status_set)835*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_any_gpe_status_set)
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun /*******************************************************************************
838*4882a593Smuzhiyun *
839*4882a593Smuzhiyun * FUNCTION: acpi_install_gpe_block
840*4882a593Smuzhiyun *
841*4882a593Smuzhiyun * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
842*4882a593Smuzhiyun * gpe_block_address - Address and space_ID
843*4882a593Smuzhiyun * register_count - Number of GPE register pairs in the block
844*4882a593Smuzhiyun * interrupt_number - H/W interrupt for the block
845*4882a593Smuzhiyun *
846*4882a593Smuzhiyun * RETURN: Status
847*4882a593Smuzhiyun *
848*4882a593Smuzhiyun * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
849*4882a593Smuzhiyun * enabled here.
850*4882a593Smuzhiyun *
851*4882a593Smuzhiyun ******************************************************************************/
852*4882a593Smuzhiyun acpi_status
853*4882a593Smuzhiyun acpi_install_gpe_block(acpi_handle gpe_device,
854*4882a593Smuzhiyun struct acpi_generic_address *gpe_block_address,
855*4882a593Smuzhiyun u32 register_count, u32 interrupt_number)
856*4882a593Smuzhiyun {
857*4882a593Smuzhiyun acpi_status status;
858*4882a593Smuzhiyun union acpi_operand_object *obj_desc;
859*4882a593Smuzhiyun struct acpi_namespace_node *node;
860*4882a593Smuzhiyun struct acpi_gpe_block_info *gpe_block;
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
865*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
869*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
870*4882a593Smuzhiyun return_ACPI_STATUS(status);
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun node = acpi_ns_validate_handle(gpe_device);
874*4882a593Smuzhiyun if (!node) {
875*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
876*4882a593Smuzhiyun goto unlock_and_exit;
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun /* Validate the parent device */
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun if (node->type != ACPI_TYPE_DEVICE) {
882*4882a593Smuzhiyun status = AE_TYPE;
883*4882a593Smuzhiyun goto unlock_and_exit;
884*4882a593Smuzhiyun }
885*4882a593Smuzhiyun
886*4882a593Smuzhiyun if (node->object) {
887*4882a593Smuzhiyun status = AE_ALREADY_EXISTS;
888*4882a593Smuzhiyun goto unlock_and_exit;
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun /*
892*4882a593Smuzhiyun * For user-installed GPE Block Devices, the gpe_block_base_number
893*4882a593Smuzhiyun * is always zero
894*4882a593Smuzhiyun */
895*4882a593Smuzhiyun status = acpi_ev_create_gpe_block(node, gpe_block_address->address,
896*4882a593Smuzhiyun gpe_block_address->space_id,
897*4882a593Smuzhiyun register_count, 0, interrupt_number,
898*4882a593Smuzhiyun &gpe_block);
899*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
900*4882a593Smuzhiyun goto unlock_and_exit;
901*4882a593Smuzhiyun }
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun /* Install block in the device_object attached to the node */
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun obj_desc = acpi_ns_get_attached_object(node);
906*4882a593Smuzhiyun if (!obj_desc) {
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun /*
909*4882a593Smuzhiyun * No object, create a new one (Device nodes do not always have
910*4882a593Smuzhiyun * an attached object)
911*4882a593Smuzhiyun */
912*4882a593Smuzhiyun obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
913*4882a593Smuzhiyun if (!obj_desc) {
914*4882a593Smuzhiyun status = AE_NO_MEMORY;
915*4882a593Smuzhiyun goto unlock_and_exit;
916*4882a593Smuzhiyun }
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun status =
919*4882a593Smuzhiyun acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun /* Remove local reference to the object */
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun acpi_ut_remove_reference(obj_desc);
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
926*4882a593Smuzhiyun goto unlock_and_exit;
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun }
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun /* Now install the GPE block in the device_object */
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun obj_desc->device.gpe_block = gpe_block;
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun unlock_and_exit:
935*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
936*4882a593Smuzhiyun return_ACPI_STATUS(status);
937*4882a593Smuzhiyun }
938*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)939*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun /*******************************************************************************
942*4882a593Smuzhiyun *
943*4882a593Smuzhiyun * FUNCTION: acpi_remove_gpe_block
944*4882a593Smuzhiyun *
945*4882a593Smuzhiyun * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
946*4882a593Smuzhiyun *
947*4882a593Smuzhiyun * RETURN: Status
948*4882a593Smuzhiyun *
949*4882a593Smuzhiyun * DESCRIPTION: Remove a previously installed block of GPE registers
950*4882a593Smuzhiyun *
951*4882a593Smuzhiyun ******************************************************************************/
952*4882a593Smuzhiyun acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
953*4882a593Smuzhiyun {
954*4882a593Smuzhiyun union acpi_operand_object *obj_desc;
955*4882a593Smuzhiyun acpi_status status;
956*4882a593Smuzhiyun struct acpi_namespace_node *node;
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
959*4882a593Smuzhiyun
960*4882a593Smuzhiyun if (!gpe_device) {
961*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
965*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
966*4882a593Smuzhiyun return_ACPI_STATUS(status);
967*4882a593Smuzhiyun }
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun node = acpi_ns_validate_handle(gpe_device);
970*4882a593Smuzhiyun if (!node) {
971*4882a593Smuzhiyun status = AE_BAD_PARAMETER;
972*4882a593Smuzhiyun goto unlock_and_exit;
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun /* Validate the parent device */
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun if (node->type != ACPI_TYPE_DEVICE) {
978*4882a593Smuzhiyun status = AE_TYPE;
979*4882a593Smuzhiyun goto unlock_and_exit;
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun /* Get the device_object attached to the node */
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun obj_desc = acpi_ns_get_attached_object(node);
985*4882a593Smuzhiyun if (!obj_desc || !obj_desc->device.gpe_block) {
986*4882a593Smuzhiyun return_ACPI_STATUS(AE_NULL_OBJECT);
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun /* Delete the GPE block (but not the device_object) */
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
992*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
993*4882a593Smuzhiyun obj_desc->device.gpe_block = NULL;
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun unlock_and_exit:
997*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
998*4882a593Smuzhiyun return_ACPI_STATUS(status);
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)1001*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun /*******************************************************************************
1004*4882a593Smuzhiyun *
1005*4882a593Smuzhiyun * FUNCTION: acpi_get_gpe_device
1006*4882a593Smuzhiyun *
1007*4882a593Smuzhiyun * PARAMETERS: index - System GPE index (0-current_gpe_count)
1008*4882a593Smuzhiyun * gpe_device - Where the parent GPE Device is returned
1009*4882a593Smuzhiyun *
1010*4882a593Smuzhiyun * RETURN: Status
1011*4882a593Smuzhiyun *
1012*4882a593Smuzhiyun * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1013*4882a593Smuzhiyun * gpe device indicates that the gpe number is contained in one of
1014*4882a593Smuzhiyun * the FADT-defined gpe blocks. Otherwise, the GPE block device.
1015*4882a593Smuzhiyun *
1016*4882a593Smuzhiyun ******************************************************************************/
1017*4882a593Smuzhiyun acpi_status acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
1018*4882a593Smuzhiyun {
1019*4882a593Smuzhiyun struct acpi_gpe_device_info info;
1020*4882a593Smuzhiyun acpi_status status;
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
1023*4882a593Smuzhiyun
1024*4882a593Smuzhiyun if (!gpe_device) {
1025*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
1026*4882a593Smuzhiyun }
1027*4882a593Smuzhiyun
1028*4882a593Smuzhiyun if (index >= acpi_current_gpe_count) {
1029*4882a593Smuzhiyun return_ACPI_STATUS(AE_NOT_EXIST);
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun /* Setup and walk the GPE list */
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun info.index = index;
1035*4882a593Smuzhiyun info.status = AE_NOT_EXIST;
1036*4882a593Smuzhiyun info.gpe_device = NULL;
1037*4882a593Smuzhiyun info.next_block_base_index = 0;
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
1040*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
1041*4882a593Smuzhiyun return_ACPI_STATUS(status);
1042*4882a593Smuzhiyun }
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
1045*4882a593Smuzhiyun return_ACPI_STATUS(info.status);
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
1049*4882a593Smuzhiyun #endif /* !ACPI_REDUCED_HARDWARE */
1050