blob: 304825528d4803d22e025b9fb6d2220b10851d0b [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);
Len Brown4be44fc2005-08-05 00:44:28 -0400382 if (!gpe_event_info) {
Bob Moore50ffba12009-02-23 15:02:07 +0800383 status = AE_BAD_PARAMETER;
384 goto unlock_and_exit;
Len Brown4be44fc2005-08-05 00:44:28 -0400385 }
386
Rafael J. Wysocki98746472010-07-08 00:43:36 +0200387 if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
388 goto unlock_and_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 }
390
Rafael J. Wysocki98746472010-07-08 00:43:36 +0200391 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
Rafael J. Wysocki28f4f8a2010-08-03 23:55:14 +0200392 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) {
393 (void)acpi_raw_disable_gpe(gpe_event_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 }
395
396unlock_and_exit:
397 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
398 return_ACPI_STATUS(status);
399}
Rafael J. Wysocki98746472010-07-08 00:43:36 +0200400ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
402/*******************************************************************************
403 *
404 * FUNCTION: acpi_disable_event
405 *
406 * PARAMETERS: Event - The fixed eventto be enabled
407 * Flags - Reserved
408 *
409 * RETURN: Status
410 *
411 * DESCRIPTION: Disable an ACPI event (fixed)
412 *
413 ******************************************************************************/
414acpi_status acpi_disable_event(u32 event, u32 flags)
415{
416 acpi_status status = AE_OK;
417 u32 value;
418
419 ACPI_FUNCTION_TRACE(acpi_disable_event);
420
421 /* Decode the Fixed Event */
422
423 if (event > ACPI_EVENT_MAX) {
424 return_ACPI_STATUS(AE_BAD_PARAMETER);
425 }
426
427 /*
428 * Disable the requested fixed event (by writing a zero to the enable
429 * register bit)
430 */
431 status =
432 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
433 enable_register_id, ACPI_DISABLE_EVENT);
434 if (ACPI_FAILURE(status)) {
435 return_ACPI_STATUS(status);
436 }
437
438 status =
439 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
440 enable_register_id, &value);
441 if (ACPI_FAILURE(status)) {
442 return_ACPI_STATUS(status);
443 }
444
445 if (value != 0) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500446 ACPI_ERROR((AE_INFO,
447 "Could not disable %s events",
448 acpi_ut_get_event_name(event)));
Len Brown4be44fc2005-08-05 00:44:28 -0400449 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 }
451
Len Brown4be44fc2005-08-05 00:44:28 -0400452 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
Bob Moore83135242006-10-03 00:00:00 -0400455ACPI_EXPORT_SYMBOL(acpi_disable_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
457/*******************************************************************************
458 *
459 * FUNCTION: acpi_clear_event
460 *
461 * PARAMETERS: Event - The fixed event to be cleared
462 *
463 * RETURN: Status
464 *
465 * DESCRIPTION: Clear an ACPI event (fixed)
466 *
467 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400468acpi_status acpi_clear_event(u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469{
Len Brown4be44fc2005-08-05 00:44:28 -0400470 acpi_status status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
Bob Mooreb229cf92006-04-21 17:15:00 -0400472 ACPI_FUNCTION_TRACE(acpi_clear_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
474 /* Decode the Fixed Event */
475
476 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400477 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 }
479
480 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800481 * Clear the requested fixed event (By writing a one to the status
482 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 */
Len Brown4be44fc2005-08-05 00:44:28 -0400484 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800485 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
Bob Moore768aaaf2009-03-06 09:49:25 +0800486 status_register_id, ACPI_CLEAR_STATUS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
Len Brown4be44fc2005-08-05 00:44:28 -0400488 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
Bob Moore83135242006-10-03 00:00:00 -0400491ACPI_EXPORT_SYMBOL(acpi_clear_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
493/*******************************************************************************
494 *
495 * FUNCTION: acpi_clear_gpe
496 *
Lin Ming0f849d22010-04-06 14:52:37 +0800497 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 * gpe_number - GPE level within the GPE block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 *
500 * RETURN: Status
501 *
502 * DESCRIPTION: Clear an ACPI event (general purpose)
503 *
504 ******************************************************************************/
Lin Ming0f849d22010-04-06 14:52:37 +0800505acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506{
Len Brown4be44fc2005-08-05 00:44:28 -0400507 acpi_status status = AE_OK;
508 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800509 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
Bob Mooreb229cf92006-04-21 17:15:00 -0400511 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Lin Ming0f849d22010-04-06 14:52:37 +0800513 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
515 /* Ensure that we have a valid GPE number */
516
Len Brown4be44fc2005-08-05 00:44:28 -0400517 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 if (!gpe_event_info) {
519 status = AE_BAD_PARAMETER;
520 goto unlock_and_exit;
521 }
522
Len Brown4be44fc2005-08-05 00:44:28 -0400523 status = acpi_hw_clear_gpe(gpe_event_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Len Brown4be44fc2005-08-05 00:44:28 -0400525 unlock_and_exit:
Lin Ming0f849d22010-04-06 14:52:37 +0800526 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400527 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528}
529
Bob Moore83135242006-10-03 00:00:00 -0400530ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531/*******************************************************************************
532 *
533 * FUNCTION: acpi_get_event_status
534 *
535 * PARAMETERS: Event - The fixed event
Robert Moore44f6c012005-04-18 22:49:35 -0400536 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 * be returned
538 *
539 * RETURN: Status
540 *
541 * DESCRIPTION: Obtains and returns the current status of the event
542 *
543 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400544acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545{
Len Brown4be44fc2005-08-05 00:44:28 -0400546 acpi_status status = AE_OK;
Zhang Rui71b58cb2008-06-20 09:42:47 +0800547 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Bob Mooreb229cf92006-04-21 17:15:00 -0400549 ACPI_FUNCTION_TRACE(acpi_get_event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
551 if (!event_status) {
Len Brown4be44fc2005-08-05 00:44:28 -0400552 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 }
554
555 /* Decode the Fixed Event */
556
557 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400558 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 }
560
561 /* Get the status of the requested fixed event */
562
Len Brown4be44fc2005-08-05 00:44:28 -0400563 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800564 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
Zhang Rui71b58cb2008-06-20 09:42:47 +0800565 enable_register_id, &value);
566 if (ACPI_FAILURE(status))
567 return_ACPI_STATUS(status);
568
569 *event_status = value;
570
571 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800572 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
Zhang Rui71b58cb2008-06-20 09:42:47 +0800573 status_register_id, &value);
574 if (ACPI_FAILURE(status))
575 return_ACPI_STATUS(status);
576
577 if (value)
578 *event_status |= ACPI_EVENT_FLAG_SET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
Zhang Ruied206fa2008-10-27 14:01:02 -0700580 if (acpi_gbl_fixed_event_handlers[event].handler)
581 *event_status |= ACPI_EVENT_FLAG_HANDLE;
582
Len Brown4be44fc2005-08-05 00:44:28 -0400583 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584}
585
Bob Moore83135242006-10-03 00:00:00 -0400586ACPI_EXPORT_SYMBOL(acpi_get_event_status)
587
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588/*******************************************************************************
589 *
590 * FUNCTION: acpi_get_gpe_status
591 *
Lin Ming0f849d22010-04-06 14:52:37 +0800592 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 * gpe_number - GPE level within the GPE block
Robert Moore44f6c012005-04-18 22:49:35 -0400594 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 * be returned
596 *
597 * RETURN: Status
598 *
599 * DESCRIPTION: Get status of an event (general purpose)
600 *
601 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400603acpi_get_gpe_status(acpi_handle gpe_device,
Lin Ming0f849d22010-04-06 14:52:37 +0800604 u32 gpe_number, acpi_event_status *event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605{
Len Brown4be44fc2005-08-05 00:44:28 -0400606 acpi_status status = AE_OK;
607 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800608 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Bob Mooreb229cf92006-04-21 17:15:00 -0400610 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Lin Ming0f849d22010-04-06 14:52:37 +0800612 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
614 /* Ensure that we have a valid GPE number */
615
Len Brown4be44fc2005-08-05 00:44:28 -0400616 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 if (!gpe_event_info) {
618 status = AE_BAD_PARAMETER;
619 goto unlock_and_exit;
620 }
621
622 /* Obtain status on the requested GPE number */
623
Len Brown4be44fc2005-08-05 00:44:28 -0400624 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
Zhang Ruied206fa2008-10-27 14:01:02 -0700626 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
627 *event_status |= ACPI_EVENT_FLAG_HANDLE;
628
Len Brown4be44fc2005-08-05 00:44:28 -0400629 unlock_and_exit:
Lin Ming0f849d22010-04-06 14:52:37 +0800630 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400631 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632}
Bob Moore83135242006-10-03 00:00:00 -0400633
634ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635/*******************************************************************************
636 *
637 * FUNCTION: acpi_install_gpe_block
638 *
639 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
640 * gpe_block_address - Address and space_iD
641 * register_count - Number of GPE register pairs in the block
Robert Moore6f42ccf2005-05-13 00:00:00 -0400642 * interrupt_number - H/W interrupt for the block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 *
644 * RETURN: Status
645 *
646 * DESCRIPTION: Create and Install a block of GPE registers
647 *
648 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400650acpi_install_gpe_block(acpi_handle gpe_device,
651 struct acpi_generic_address *gpe_block_address,
652 u32 register_count, u32 interrupt_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653{
Len Brown4be44fc2005-08-05 00:44:28 -0400654 acpi_status status;
655 union acpi_operand_object *obj_desc;
656 struct acpi_namespace_node *node;
657 struct acpi_gpe_block_info *gpe_block;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
Bob Mooreb229cf92006-04-21 17:15:00 -0400659 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
Len Brown4be44fc2005-08-05 00:44:28 -0400661 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
662 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
664
Len Brown4be44fc2005-08-05 00:44:28 -0400665 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
666 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 return (status);
668 }
669
Bob Mooref24b6642009-12-11 14:57:00 +0800670 node = acpi_ns_validate_handle(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 if (!node) {
672 status = AE_BAD_PARAMETER;
673 goto unlock_and_exit;
674 }
675
676 /*
677 * For user-installed GPE Block Devices, the gpe_block_base_number
678 * is always zero
679 */
Len Brown4be44fc2005-08-05 00:44:28 -0400680 status =
681 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
682 interrupt_number, &gpe_block);
683 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 goto unlock_and_exit;
685 }
686
Lin Ming0f849d22010-04-06 14:52:37 +0800687 /* Install block in the device_object attached to the node */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
Len Brown4be44fc2005-08-05 00:44:28 -0400689 obj_desc = acpi_ns_get_attached_object(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 if (!obj_desc) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400691
Lin Ming0f849d22010-04-06 14:52:37 +0800692 /*
693 * No object, create a new one (Device nodes do not always have
694 * an attached object)
695 */
Len Brown4be44fc2005-08-05 00:44:28 -0400696 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 if (!obj_desc) {
698 status = AE_NO_MEMORY;
699 goto unlock_and_exit;
700 }
701
Len Brown4be44fc2005-08-05 00:44:28 -0400702 status =
703 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
705 /* Remove local reference to the object */
706
Len Brown4be44fc2005-08-05 00:44:28 -0400707 acpi_ut_remove_reference(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Len Brown4be44fc2005-08-05 00:44:28 -0400709 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 goto unlock_and_exit;
711 }
712 }
713
Lin Ming0f849d22010-04-06 14:52:37 +0800714 /* Now install the GPE block in the device_object */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
716 obj_desc->device.gpe_block = gpe_block;
717
Rafael J. Wysocki98746472010-07-08 00:43:36 +0200718 /* Enable the runtime GPEs in the new block */
Lin Ming0f849d22010-04-06 14:52:37 +0800719
720 status = acpi_ev_initialize_gpe_block(node, gpe_block);
721
Len Brown4be44fc2005-08-05 00:44:28 -0400722 unlock_and_exit:
723 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
724 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
Bob Moore83135242006-10-03 00:00:00 -0400727ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728
729/*******************************************************************************
730 *
731 * FUNCTION: acpi_remove_gpe_block
732 *
733 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
734 *
735 * RETURN: Status
736 *
737 * DESCRIPTION: Remove a previously installed block of GPE registers
738 *
739 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400740acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741{
Len Brown4be44fc2005-08-05 00:44:28 -0400742 union acpi_operand_object *obj_desc;
743 acpi_status status;
744 struct acpi_namespace_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
Bob Mooreb229cf92006-04-21 17:15:00 -0400746 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
748 if (!gpe_device) {
Len Brown4be44fc2005-08-05 00:44:28 -0400749 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 }
751
Len Brown4be44fc2005-08-05 00:44:28 -0400752 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
753 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 return (status);
755 }
756
Bob Mooref24b6642009-12-11 14:57:00 +0800757 node = acpi_ns_validate_handle(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 if (!node) {
759 status = AE_BAD_PARAMETER;
760 goto unlock_and_exit;
761 }
762
763 /* Get the device_object attached to the node */
764
Len Brown4be44fc2005-08-05 00:44:28 -0400765 obj_desc = acpi_ns_get_attached_object(node);
766 if (!obj_desc || !obj_desc->device.gpe_block) {
767 return_ACPI_STATUS(AE_NULL_OBJECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 }
769
770 /* Delete the GPE block (but not the device_object) */
771
Len Brown4be44fc2005-08-05 00:44:28 -0400772 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
773 if (ACPI_SUCCESS(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 obj_desc->device.gpe_block = NULL;
775 }
776
Len Brown4be44fc2005-08-05 00:44:28 -0400777 unlock_and_exit:
778 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
779 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780}
Robert Moore44f6c012005-04-18 22:49:35 -0400781
Bob Moore83135242006-10-03 00:00:00 -0400782ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
Bob Mooree97d6bf2008-12-30 09:45:17 +0800783
784/*******************************************************************************
785 *
786 * FUNCTION: acpi_get_gpe_device
787 *
788 * PARAMETERS: Index - System GPE index (0-current_gpe_count)
789 * gpe_device - Where the parent GPE Device is returned
790 *
791 * RETURN: Status
792 *
793 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
794 * gpe device indicates that the gpe number is contained in one of
795 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
796 *
797 ******************************************************************************/
798acpi_status
799acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
800{
801 struct acpi_gpe_device_info info;
802 acpi_status status;
803
804 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
805
806 if (!gpe_device) {
807 return_ACPI_STATUS(AE_BAD_PARAMETER);
808 }
809
810 if (index >= acpi_current_gpe_count) {
811 return_ACPI_STATUS(AE_NOT_EXIST);
812 }
813
814 /* Setup and walk the GPE list */
815
816 info.index = index;
817 info.status = AE_NOT_EXIST;
818 info.gpe_device = NULL;
819 info.next_block_base_index = 0;
820
821 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
822 if (ACPI_FAILURE(status)) {
823 return_ACPI_STATUS(status);
824 }
825
826 *gpe_device = info.gpe_device;
827 return_ACPI_STATUS(info.status);
828}
829
830ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
831
832/*******************************************************************************
833 *
834 * FUNCTION: acpi_ev_get_gpe_device
835 *
836 * PARAMETERS: GPE_WALK_CALLBACK
837 *
838 * RETURN: Status
839 *
840 * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
841 * block device. NULL if the GPE is one of the FADT-defined GPEs.
842 *
843 ******************************************************************************/
Bob Mooree4c1ebf2009-04-22 13:02:06 +0800844static acpi_status
Bob Mooree97d6bf2008-12-30 09:45:17 +0800845acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
846 struct acpi_gpe_block_info *gpe_block, void *context)
847{
848 struct acpi_gpe_device_info *info = context;
849
850 /* Increment Index by the number of GPEs in this block */
851
Lin Ming0f849d22010-04-06 14:52:37 +0800852 info->next_block_base_index += gpe_block->gpe_count;
Bob Mooree97d6bf2008-12-30 09:45:17 +0800853
854 if (info->index < info->next_block_base_index) {
855 /*
856 * The GPE index is within this block, get the node. Leave the node
857 * NULL for the FADT-defined GPEs
858 */
859 if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
860 info->gpe_device = gpe_block->node;
861 }
862
863 info->status = AE_OK;
864 return (AE_CTRL_END);
865 }
866
867 return (AE_OK);
868}
Bob Moore08ac07b2008-12-30 09:55:48 +0800869
870/******************************************************************************
871 *
872 * FUNCTION: acpi_disable_all_gpes
873 *
874 * PARAMETERS: None
875 *
876 * RETURN: Status
877 *
878 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
879 *
880 ******************************************************************************/
881
882acpi_status acpi_disable_all_gpes(void)
883{
884 acpi_status status;
885
886 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
887
888 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
889 if (ACPI_FAILURE(status)) {
890 return_ACPI_STATUS(status);
891 }
892
893 status = acpi_hw_disable_all_gpes();
894 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
895
896 return_ACPI_STATUS(status);
897}
898
899/******************************************************************************
900 *
901 * FUNCTION: acpi_enable_all_runtime_gpes
902 *
903 * PARAMETERS: None
904 *
905 * RETURN: Status
906 *
907 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
908 *
909 ******************************************************************************/
910
911acpi_status acpi_enable_all_runtime_gpes(void)
912{
913 acpi_status status;
914
915 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
916
917 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
918 if (ACPI_FAILURE(status)) {
919 return_ACPI_STATUS(status);
920 }
921
922 status = acpi_hw_enable_all_runtime_gpes();
923 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
924
925 return_ACPI_STATUS(status);
926}