blob: a1dabe3fd8ae771c7f8e676d907e4ad4cfba4ba3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/******************************************************************************
2 *
3 * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
4 *
5 *****************************************************************************/
6
7/*
Bob Moorea8357b02010-01-22 19:07:36 +08008 * Copyright (C) 2000 - 2010, Intel Corp.
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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.
25 *
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.
29 *
30 * NO WARRANTY
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.
42 */
43
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <acpi/acpi.h>
Len Browne2f7a772009-01-09 00:30:03 -050045#include "accommon.h"
46#include "acevents.h"
47#include "acnamesp.h"
48#include "actables.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50#define _COMPONENT ACPI_EVENTS
Len Brown4be44fc2005-08-05 00:44:28 -040051ACPI_MODULE_NAME("evxfevnt")
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Bob Mooree97d6bf2008-12-30 09:45:17 +080053/* Local prototypes */
Bob Mooree4c1ebf2009-04-22 13:02:06 +080054static acpi_status
Bob Mooree97d6bf2008-12-30 09:45:17 +080055acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
56 struct acpi_gpe_block_info *gpe_block, void *context);
57
Linus Torvalds1da177e2005-04-16 15:20:36 -070058/*******************************************************************************
59 *
60 * FUNCTION: acpi_enable
61 *
62 * PARAMETERS: None
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: Transfers the system into ACPI mode.
67 *
68 ******************************************************************************/
Bob Mooree97d6bf2008-12-30 09:45:17 +080069
Len Brown4be44fc2005-08-05 00:44:28 -040070acpi_status acpi_enable(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070071{
Len Brownb430acb2010-05-06 17:41:08 -040072 acpi_status status;
Len Brown3d695832010-06-28 20:55:01 -040073 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Bob Mooreb229cf92006-04-21 17:15:00 -040075 ACPI_FUNCTION_TRACE(acpi_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
Bob Moorec8573032007-02-02 19:48:23 +030077 /* ACPI tables must be present */
78
79 if (!acpi_tb_tables_loaded()) {
80 return_ACPI_STATUS(AE_NO_ACPI_TABLES);
81 }
82
83 /* Check current mode */
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
Len Brown4be44fc2005-08-05 00:44:28 -040086 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
87 "System is already in ACPI mode\n"));
Len Brownb430acb2010-05-06 17:41:08 -040088 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 }
90
Len Brownb430acb2010-05-06 17:41:08 -040091 /* Transition to ACPI mode */
92
93 status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
94 if (ACPI_FAILURE(status)) {
95 ACPI_ERROR((AE_INFO,
96 "Could not transition to ACPI mode"));
97 return_ACPI_STATUS(status);
98 }
99
100 /* Sanity check that transition succeeded */
101
Len Brown3d695832010-06-28 20:55:01 -0400102 for (retry = 0; retry < 30000; ++retry) {
103 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
104 if (retry != 0)
105 ACPI_WARNING((AE_INFO,
106 "Platform took > %d00 usec to enter ACPI mode", retry));
107 return_ACPI_STATUS(AE_OK);
108 }
109 acpi_os_stall(100); /* 100 usec */
Len Brownb430acb2010-05-06 17:41:08 -0400110 }
111
Len Brown3d695832010-06-28 20:55:01 -0400112 ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
113 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115
Bob Moore83135242006-10-03 00:00:00 -0400116ACPI_EXPORT_SYMBOL(acpi_enable)
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118/*******************************************************************************
119 *
120 * FUNCTION: acpi_disable
121 *
122 * PARAMETERS: None
123 *
124 * RETURN: Status
125 *
Robert Moore44f6c012005-04-18 22:49:35 -0400126 * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 *
128 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400129acpi_status acpi_disable(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130{
Len Brown4be44fc2005-08-05 00:44:28 -0400131 acpi_status status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Bob Mooreb229cf92006-04-21 17:15:00 -0400133 ACPI_FUNCTION_TRACE(acpi_disable);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
Len Brown4be44fc2005-08-05 00:44:28 -0400136 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
137 "System is already in legacy (non-ACPI) mode\n"));
138 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 /* Transition to LEGACY mode */
140
Len Brown4be44fc2005-08-05 00:44:28 -0400141 status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Len Brown4be44fc2005-08-05 00:44:28 -0400143 if (ACPI_FAILURE(status)) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500144 ACPI_ERROR((AE_INFO,
145 "Could not exit ACPI mode to legacy mode"));
Len Brown4be44fc2005-08-05 00:44:28 -0400146 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 }
148
Len Brown4be44fc2005-08-05 00:44:28 -0400149 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 }
151
Len Brown4be44fc2005-08-05 00:44:28 -0400152 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153}
154
Bob Moore83135242006-10-03 00:00:00 -0400155ACPI_EXPORT_SYMBOL(acpi_disable)
156
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157/*******************************************************************************
158 *
159 * FUNCTION: acpi_enable_event
160 *
161 * PARAMETERS: Event - The fixed eventto be enabled
162 * Flags - Reserved
163 *
164 * RETURN: Status
165 *
166 * DESCRIPTION: Enable an ACPI event (fixed)
167 *
168 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400169acpi_status acpi_enable_event(u32 event, u32 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170{
Len Brown4be44fc2005-08-05 00:44:28 -0400171 acpi_status status = AE_OK;
172 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
Bob Mooreb229cf92006-04-21 17:15:00 -0400174 ACPI_FUNCTION_TRACE(acpi_enable_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
176 /* Decode the Fixed Event */
177
178 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400179 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 }
181
182 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800183 * Enable the requested fixed event (by writing a one to the enable
184 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 */
Len Brown4be44fc2005-08-05 00:44:28 -0400186 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800187 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
Bob Moore768aaaf2009-03-06 09:49:25 +0800188 enable_register_id, ACPI_ENABLE_EVENT);
Len Brown4be44fc2005-08-05 00:44:28 -0400189 if (ACPI_FAILURE(status)) {
190 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 }
192
193 /* Make sure that the hardware responded */
194
Len Brown4be44fc2005-08-05 00:44:28 -0400195 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800196 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
197 enable_register_id, &value);
Len Brown4be44fc2005-08-05 00:44:28 -0400198 if (ACPI_FAILURE(status)) {
199 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 }
201
202 if (value != 1) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500203 ACPI_ERROR((AE_INFO,
204 "Could not enable %s event",
205 acpi_ut_get_event_name(event)));
Len Brown4be44fc2005-08-05 00:44:28 -0400206 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 }
208
Len Brown4be44fc2005-08-05 00:44:28 -0400209 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
Bob Moore83135242006-10-03 00:00:00 -0400212ACPI_EXPORT_SYMBOL(acpi_enable_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
214/*******************************************************************************
215 *
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200216 * FUNCTION: acpi_gpe_wakeup
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 *
Lin Ming0f849d22010-04-06 14:52:37 +0800218 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 * gpe_number - GPE level within the GPE block
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200220 * Action - Enable or Disable
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 *
222 * RETURN: Status
223 *
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200224 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 *
226 ******************************************************************************/
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200227acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228{
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200229 acpi_status status = AE_OK;
Len Brown4be44fc2005-08-05 00:44:28 -0400230 struct acpi_gpe_event_info *gpe_event_info;
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200231 struct acpi_gpe_register_info *gpe_register_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800232 acpi_cpu_flags flags;
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200233 u32 register_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200235 ACPI_FUNCTION_TRACE(acpi_gpe_wakeup);
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100236
237 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
239 /* Ensure that we have a valid GPE number */
240
Len Brown4be44fc2005-08-05 00:44:28 -0400241 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Rafael J. Wysocki9ce10df2010-07-08 00:45:34 +0200242 if (!gpe_event_info || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 status = AE_BAD_PARAMETER;
244 goto unlock_and_exit;
245 }
246
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200247 gpe_register_info = gpe_event_info->register_info;
248 if (!gpe_register_info) {
249 status = AE_NOT_EXIST;
250 goto unlock_and_exit;
251 }
252
253 register_bit =
254 acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
255
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100256 /* Perform the action */
257
258 switch (action) {
259 case ACPI_GPE_ENABLE:
Rafael J. Wysockia44061a2010-07-01 10:11:45 +0800260 ACPI_SET_BIT(gpe_register_info->enable_for_wake,
261 (u8)register_bit);
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100262 break;
263
264 case ACPI_GPE_DISABLE:
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200265 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
Rafael J. Wysockia44061a2010-07-01 10:11:45 +0800266 (u8)register_bit);
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100267 break;
268
269 default:
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200270 ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100271 status = AE_BAD_PARAMETER;
272 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 }
274
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200275unlock_and_exit:
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100276 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400277 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Rafael J. Wysockie8b6f972010-06-25 01:18:39 +0200280ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
282/*******************************************************************************
283 *
284 * FUNCTION: acpi_enable_gpe
285 *
Lin Ming0f849d22010-04-06 14:52:37 +0800286 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 * gpe_number - GPE level within the GPE block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 *
289 * RETURN: Status
290 *
Lin Ming0f849d22010-04-06 14:52:37 +0800291 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
Rafael J. Wysockia44061a2010-07-01 10:11:45 +0800292 * hardware-enabled.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 *
294 ******************************************************************************/
Rafael J. Wysockia44061a2010-07-01 10:11:45 +0800295acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296{
Rafael J. Wysocki28f4f8a2010-08-03 23:55:14 +0200297 acpi_status status = AE_BAD_PARAMETER;
Len Brown4be44fc2005-08-05 00:44:28 -0400298 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800299 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
Bob Mooreb229cf92006-04-21 17:15:00 -0400301 ACPI_FUNCTION_TRACE(acpi_enable_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400303 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
305 /* Ensure that we have a valid GPE number */
306
Len Brown4be44fc2005-08-05 00:44:28 -0400307 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Rafael J. Wysocki28f4f8a2010-08-03 23:55:14 +0200308 if (gpe_event_info) {
309 status = acpi_raw_enable_gpe(gpe_event_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 }
311
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400312 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400313 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314}
Bob Moore83135242006-10-03 00:00:00 -0400315ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
317/*******************************************************************************
318 *
319 * FUNCTION: acpi_disable_gpe
320 *
Lin Ming0f849d22010-04-06 14:52:37 +0800321 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 * gpe_number - GPE level within the GPE block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 *
324 * RETURN: Status
325 *
Lin Ming0f849d22010-04-06 14:52:37 +0800326 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
327 * removed, only then is the GPE disabled (for runtime GPEs), or
328 * the GPE mask bit disabled (for wake GPEs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 *
330 ******************************************************************************/
Rafael J. Wysockia44061a2010-07-01 10:11:45 +0800331acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332{
Rafael J. Wysocki28f4f8a2010-08-03 23:55:14 +0200333 acpi_status status = AE_BAD_PARAMETER;
Len Brown4be44fc2005-08-05 00:44:28 -0400334 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800335 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
Bob Mooreb229cf92006-04-21 17:15:00 -0400337 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400339 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Len Brown4be44fc2005-08-05 00:44:28 -0400340
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 /* Ensure that we have a valid GPE number */
342
Len Brown4be44fc2005-08-05 00:44:28 -0400343 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Rafael J. Wysocki28f4f8a2010-08-03 23:55:14 +0200344 if (gpe_event_info) {
345 status = acpi_raw_disable_gpe(gpe_event_info) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 }
347
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400348 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400349 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350}
Bob Moore83135242006-10-03 00:00:00 -0400351ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353/*******************************************************************************
354 *
Rafael J. Wysocki98746472010-07-08 00:43:36 +0200355 * FUNCTION: acpi_gpe_can_wake
356 *
357 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
358 * gpe_number - GPE level within the GPE block
359 *
360 * RETURN: Status
361 *
362 * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE. If the GPE
363 * has a corresponding method and is currently enabled, disable it
364 * (GPEs with corresponding methods are enabled unconditionally
365 * during initialization, but GPEs that can wake up are expected
366 * to be initially disabled).
367 *
368 ******************************************************************************/
369acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
370{
371 acpi_status status = AE_OK;
372 struct acpi_gpe_event_info *gpe_event_info;
373 acpi_cpu_flags flags;
Rafael J. Wysocki98746472010-07-08 00:43:36 +0200374
375 ACPI_FUNCTION_TRACE(acpi_gpe_can_wake);
376
Bob Moore768aaaf2009-03-06 09:49:25 +0800377 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Len Brown4be44fc2005-08-05 00:44:28 -0400378
379 /* Ensure that we have a valid GPE number */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
381 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200382 if (gpe_event_info) {
383 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
384 } else {
Bob Moore50ffba12009-02-23 15:02:07 +0800385 status = AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 }
387
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400389 return_ACPI_STATUS(status);
Bob Moore50ffba12009-02-23 15:02:07 +0800390}
Rafael J. Wysocki98746472010-07-08 00:43:36 +0200391ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
393/*******************************************************************************
394 *
395 * FUNCTION: acpi_disable_event
396 *
397 * PARAMETERS: Event - The fixed eventto be enabled
398 * Flags - Reserved
399 *
400 * RETURN: Status
401 *
402 * DESCRIPTION: Disable an ACPI event (fixed)
403 *
404 ******************************************************************************/
405acpi_status acpi_disable_event(u32 event, u32 flags)
406{
407 acpi_status status = AE_OK;
408 u32 value;
409
410 ACPI_FUNCTION_TRACE(acpi_disable_event);
411
412 /* Decode the Fixed Event */
413
414 if (event > ACPI_EVENT_MAX) {
415 return_ACPI_STATUS(AE_BAD_PARAMETER);
416 }
417
418 /*
419 * Disable the requested fixed event (by writing a zero to the enable
420 * register bit)
421 */
422 status =
423 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
424 enable_register_id, ACPI_DISABLE_EVENT);
425 if (ACPI_FAILURE(status)) {
426 return_ACPI_STATUS(status);
427 }
428
Len Brown4be44fc2005-08-05 00:44:28 -0400429 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800430 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
431 enable_register_id, &value);
Len Brown4be44fc2005-08-05 00:44:28 -0400432 if (ACPI_FAILURE(status)) {
433 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 }
435
436 if (value != 0) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500437 ACPI_ERROR((AE_INFO,
438 "Could not disable %s events",
439 acpi_ut_get_event_name(event)));
Len Brown4be44fc2005-08-05 00:44:28 -0400440 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 }
442
Len Brown4be44fc2005-08-05 00:44:28 -0400443 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
Bob Moore83135242006-10-03 00:00:00 -0400446ACPI_EXPORT_SYMBOL(acpi_disable_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
448/*******************************************************************************
449 *
450 * FUNCTION: acpi_clear_event
451 *
452 * PARAMETERS: Event - The fixed event to be cleared
453 *
454 * RETURN: Status
455 *
456 * DESCRIPTION: Clear an ACPI event (fixed)
457 *
458 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400459acpi_status acpi_clear_event(u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
Len Brown4be44fc2005-08-05 00:44:28 -0400461 acpi_status status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
Bob Mooreb229cf92006-04-21 17:15:00 -0400463 ACPI_FUNCTION_TRACE(acpi_clear_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
465 /* Decode the Fixed Event */
466
467 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400468 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 }
470
471 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800472 * Clear the requested fixed event (By writing a one to the status
473 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 */
Len Brown4be44fc2005-08-05 00:44:28 -0400475 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800476 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
Bob Moore768aaaf2009-03-06 09:49:25 +0800477 status_register_id, ACPI_CLEAR_STATUS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Len Brown4be44fc2005-08-05 00:44:28 -0400479 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
Bob Moore83135242006-10-03 00:00:00 -0400482ACPI_EXPORT_SYMBOL(acpi_clear_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484/*******************************************************************************
485 *
486 * FUNCTION: acpi_clear_gpe
487 *
Lin Ming0f849d22010-04-06 14:52:37 +0800488 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 * gpe_number - GPE level within the GPE block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 *
491 * RETURN: Status
492 *
493 * DESCRIPTION: Clear an ACPI event (general purpose)
494 *
495 ******************************************************************************/
Lin Ming0f849d22010-04-06 14:52:37 +0800496acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497{
Len Brown4be44fc2005-08-05 00:44:28 -0400498 acpi_status status = AE_OK;
499 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800500 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
Bob Mooreb229cf92006-04-21 17:15:00 -0400502 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
Lin Ming0f849d22010-04-06 14:52:37 +0800504 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
506 /* Ensure that we have a valid GPE number */
507
Len Brown4be44fc2005-08-05 00:44:28 -0400508 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 if (!gpe_event_info) {
510 status = AE_BAD_PARAMETER;
511 goto unlock_and_exit;
512 }
513
Len Brown4be44fc2005-08-05 00:44:28 -0400514 status = acpi_hw_clear_gpe(gpe_event_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
Len Brown4be44fc2005-08-05 00:44:28 -0400516 unlock_and_exit:
Lin Ming0f849d22010-04-06 14:52:37 +0800517 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400518 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519}
520
Bob Moore83135242006-10-03 00:00:00 -0400521ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522/*******************************************************************************
523 *
524 * FUNCTION: acpi_get_event_status
525 *
526 * PARAMETERS: Event - The fixed event
Robert Moore44f6c012005-04-18 22:49:35 -0400527 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 * be returned
529 *
530 * RETURN: Status
531 *
532 * DESCRIPTION: Obtains and returns the current status of the event
533 *
534 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400535acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536{
Len Brown4be44fc2005-08-05 00:44:28 -0400537 acpi_status status = AE_OK;
Zhang Rui71b58cb2008-06-20 09:42:47 +0800538 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
Bob Mooreb229cf92006-04-21 17:15:00 -0400540 ACPI_FUNCTION_TRACE(acpi_get_event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
542 if (!event_status) {
Len Brown4be44fc2005-08-05 00:44:28 -0400543 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 }
545
546 /* Decode the Fixed Event */
547
548 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400549 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 }
551
552 /* Get the status of the requested fixed event */
553
Len Brown4be44fc2005-08-05 00:44:28 -0400554 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800555 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
Zhang Rui71b58cb2008-06-20 09:42:47 +0800556 enable_register_id, &value);
557 if (ACPI_FAILURE(status))
558 return_ACPI_STATUS(status);
559
560 *event_status = value;
561
562 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800563 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
Zhang Rui71b58cb2008-06-20 09:42:47 +0800564 status_register_id, &value);
565 if (ACPI_FAILURE(status))
566 return_ACPI_STATUS(status);
567
568 if (value)
569 *event_status |= ACPI_EVENT_FLAG_SET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570
Zhang Ruied206fa2008-10-27 14:01:02 -0700571 if (acpi_gbl_fixed_event_handlers[event].handler)
572 *event_status |= ACPI_EVENT_FLAG_HANDLE;
573
Len Brown4be44fc2005-08-05 00:44:28 -0400574 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575}
576
Bob Moore83135242006-10-03 00:00:00 -0400577ACPI_EXPORT_SYMBOL(acpi_get_event_status)
578
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579/*******************************************************************************
580 *
581 * FUNCTION: acpi_get_gpe_status
582 *
Lin Ming0f849d22010-04-06 14:52:37 +0800583 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 * gpe_number - GPE level within the GPE block
Robert Moore44f6c012005-04-18 22:49:35 -0400585 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 * be returned
587 *
588 * RETURN: Status
589 *
590 * DESCRIPTION: Get status of an event (general purpose)
591 *
592 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400594acpi_get_gpe_status(acpi_handle gpe_device,
Lin Ming0f849d22010-04-06 14:52:37 +0800595 u32 gpe_number, acpi_event_status *event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596{
Len Brown4be44fc2005-08-05 00:44:28 -0400597 acpi_status status = AE_OK;
598 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800599 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Bob Mooreb229cf92006-04-21 17:15:00 -0400601 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Lin Ming0f849d22010-04-06 14:52:37 +0800603 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604
605 /* Ensure that we have a valid GPE number */
606
Len Brown4be44fc2005-08-05 00:44:28 -0400607 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 if (!gpe_event_info) {
609 status = AE_BAD_PARAMETER;
610 goto unlock_and_exit;
611 }
612
613 /* Obtain status on the requested GPE number */
614
Len Brown4be44fc2005-08-05 00:44:28 -0400615 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
Zhang Ruied206fa2008-10-27 14:01:02 -0700617 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
618 *event_status |= ACPI_EVENT_FLAG_HANDLE;
619
Len Brown4be44fc2005-08-05 00:44:28 -0400620 unlock_and_exit:
Lin Ming0f849d22010-04-06 14:52:37 +0800621 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400622 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623}
Bob Moore83135242006-10-03 00:00:00 -0400624
625ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626/*******************************************************************************
627 *
628 * FUNCTION: acpi_install_gpe_block
629 *
630 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
631 * gpe_block_address - Address and space_iD
632 * register_count - Number of GPE register pairs in the block
Robert Moore6f42ccf2005-05-13 00:00:00 -0400633 * interrupt_number - H/W interrupt for the block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 *
635 * RETURN: Status
636 *
637 * DESCRIPTION: Create and Install a block of GPE registers
638 *
639 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400641acpi_install_gpe_block(acpi_handle gpe_device,
642 struct acpi_generic_address *gpe_block_address,
643 u32 register_count, u32 interrupt_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200645 acpi_status status = AE_OK;
Len Brown4be44fc2005-08-05 00:44:28 -0400646 union acpi_operand_object *obj_desc;
647 struct acpi_namespace_node *node;
648 struct acpi_gpe_block_info *gpe_block;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Bob Mooreb229cf92006-04-21 17:15:00 -0400650 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Len Brown4be44fc2005-08-05 00:44:28 -0400652 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
653 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 }
655
Len Brown4be44fc2005-08-05 00:44:28 -0400656 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
657 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 return (status);
659 }
660
Bob Mooref24b6642009-12-11 14:57:00 +0800661 node = acpi_ns_validate_handle(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 if (!node) {
663 status = AE_BAD_PARAMETER;
664 goto unlock_and_exit;
665 }
666
667 /*
668 * For user-installed GPE Block Devices, the gpe_block_base_number
669 * is always zero
670 */
Len Brown4be44fc2005-08-05 00:44:28 -0400671 status =
672 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
673 interrupt_number, &gpe_block);
674 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 goto unlock_and_exit;
676 }
677
Lin Ming0f849d22010-04-06 14:52:37 +0800678 /* Install block in the device_object attached to the node */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Len Brown4be44fc2005-08-05 00:44:28 -0400680 obj_desc = acpi_ns_get_attached_object(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 if (!obj_desc) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400682
Lin Ming0f849d22010-04-06 14:52:37 +0800683 /*
684 * No object, create a new one (Device nodes do not always have
685 * an attached object)
686 */
Len Brown4be44fc2005-08-05 00:44:28 -0400687 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 if (!obj_desc) {
689 status = AE_NO_MEMORY;
690 goto unlock_and_exit;
691 }
692
Len Brown4be44fc2005-08-05 00:44:28 -0400693 status =
694 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
696 /* Remove local reference to the object */
697
Len Brown4be44fc2005-08-05 00:44:28 -0400698 acpi_ut_remove_reference(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Len Brown4be44fc2005-08-05 00:44:28 -0400700 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 goto unlock_and_exit;
702 }
703 }
704
Lin Ming0f849d22010-04-06 14:52:37 +0800705 /* Now install the GPE block in the device_object */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
707 obj_desc->device.gpe_block = gpe_block;
708
Len Brown4be44fc2005-08-05 00:44:28 -0400709 unlock_and_exit:
710 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
711 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Bob Moore83135242006-10-03 00:00:00 -0400714ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
716/*******************************************************************************
717 *
718 * FUNCTION: acpi_remove_gpe_block
719 *
720 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
721 *
722 * RETURN: Status
723 *
724 * DESCRIPTION: Remove a previously installed block of GPE registers
725 *
726 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400727acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728{
Len Brown4be44fc2005-08-05 00:44:28 -0400729 union acpi_operand_object *obj_desc;
730 acpi_status status;
731 struct acpi_namespace_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
Bob Mooreb229cf92006-04-21 17:15:00 -0400733 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
735 if (!gpe_device) {
Len Brown4be44fc2005-08-05 00:44:28 -0400736 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 }
738
Len Brown4be44fc2005-08-05 00:44:28 -0400739 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
740 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 return (status);
742 }
743
Bob Mooref24b6642009-12-11 14:57:00 +0800744 node = acpi_ns_validate_handle(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 if (!node) {
746 status = AE_BAD_PARAMETER;
747 goto unlock_and_exit;
748 }
749
750 /* Get the device_object attached to the node */
751
Len Brown4be44fc2005-08-05 00:44:28 -0400752 obj_desc = acpi_ns_get_attached_object(node);
753 if (!obj_desc || !obj_desc->device.gpe_block) {
754 return_ACPI_STATUS(AE_NULL_OBJECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 }
756
757 /* Delete the GPE block (but not the device_object) */
758
Len Brown4be44fc2005-08-05 00:44:28 -0400759 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
760 if (ACPI_SUCCESS(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 obj_desc->device.gpe_block = NULL;
762 }
763
Len Brown4be44fc2005-08-05 00:44:28 -0400764 unlock_and_exit:
765 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
766 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767}
Robert Moore44f6c012005-04-18 22:49:35 -0400768
Bob Moore83135242006-10-03 00:00:00 -0400769ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
Bob Mooree97d6bf2008-12-30 09:45:17 +0800770
771/*******************************************************************************
772 *
773 * FUNCTION: acpi_get_gpe_device
774 *
775 * PARAMETERS: Index - System GPE index (0-current_gpe_count)
776 * gpe_device - Where the parent GPE Device is returned
777 *
778 * RETURN: Status
779 *
780 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
781 * gpe device indicates that the gpe number is contained in one of
782 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
783 *
784 ******************************************************************************/
785acpi_status
786acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
787{
788 struct acpi_gpe_device_info info;
789 acpi_status status;
790
791 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
792
793 if (!gpe_device) {
794 return_ACPI_STATUS(AE_BAD_PARAMETER);
795 }
796
797 if (index >= acpi_current_gpe_count) {
798 return_ACPI_STATUS(AE_NOT_EXIST);
799 }
800
801 /* Setup and walk the GPE list */
802
803 info.index = index;
804 info.status = AE_NOT_EXIST;
805 info.gpe_device = NULL;
806 info.next_block_base_index = 0;
807
808 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
809 if (ACPI_FAILURE(status)) {
810 return_ACPI_STATUS(status);
811 }
812
813 *gpe_device = info.gpe_device;
814 return_ACPI_STATUS(info.status);
815}
816
817ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
818
819/*******************************************************************************
820 *
821 * FUNCTION: acpi_ev_get_gpe_device
822 *
823 * PARAMETERS: GPE_WALK_CALLBACK
824 *
825 * RETURN: Status
826 *
827 * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
828 * block device. NULL if the GPE is one of the FADT-defined GPEs.
829 *
830 ******************************************************************************/
Bob Mooree4c1ebf2009-04-22 13:02:06 +0800831static acpi_status
Bob Mooree97d6bf2008-12-30 09:45:17 +0800832acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
833 struct acpi_gpe_block_info *gpe_block, void *context)
834{
835 struct acpi_gpe_device_info *info = context;
836
837 /* Increment Index by the number of GPEs in this block */
838
Lin Ming0f849d22010-04-06 14:52:37 +0800839 info->next_block_base_index += gpe_block->gpe_count;
Bob Mooree97d6bf2008-12-30 09:45:17 +0800840
841 if (info->index < info->next_block_base_index) {
842 /*
843 * The GPE index is within this block, get the node. Leave the node
844 * NULL for the FADT-defined GPEs
845 */
846 if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
847 info->gpe_device = gpe_block->node;
848 }
849
850 info->status = AE_OK;
851 return (AE_CTRL_END);
852 }
853
854 return (AE_OK);
855}
Bob Moore08ac07b2008-12-30 09:55:48 +0800856
857/******************************************************************************
858 *
859 * FUNCTION: acpi_disable_all_gpes
860 *
861 * PARAMETERS: None
862 *
863 * RETURN: Status
864 *
865 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
866 *
867 ******************************************************************************/
868
869acpi_status acpi_disable_all_gpes(void)
870{
871 acpi_status status;
872
873 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
874
875 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
876 if (ACPI_FAILURE(status)) {
877 return_ACPI_STATUS(status);
878 }
879
880 status = acpi_hw_disable_all_gpes();
881 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
882
883 return_ACPI_STATUS(status);
884}
885
886/******************************************************************************
887 *
888 * FUNCTION: acpi_enable_all_runtime_gpes
889 *
890 * PARAMETERS: None
891 *
892 * RETURN: Status
893 *
894 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
895 *
896 ******************************************************************************/
897
898acpi_status acpi_enable_all_runtime_gpes(void)
899{
900 acpi_status status;
901
902 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
903
904 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
905 if (ACPI_FAILURE(status)) {
906 return_ACPI_STATUS(status);
907 }
908
909 status = acpi_hw_enable_all_runtime_gpes();
910 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
911
912 return_ACPI_STATUS(status);
913}
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200914
915/******************************************************************************
916 *
917 * FUNCTION: acpi_update_gpes
918 *
919 * PARAMETERS: None
920 *
921 * RETURN: None
922 *
923 * DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and
924 * are not pointed to by any device _PRW methods indicating that
925 * these GPEs are generally intended for system or device wakeup
926 * (such GPEs have to be enabled directly when the devices whose
927 * _PRW methods point to them are set up for wakeup signaling).
928 *
929 ******************************************************************************/
930
931acpi_status acpi_update_gpes(void)
932{
933 acpi_status status;
934
935 ACPI_FUNCTION_TRACE(acpi_update_gpes);
936
937 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
938 if (ACPI_FAILURE(status)) {
939 return_ACPI_STATUS(status);
940 } else if (acpi_all_gpes_initialized) {
941 goto unlock;
942 }
943
944 status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
945 if (ACPI_SUCCESS(status)) {
946 acpi_all_gpes_initialized = TRUE;
947 }
948
949unlock:
950 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
951
952 return_ACPI_STATUS(status);
953}