1 /******************************************************************************
3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2010, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
44 #include <acpi/acpi.h>
49 #define _COMPONENT ACPI_EVENTS
50 ACPI_MODULE_NAME("evxfgpe")
52 /******************************************************************************
54 * FUNCTION: acpi_update_all_gpes
60 * DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and
61 * are not pointed to by any device _PRW methods indicating that
62 * these GPEs are generally intended for system or device wakeup
63 * (such GPEs have to be enabled directly when the devices whose
64 * _PRW methods point to them are set up for wakeup signaling).
66 ******************************************************************************/
68 acpi_status acpi_update_all_gpes(void)
72 ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
74 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
75 if (ACPI_FAILURE(status)) {
76 return_ACPI_STATUS(status);
79 if (acpi_gbl_all_gpes_initialized) {
83 status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
84 if (ACPI_SUCCESS(status)) {
85 acpi_gbl_all_gpes_initialized = TRUE;
89 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
91 return_ACPI_STATUS(status);
94 ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
96 /*******************************************************************************
98 * FUNCTION: acpi_enable_gpe
100 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
101 * gpe_number - GPE level within the GPE block
105 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
108 ******************************************************************************/
110 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
112 acpi_status status = AE_BAD_PARAMETER;
113 struct acpi_gpe_event_info *gpe_event_info;
114 acpi_cpu_flags flags;
116 ACPI_FUNCTION_TRACE(acpi_enable_gpe);
118 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
120 /* Ensure that we have a valid GPE number */
122 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
123 if (gpe_event_info) {
124 status = acpi_ev_add_gpe_reference(gpe_event_info);
127 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
128 return_ACPI_STATUS(status);
130 ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
132 /*******************************************************************************
134 * FUNCTION: acpi_disable_gpe
136 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
137 * gpe_number - GPE level within the GPE block
141 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
142 * removed, only then is the GPE disabled (for runtime GPEs), or
143 * the GPE mask bit disabled (for wake GPEs)
145 ******************************************************************************/
147 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
149 acpi_status status = AE_BAD_PARAMETER;
150 struct acpi_gpe_event_info *gpe_event_info;
151 acpi_cpu_flags flags;
153 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
155 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
157 /* Ensure that we have a valid GPE number */
159 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
160 if (gpe_event_info) {
161 status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
164 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
165 return_ACPI_STATUS(status);
167 ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
170 /*******************************************************************************
172 * FUNCTION: acpi_setup_gpe_for_wake
174 * PARAMETERS: wake_device - Device associated with the GPE (via _PRW)
175 * gpe_device - Parent GPE Device. NULL for GPE0/GPE1
176 * gpe_number - GPE level within the GPE block
180 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
181 * interface is intended to be used as the host executes the
182 * _PRW methods (Power Resources for Wake) in the system tables.
183 * Each _PRW appears under a Device Object (The wake_device), and
184 * contains the info for the wake GPE associated with the
187 ******************************************************************************/
189 acpi_setup_gpe_for_wake(acpi_handle wake_device,
190 acpi_handle gpe_device, u32 gpe_number)
192 acpi_status status = AE_BAD_PARAMETER;
193 struct acpi_gpe_event_info *gpe_event_info;
194 struct acpi_namespace_node *device_node;
195 acpi_cpu_flags flags;
197 ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
199 /* Parameter Validation */
203 * By forcing wake_device to be valid, we automatically enable the
204 * implicit notify feature on all hosts.
206 return_ACPI_STATUS(AE_BAD_PARAMETER);
209 /* Validate wake_device is of type Device */
211 device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
212 if (device_node->type != ACPI_TYPE_DEVICE) {
213 return_ACPI_STATUS(AE_BAD_PARAMETER);
216 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
218 /* Ensure that we have a valid GPE number */
220 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
221 if (gpe_event_info) {
223 * If there is no method or handler for this GPE, then the
224 * wake_device will be notified whenever this GPE fires (aka
225 * "implicit notify") Note: The GPE is assumed to be
226 * level-triggered (for windows compatibility).
228 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
229 ACPI_GPE_DISPATCH_NONE) {
230 gpe_event_info->flags =
231 (ACPI_GPE_DISPATCH_NOTIFY |
232 ACPI_GPE_LEVEL_TRIGGERED);
233 gpe_event_info->dispatch.device_node = device_node;
236 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
240 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
241 return_ACPI_STATUS(status);
243 ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
245 /*******************************************************************************
247 * FUNCTION: acpi_set_gpe_wake_mask
249 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
250 * gpe_number - GPE level within the GPE block
251 * Action - Enable or Disable
255 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
257 ******************************************************************************/
259 acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
261 acpi_status status = AE_OK;
262 struct acpi_gpe_event_info *gpe_event_info;
263 struct acpi_gpe_register_info *gpe_register_info;
264 acpi_cpu_flags flags;
267 ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
269 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
271 /* Ensure that we have a valid GPE number */
273 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
274 if (!gpe_event_info) {
275 status = AE_BAD_PARAMETER;
276 goto unlock_and_exit;
279 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
281 goto unlock_and_exit;
284 gpe_register_info = gpe_event_info->register_info;
285 if (!gpe_register_info) {
286 status = AE_NOT_EXIST;
287 goto unlock_and_exit;
291 acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
293 /* Perform the action */
296 case ACPI_GPE_ENABLE:
297 ACPI_SET_BIT(gpe_register_info->enable_for_wake,
301 case ACPI_GPE_DISABLE:
302 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
307 ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
308 status = AE_BAD_PARAMETER;
313 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
314 return_ACPI_STATUS(status);
317 ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
319 /*******************************************************************************
321 * FUNCTION: acpi_clear_gpe
323 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
324 * gpe_number - GPE level within the GPE block
328 * DESCRIPTION: Clear an ACPI event (general purpose)
330 ******************************************************************************/
331 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
333 acpi_status status = AE_OK;
334 struct acpi_gpe_event_info *gpe_event_info;
335 acpi_cpu_flags flags;
337 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
339 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
341 /* Ensure that we have a valid GPE number */
343 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
344 if (!gpe_event_info) {
345 status = AE_BAD_PARAMETER;
346 goto unlock_and_exit;
349 status = acpi_hw_clear_gpe(gpe_event_info);
352 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
353 return_ACPI_STATUS(status);
356 ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
358 /*******************************************************************************
360 * FUNCTION: acpi_get_gpe_status
362 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
363 * gpe_number - GPE level within the GPE block
364 * event_status - Where the current status of the event will
369 * DESCRIPTION: Get status of an event (general purpose)
371 ******************************************************************************/
373 acpi_get_gpe_status(acpi_handle gpe_device,
374 u32 gpe_number, acpi_event_status *event_status)
376 acpi_status status = AE_OK;
377 struct acpi_gpe_event_info *gpe_event_info;
378 acpi_cpu_flags flags;
380 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
382 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
384 /* Ensure that we have a valid GPE number */
386 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
387 if (!gpe_event_info) {
388 status = AE_BAD_PARAMETER;
389 goto unlock_and_exit;
392 /* Obtain status on the requested GPE number */
394 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
396 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
397 *event_status |= ACPI_EVENT_FLAG_HANDLE;
400 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
401 return_ACPI_STATUS(status);
404 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
406 /******************************************************************************
408 * FUNCTION: acpi_disable_all_gpes
414 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
416 ******************************************************************************/
418 acpi_status acpi_disable_all_gpes(void)
422 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
424 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
425 if (ACPI_FAILURE(status)) {
426 return_ACPI_STATUS(status);
429 status = acpi_hw_disable_all_gpes();
430 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
432 return_ACPI_STATUS(status);
435 ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
437 /******************************************************************************
439 * FUNCTION: acpi_enable_all_runtime_gpes
445 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
447 ******************************************************************************/
449 acpi_status acpi_enable_all_runtime_gpes(void)
453 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
455 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
456 if (ACPI_FAILURE(status)) {
457 return_ACPI_STATUS(status);
460 status = acpi_hw_enable_all_runtime_gpes();
461 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
463 return_ACPI_STATUS(status);
466 ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
468 /*******************************************************************************
470 * FUNCTION: acpi_install_gpe_block
472 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
473 * gpe_block_address - Address and space_iD
474 * register_count - Number of GPE register pairs in the block
475 * interrupt_number - H/W interrupt for the block
479 * DESCRIPTION: Create and Install a block of GPE registers
481 ******************************************************************************/
483 acpi_install_gpe_block(acpi_handle gpe_device,
484 struct acpi_generic_address *gpe_block_address,
485 u32 register_count, u32 interrupt_number)
488 union acpi_operand_object *obj_desc;
489 struct acpi_namespace_node *node;
490 struct acpi_gpe_block_info *gpe_block;
492 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
494 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
495 return_ACPI_STATUS(AE_BAD_PARAMETER);
498 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
499 if (ACPI_FAILURE(status)) {
503 node = acpi_ns_validate_handle(gpe_device);
505 status = AE_BAD_PARAMETER;
506 goto unlock_and_exit;
510 * For user-installed GPE Block Devices, the gpe_block_base_number
514 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
515 interrupt_number, &gpe_block);
516 if (ACPI_FAILURE(status)) {
517 goto unlock_and_exit;
520 /* Install block in the device_object attached to the node */
522 obj_desc = acpi_ns_get_attached_object(node);
526 * No object, create a new one (Device nodes do not always have
527 * an attached object)
529 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
531 status = AE_NO_MEMORY;
532 goto unlock_and_exit;
536 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
538 /* Remove local reference to the object */
540 acpi_ut_remove_reference(obj_desc);
542 if (ACPI_FAILURE(status)) {
543 goto unlock_and_exit;
547 /* Now install the GPE block in the device_object */
549 obj_desc->device.gpe_block = gpe_block;
552 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
553 return_ACPI_STATUS(status);
556 ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
558 /*******************************************************************************
560 * FUNCTION: acpi_remove_gpe_block
562 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
566 * DESCRIPTION: Remove a previously installed block of GPE registers
568 ******************************************************************************/
569 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
571 union acpi_operand_object *obj_desc;
573 struct acpi_namespace_node *node;
575 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
578 return_ACPI_STATUS(AE_BAD_PARAMETER);
581 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
582 if (ACPI_FAILURE(status)) {
586 node = acpi_ns_validate_handle(gpe_device);
588 status = AE_BAD_PARAMETER;
589 goto unlock_and_exit;
592 /* Get the device_object attached to the node */
594 obj_desc = acpi_ns_get_attached_object(node);
595 if (!obj_desc || !obj_desc->device.gpe_block) {
596 return_ACPI_STATUS(AE_NULL_OBJECT);
599 /* Delete the GPE block (but not the device_object) */
601 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
602 if (ACPI_SUCCESS(status)) {
603 obj_desc->device.gpe_block = NULL;
607 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
608 return_ACPI_STATUS(status);
611 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
613 /*******************************************************************************
615 * FUNCTION: acpi_get_gpe_device
617 * PARAMETERS: Index - System GPE index (0-current_gpe_count)
618 * gpe_device - Where the parent GPE Device is returned
622 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
623 * gpe device indicates that the gpe number is contained in one of
624 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
626 ******************************************************************************/
628 acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
630 struct acpi_gpe_device_info info;
633 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
636 return_ACPI_STATUS(AE_BAD_PARAMETER);
639 if (index >= acpi_current_gpe_count) {
640 return_ACPI_STATUS(AE_NOT_EXIST);
643 /* Setup and walk the GPE list */
646 info.status = AE_NOT_EXIST;
647 info.gpe_device = NULL;
648 info.next_block_base_index = 0;
650 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
651 if (ACPI_FAILURE(status)) {
652 return_ACPI_STATUS(status);
655 *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
656 return_ACPI_STATUS(info.status);
659 ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)