blob: d97b8dce16681ba90886a3b0e5546cf5b7060ce8 [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;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Bob Mooreb229cf92006-04-21 17:15:00 -040074 ACPI_FUNCTION_TRACE(acpi_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Bob Moorec8573032007-02-02 19:48:23 +030076 /* ACPI tables must be present */
77
78 if (!acpi_tb_tables_loaded()) {
79 return_ACPI_STATUS(AE_NO_ACPI_TABLES);
80 }
81
82 /* Check current mode */
83
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
Len Brown4be44fc2005-08-05 00:44:28 -040085 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
86 "System is already in ACPI mode\n"));
Len Brownb430acb2010-05-06 17:41:08 -040087 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 }
89
Len Brownb430acb2010-05-06 17:41:08 -040090 /* Transition to ACPI mode */
91
92 status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
93 if (ACPI_FAILURE(status)) {
94 ACPI_ERROR((AE_INFO,
95 "Could not transition to ACPI mode"));
96 return_ACPI_STATUS(status);
97 }
98
99 /* Sanity check that transition succeeded */
100
101 if (acpi_hw_get_mode() != ACPI_SYS_MODE_ACPI) {
102 ACPI_ERROR((AE_INFO,
103 "Hardware did not enter ACPI mode"));
104 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
105 }
106
107 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
108 "Transition to ACPI mode successful\n"));
109
110 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111}
112
Bob Moore83135242006-10-03 00:00:00 -0400113ACPI_EXPORT_SYMBOL(acpi_enable)
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115/*******************************************************************************
116 *
117 * FUNCTION: acpi_disable
118 *
119 * PARAMETERS: None
120 *
121 * RETURN: Status
122 *
Robert Moore44f6c012005-04-18 22:49:35 -0400123 * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 *
125 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400126acpi_status acpi_disable(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127{
Len Brown4be44fc2005-08-05 00:44:28 -0400128 acpi_status status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Bob Mooreb229cf92006-04-21 17:15:00 -0400130 ACPI_FUNCTION_TRACE(acpi_disable);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
Len Brown4be44fc2005-08-05 00:44:28 -0400133 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
134 "System is already in legacy (non-ACPI) mode\n"));
135 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 /* Transition to LEGACY mode */
137
Len Brown4be44fc2005-08-05 00:44:28 -0400138 status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Len Brown4be44fc2005-08-05 00:44:28 -0400140 if (ACPI_FAILURE(status)) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500141 ACPI_ERROR((AE_INFO,
142 "Could not exit ACPI mode to legacy mode"));
Len Brown4be44fc2005-08-05 00:44:28 -0400143 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 }
145
Len Brown4be44fc2005-08-05 00:44:28 -0400146 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 }
148
Len Brown4be44fc2005-08-05 00:44:28 -0400149 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150}
151
Bob Moore83135242006-10-03 00:00:00 -0400152ACPI_EXPORT_SYMBOL(acpi_disable)
153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154/*******************************************************************************
155 *
156 * FUNCTION: acpi_enable_event
157 *
158 * PARAMETERS: Event - The fixed eventto be enabled
159 * Flags - Reserved
160 *
161 * RETURN: Status
162 *
163 * DESCRIPTION: Enable an ACPI event (fixed)
164 *
165 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400166acpi_status acpi_enable_event(u32 event, u32 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167{
Len Brown4be44fc2005-08-05 00:44:28 -0400168 acpi_status status = AE_OK;
169 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
Bob Mooreb229cf92006-04-21 17:15:00 -0400171 ACPI_FUNCTION_TRACE(acpi_enable_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173 /* Decode the Fixed Event */
174
175 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400176 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 }
178
179 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800180 * Enable the requested fixed event (by writing a one to the enable
181 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 */
Len Brown4be44fc2005-08-05 00:44:28 -0400183 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800184 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
Bob Moore768aaaf2009-03-06 09:49:25 +0800185 enable_register_id, ACPI_ENABLE_EVENT);
Len Brown4be44fc2005-08-05 00:44:28 -0400186 if (ACPI_FAILURE(status)) {
187 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 }
189
190 /* Make sure that the hardware responded */
191
Len Brown4be44fc2005-08-05 00:44:28 -0400192 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800193 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
194 enable_register_id, &value);
Len Brown4be44fc2005-08-05 00:44:28 -0400195 if (ACPI_FAILURE(status)) {
196 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 }
198
199 if (value != 1) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500200 ACPI_ERROR((AE_INFO,
201 "Could not enable %s event",
202 acpi_ut_get_event_name(event)));
Len Brown4be44fc2005-08-05 00:44:28 -0400203 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 }
205
Len Brown4be44fc2005-08-05 00:44:28 -0400206 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Bob Moore83135242006-10-03 00:00:00 -0400209ACPI_EXPORT_SYMBOL(acpi_enable_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
211/*******************************************************************************
212 *
Rafael J. Wysockifd247442010-06-08 10:49:08 +0200213 * FUNCTION: acpi_clear_and_enable_gpe
214 *
215 * PARAMETERS: gpe_event_info - GPE to enable
216 *
217 * RETURN: Status
218 *
219 * DESCRIPTION: Clear the given GPE from stale events and enable it.
220 *
221 ******************************************************************************/
222static acpi_status
223acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
224{
225 acpi_status status;
226
227 /*
228 * We will only allow a GPE to be enabled if it has either an
229 * associated method (_Lxx/_Exx) or a handler. Otherwise, the
230 * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
231 * first time it fires.
232 */
233 if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
234 return_ACPI_STATUS(AE_NO_HANDLER);
235 }
236
237 /* Clear the GPE (of stale events) */
238 status = acpi_hw_clear_gpe(gpe_event_info);
239 if (ACPI_FAILURE(status)) {
240 return_ACPI_STATUS(status);
241 }
242
243 /* Enable the requested GPE */
244 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
245
246 return_ACPI_STATUS(status);
247}
248
249/*******************************************************************************
250 *
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100251 * FUNCTION: acpi_set_gpe
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 *
Lin Ming0f849d22010-04-06 14:52:37 +0800253 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 * gpe_number - GPE level within the GPE block
Lin Ming0f849d22010-04-06 14:52:37 +0800255 * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 *
257 * RETURN: Status
258 *
Lin Ming0f849d22010-04-06 14:52:37 +0800259 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
260 * the reference count mechanism used in the acpi_enable_gpe and
261 * acpi_disable_gpe interfaces -- and should be used with care.
262 *
263 * Note: Typically used to disable a runtime GPE for short period of time,
264 * then re-enable it, without disturbing the existing reference counts. This
265 * is useful, for example, in the Embedded Controller (EC) driver.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 *
267 ******************************************************************************/
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100268acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
Len Brown4be44fc2005-08-05 00:44:28 -0400270 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800271 acpi_status status;
272 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100274 ACPI_FUNCTION_TRACE(acpi_set_gpe);
275
276 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
278 /* Ensure that we have a valid GPE number */
279
Len Brown4be44fc2005-08-05 00:44:28 -0400280 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 if (!gpe_event_info) {
282 status = AE_BAD_PARAMETER;
283 goto unlock_and_exit;
284 }
285
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100286 /* Perform the action */
287
288 switch (action) {
289 case ACPI_GPE_ENABLE:
Rafael J. Wysockifd247442010-06-08 10:49:08 +0200290 status = acpi_clear_and_enable_gpe(gpe_event_info);
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100291 break;
292
293 case ACPI_GPE_DISABLE:
Rafael J. Wysockifd247442010-06-08 10:49:08 +0200294 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100295 break;
296
297 default:
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100298 status = AE_BAD_PARAMETER;
299 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 }
301
Len Brown4be44fc2005-08-05 00:44:28 -0400302 unlock_and_exit:
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100303 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400304 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100307ACPI_EXPORT_SYMBOL(acpi_set_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
309/*******************************************************************************
310 *
311 * FUNCTION: acpi_enable_gpe
312 *
Lin Ming0f849d22010-04-06 14:52:37 +0800313 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 * gpe_number - GPE level within the GPE block
Lin Ming0f849d22010-04-06 14:52:37 +0800315 * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
316 * or both
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 *
318 * RETURN: Status
319 *
Lin Ming0f849d22010-04-06 14:52:37 +0800320 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
321 * hardware-enabled (for runtime GPEs), or the GPE register mask
322 * is updated (for wake GPEs).
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 *
324 ******************************************************************************/
Lin Ming0f849d22010-04-06 14:52:37 +0800325acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326{
Len Brown4be44fc2005-08-05 00:44:28 -0400327 acpi_status status = AE_OK;
328 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800329 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330
Bob Mooreb229cf92006-04-21 17:15:00 -0400331 ACPI_FUNCTION_TRACE(acpi_enable_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
Lin Ming0f849d22010-04-06 14:52:37 +0800333 /* Parameter validation */
334
335 if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100336 return_ACPI_STATUS(AE_BAD_PARAMETER);
Lin Ming0f849d22010-04-06 14:52:37 +0800337 }
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100338
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400339 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
341 /* 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 if (!gpe_event_info) {
345 status = AE_BAD_PARAMETER;
346 goto unlock_and_exit;
347 }
348
Lin Ming0f849d22010-04-06 14:52:37 +0800349 if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
350 if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
351 status = AE_LIMIT; /* Too many references */
352 goto unlock_and_exit;
353 }
354
355 gpe_event_info->runtime_count++;
356 if (gpe_event_info->runtime_count == 1) {
Rafael J. Wysockifd247442010-06-08 10:49:08 +0200357 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
358 if (ACPI_SUCCESS(status)) {
359 status = acpi_clear_and_enable_gpe(gpe_event_info);
360 }
361
Lin Ming0f849d22010-04-06 14:52:37 +0800362 if (ACPI_FAILURE(status)) {
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100363 gpe_event_info->runtime_count--;
Lin Ming0f849d22010-04-06 14:52:37 +0800364 goto unlock_and_exit;
365 }
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100366 }
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100367 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Lin Ming0f849d22010-04-06 14:52:37 +0800369 if (gpe_type & ACPI_GPE_TYPE_WAKE) {
370 /* The GPE must have the ability to wake the system */
371
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100372 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
Lin Ming0f849d22010-04-06 14:52:37 +0800373 status = AE_TYPE;
374 goto unlock_and_exit;
375 }
376
377 if (gpe_event_info->wakeup_count == ACPI_UINT8_MAX) {
378 status = AE_LIMIT; /* Too many references */
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100379 goto unlock_and_exit;
380 }
381
382 /*
Lin Ming0f849d22010-04-06 14:52:37 +0800383 * Update the enable mask on the first wakeup reference. Wake GPEs
384 * are only hardware-enabled just before sleeping.
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100385 */
Lin Ming0f849d22010-04-06 14:52:37 +0800386 gpe_event_info->wakeup_count++;
387 if (gpe_event_info->wakeup_count == 1) {
Rafael J. Wysockifd247442010-06-08 10:49:08 +0200388 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
Lin Ming0f849d22010-04-06 14:52:37 +0800389 }
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100390 }
391
392unlock_and_exit:
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400393 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400394 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395}
Bob Moore83135242006-10-03 00:00:00 -0400396ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
398/*******************************************************************************
399 *
400 * FUNCTION: acpi_disable_gpe
401 *
Lin Ming0f849d22010-04-06 14:52:37 +0800402 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 * gpe_number - GPE level within the GPE block
Lin Ming0f849d22010-04-06 14:52:37 +0800404 * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
405 * or both
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 *
407 * RETURN: Status
408 *
Lin Ming0f849d22010-04-06 14:52:37 +0800409 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
410 * removed, only then is the GPE disabled (for runtime GPEs), or
411 * the GPE mask bit disabled (for wake GPEs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 *
413 ******************************************************************************/
Lin Ming0f849d22010-04-06 14:52:37 +0800414acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415{
Len Brown4be44fc2005-08-05 00:44:28 -0400416 acpi_status status = AE_OK;
417 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800418 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Bob Mooreb229cf92006-04-21 17:15:00 -0400420 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Lin Ming0f849d22010-04-06 14:52:37 +0800422 /* Parameter validation */
423
424 if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100425 return_ACPI_STATUS(AE_BAD_PARAMETER);
Lin Ming0f849d22010-04-06 14:52:37 +0800426 }
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100427
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400428 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Lin Ming0f849d22010-04-06 14:52:37 +0800429
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 /* Ensure that we have a valid GPE number */
431
Len Brown4be44fc2005-08-05 00:44:28 -0400432 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 if (!gpe_event_info) {
434 status = AE_BAD_PARAMETER;
435 goto unlock_and_exit;
436 }
437
Lin Ming0f849d22010-04-06 14:52:37 +0800438 /* Hardware-disable a runtime GPE on removal of the last reference */
439
440 if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
441 if (!gpe_event_info->runtime_count) {
442 status = AE_LIMIT; /* There are no references to remove */
443 goto unlock_and_exit;
444 }
445
446 gpe_event_info->runtime_count--;
447 if (!gpe_event_info->runtime_count) {
Rafael J. Wysockifd247442010-06-08 10:49:08 +0200448 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
449 if (ACPI_SUCCESS(status)) {
450 status = acpi_hw_low_set_gpe(gpe_event_info,
451 ACPI_GPE_DISABLE);
452 }
453
Lin Ming0f849d22010-04-06 14:52:37 +0800454 if (ACPI_FAILURE(status)) {
455 gpe_event_info->runtime_count++;
456 goto unlock_and_exit;
457 }
458 }
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100459 }
460
Lin Ming0f849d22010-04-06 14:52:37 +0800461 /*
462 * Update masks for wake GPE on removal of the last reference.
463 * No need to hardware-disable wake GPEs here, they are not currently
464 * enabled.
465 */
466 if (gpe_type & ACPI_GPE_TYPE_WAKE) {
467 if (!gpe_event_info->wakeup_count) {
468 status = AE_LIMIT; /* There are no references to remove */
469 goto unlock_and_exit;
470 }
471
472 gpe_event_info->wakeup_count--;
473 if (!gpe_event_info->wakeup_count) {
Rafael J. Wysockifd247442010-06-08 10:49:08 +0200474 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
Lin Ming0f849d22010-04-06 14:52:37 +0800475 }
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100476 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400478unlock_and_exit:
479 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400480 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481}
Bob Moore83135242006-10-03 00:00:00 -0400482ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484/*******************************************************************************
485 *
486 * FUNCTION: acpi_disable_event
487 *
488 * PARAMETERS: Event - The fixed eventto be enabled
489 * Flags - Reserved
490 *
491 * RETURN: Status
492 *
493 * DESCRIPTION: Disable an ACPI event (fixed)
494 *
495 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400496acpi_status acpi_disable_event(u32 event, u32 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497{
Len Brown4be44fc2005-08-05 00:44:28 -0400498 acpi_status status = AE_OK;
499 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
Bob Mooreb229cf92006-04-21 17:15:00 -0400501 ACPI_FUNCTION_TRACE(acpi_disable_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
503 /* Decode the Fixed Event */
504
505 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400506 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 }
508
509 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800510 * Disable the requested fixed event (by writing a zero to the enable
511 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 */
Len Brown4be44fc2005-08-05 00:44:28 -0400513 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800514 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
Bob Moore768aaaf2009-03-06 09:49:25 +0800515 enable_register_id, ACPI_DISABLE_EVENT);
Len Brown4be44fc2005-08-05 00:44:28 -0400516 if (ACPI_FAILURE(status)) {
517 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 }
519
Len Brown4be44fc2005-08-05 00:44:28 -0400520 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800521 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
522 enable_register_id, &value);
Len Brown4be44fc2005-08-05 00:44:28 -0400523 if (ACPI_FAILURE(status)) {
524 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 }
526
527 if (value != 0) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500528 ACPI_ERROR((AE_INFO,
529 "Could not disable %s events",
530 acpi_ut_get_event_name(event)));
Len Brown4be44fc2005-08-05 00:44:28 -0400531 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 }
533
Len Brown4be44fc2005-08-05 00:44:28 -0400534 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Bob Moore83135242006-10-03 00:00:00 -0400537ACPI_EXPORT_SYMBOL(acpi_disable_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
539/*******************************************************************************
540 *
541 * FUNCTION: acpi_clear_event
542 *
543 * PARAMETERS: Event - The fixed event to be cleared
544 *
545 * RETURN: Status
546 *
547 * DESCRIPTION: Clear an ACPI event (fixed)
548 *
549 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400550acpi_status acpi_clear_event(u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
Len Brown4be44fc2005-08-05 00:44:28 -0400552 acpi_status status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
Bob Mooreb229cf92006-04-21 17:15:00 -0400554 ACPI_FUNCTION_TRACE(acpi_clear_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
556 /* Decode the Fixed Event */
557
558 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400559 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 }
561
562 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800563 * Clear the requested fixed event (By writing a one to the status
564 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 */
Len Brown4be44fc2005-08-05 00:44:28 -0400566 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800567 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
Bob Moore768aaaf2009-03-06 09:49:25 +0800568 status_register_id, ACPI_CLEAR_STATUS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
Len Brown4be44fc2005-08-05 00:44:28 -0400570 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
Bob Moore83135242006-10-03 00:00:00 -0400573ACPI_EXPORT_SYMBOL(acpi_clear_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
575/*******************************************************************************
576 *
577 * FUNCTION: acpi_clear_gpe
578 *
Lin Ming0f849d22010-04-06 14:52:37 +0800579 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 * gpe_number - GPE level within the GPE block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 *
582 * RETURN: Status
583 *
584 * DESCRIPTION: Clear an ACPI event (general purpose)
585 *
586 ******************************************************************************/
Lin Ming0f849d22010-04-06 14:52:37 +0800587acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588{
Len Brown4be44fc2005-08-05 00:44:28 -0400589 acpi_status status = AE_OK;
590 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800591 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Bob Mooreb229cf92006-04-21 17:15:00 -0400593 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Lin Ming0f849d22010-04-06 14:52:37 +0800595 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
597 /* Ensure that we have a valid GPE number */
598
Len Brown4be44fc2005-08-05 00:44:28 -0400599 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 if (!gpe_event_info) {
601 status = AE_BAD_PARAMETER;
602 goto unlock_and_exit;
603 }
604
Len Brown4be44fc2005-08-05 00:44:28 -0400605 status = acpi_hw_clear_gpe(gpe_event_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
Len Brown4be44fc2005-08-05 00:44:28 -0400607 unlock_and_exit:
Lin Ming0f849d22010-04-06 14:52:37 +0800608 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400609 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
611
Bob Moore83135242006-10-03 00:00:00 -0400612ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613/*******************************************************************************
614 *
615 * FUNCTION: acpi_get_event_status
616 *
617 * PARAMETERS: Event - The fixed event
Robert Moore44f6c012005-04-18 22:49:35 -0400618 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 * be returned
620 *
621 * RETURN: Status
622 *
623 * DESCRIPTION: Obtains and returns the current status of the event
624 *
625 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400626acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627{
Len Brown4be44fc2005-08-05 00:44:28 -0400628 acpi_status status = AE_OK;
Zhang Rui71b58cb2008-06-20 09:42:47 +0800629 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
Bob Mooreb229cf92006-04-21 17:15:00 -0400631 ACPI_FUNCTION_TRACE(acpi_get_event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
633 if (!event_status) {
Len Brown4be44fc2005-08-05 00:44:28 -0400634 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 }
636
637 /* Decode the Fixed Event */
638
639 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400640 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 }
642
643 /* Get the status of the requested fixed event */
644
Len Brown4be44fc2005-08-05 00:44:28 -0400645 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800646 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
Zhang Rui71b58cb2008-06-20 09:42:47 +0800647 enable_register_id, &value);
648 if (ACPI_FAILURE(status))
649 return_ACPI_STATUS(status);
650
651 *event_status = value;
652
653 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800654 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
Zhang Rui71b58cb2008-06-20 09:42:47 +0800655 status_register_id, &value);
656 if (ACPI_FAILURE(status))
657 return_ACPI_STATUS(status);
658
659 if (value)
660 *event_status |= ACPI_EVENT_FLAG_SET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Zhang Ruied206fa2008-10-27 14:01:02 -0700662 if (acpi_gbl_fixed_event_handlers[event].handler)
663 *event_status |= ACPI_EVENT_FLAG_HANDLE;
664
Len Brown4be44fc2005-08-05 00:44:28 -0400665 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666}
667
Bob Moore83135242006-10-03 00:00:00 -0400668ACPI_EXPORT_SYMBOL(acpi_get_event_status)
669
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670/*******************************************************************************
671 *
672 * FUNCTION: acpi_get_gpe_status
673 *
Lin Ming0f849d22010-04-06 14:52:37 +0800674 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 * gpe_number - GPE level within the GPE block
Robert Moore44f6c012005-04-18 22:49:35 -0400676 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 * be returned
678 *
679 * RETURN: Status
680 *
681 * DESCRIPTION: Get status of an event (general purpose)
682 *
683 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400685acpi_get_gpe_status(acpi_handle gpe_device,
Lin Ming0f849d22010-04-06 14:52:37 +0800686 u32 gpe_number, acpi_event_status *event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687{
Len Brown4be44fc2005-08-05 00:44:28 -0400688 acpi_status status = AE_OK;
689 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800690 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Bob Mooreb229cf92006-04-21 17:15:00 -0400692 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Lin Ming0f849d22010-04-06 14:52:37 +0800694 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
696 /* Ensure that we have a valid GPE number */
697
Len Brown4be44fc2005-08-05 00:44:28 -0400698 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 if (!gpe_event_info) {
700 status = AE_BAD_PARAMETER;
701 goto unlock_and_exit;
702 }
703
704 /* Obtain status on the requested GPE number */
705
Len Brown4be44fc2005-08-05 00:44:28 -0400706 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Zhang Ruied206fa2008-10-27 14:01:02 -0700708 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
709 *event_status |= ACPI_EVENT_FLAG_HANDLE;
710
Len Brown4be44fc2005-08-05 00:44:28 -0400711 unlock_and_exit:
Lin Ming0f849d22010-04-06 14:52:37 +0800712 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400713 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
Bob Moore83135242006-10-03 00:00:00 -0400715
716ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717/*******************************************************************************
718 *
719 * FUNCTION: acpi_install_gpe_block
720 *
721 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
722 * gpe_block_address - Address and space_iD
723 * register_count - Number of GPE register pairs in the block
Robert Moore6f42ccf2005-05-13 00:00:00 -0400724 * interrupt_number - H/W interrupt for the block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 *
726 * RETURN: Status
727 *
728 * DESCRIPTION: Create and Install a block of GPE registers
729 *
730 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400732acpi_install_gpe_block(acpi_handle gpe_device,
733 struct acpi_generic_address *gpe_block_address,
734 u32 register_count, u32 interrupt_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735{
Len Brown4be44fc2005-08-05 00:44:28 -0400736 acpi_status status;
737 union acpi_operand_object *obj_desc;
738 struct acpi_namespace_node *node;
739 struct acpi_gpe_block_info *gpe_block;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
Bob Mooreb229cf92006-04-21 17:15:00 -0400741 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
Len Brown4be44fc2005-08-05 00:44:28 -0400743 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
744 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 }
746
Len Brown4be44fc2005-08-05 00:44:28 -0400747 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
748 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return (status);
750 }
751
Bob Mooref24b6642009-12-11 14:57:00 +0800752 node = acpi_ns_validate_handle(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 if (!node) {
754 status = AE_BAD_PARAMETER;
755 goto unlock_and_exit;
756 }
757
758 /*
759 * For user-installed GPE Block Devices, the gpe_block_base_number
760 * is always zero
761 */
Len Brown4be44fc2005-08-05 00:44:28 -0400762 status =
763 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
764 interrupt_number, &gpe_block);
765 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 goto unlock_and_exit;
767 }
768
Lin Ming0f849d22010-04-06 14:52:37 +0800769 /* Install block in the device_object attached to the node */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
Len Brown4be44fc2005-08-05 00:44:28 -0400771 obj_desc = acpi_ns_get_attached_object(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 if (!obj_desc) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400773
Lin Ming0f849d22010-04-06 14:52:37 +0800774 /*
775 * No object, create a new one (Device nodes do not always have
776 * an attached object)
777 */
Len Brown4be44fc2005-08-05 00:44:28 -0400778 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 if (!obj_desc) {
780 status = AE_NO_MEMORY;
781 goto unlock_and_exit;
782 }
783
Len Brown4be44fc2005-08-05 00:44:28 -0400784 status =
785 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
787 /* Remove local reference to the object */
788
Len Brown4be44fc2005-08-05 00:44:28 -0400789 acpi_ut_remove_reference(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Len Brown4be44fc2005-08-05 00:44:28 -0400791 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 goto unlock_and_exit;
793 }
794 }
795
Lin Ming0f849d22010-04-06 14:52:37 +0800796 /* Now install the GPE block in the device_object */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
798 obj_desc->device.gpe_block = gpe_block;
799
Lin Ming0f849d22010-04-06 14:52:37 +0800800 /* Run the _PRW methods and enable the runtime GPEs in the new block */
801
802 status = acpi_ev_initialize_gpe_block(node, gpe_block);
803
Len Brown4be44fc2005-08-05 00:44:28 -0400804 unlock_and_exit:
805 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
806 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
Bob Moore83135242006-10-03 00:00:00 -0400809ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
811/*******************************************************************************
812 *
813 * FUNCTION: acpi_remove_gpe_block
814 *
815 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
816 *
817 * RETURN: Status
818 *
819 * DESCRIPTION: Remove a previously installed block of GPE registers
820 *
821 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400822acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823{
Len Brown4be44fc2005-08-05 00:44:28 -0400824 union acpi_operand_object *obj_desc;
825 acpi_status status;
826 struct acpi_namespace_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
Bob Mooreb229cf92006-04-21 17:15:00 -0400828 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
830 if (!gpe_device) {
Len Brown4be44fc2005-08-05 00:44:28 -0400831 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 }
833
Len Brown4be44fc2005-08-05 00:44:28 -0400834 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
835 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 return (status);
837 }
838
Bob Mooref24b6642009-12-11 14:57:00 +0800839 node = acpi_ns_validate_handle(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 if (!node) {
841 status = AE_BAD_PARAMETER;
842 goto unlock_and_exit;
843 }
844
845 /* Get the device_object attached to the node */
846
Len Brown4be44fc2005-08-05 00:44:28 -0400847 obj_desc = acpi_ns_get_attached_object(node);
848 if (!obj_desc || !obj_desc->device.gpe_block) {
849 return_ACPI_STATUS(AE_NULL_OBJECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 }
851
852 /* Delete the GPE block (but not the device_object) */
853
Len Brown4be44fc2005-08-05 00:44:28 -0400854 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
855 if (ACPI_SUCCESS(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 obj_desc->device.gpe_block = NULL;
857 }
858
Len Brown4be44fc2005-08-05 00:44:28 -0400859 unlock_and_exit:
860 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
861 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862}
Robert Moore44f6c012005-04-18 22:49:35 -0400863
Bob Moore83135242006-10-03 00:00:00 -0400864ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
Bob Mooree97d6bf2008-12-30 09:45:17 +0800865
866/*******************************************************************************
867 *
868 * FUNCTION: acpi_get_gpe_device
869 *
870 * PARAMETERS: Index - System GPE index (0-current_gpe_count)
871 * gpe_device - Where the parent GPE Device is returned
872 *
873 * RETURN: Status
874 *
875 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
876 * gpe device indicates that the gpe number is contained in one of
877 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
878 *
879 ******************************************************************************/
880acpi_status
881acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
882{
883 struct acpi_gpe_device_info info;
884 acpi_status status;
885
886 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
887
888 if (!gpe_device) {
889 return_ACPI_STATUS(AE_BAD_PARAMETER);
890 }
891
892 if (index >= acpi_current_gpe_count) {
893 return_ACPI_STATUS(AE_NOT_EXIST);
894 }
895
896 /* Setup and walk the GPE list */
897
898 info.index = index;
899 info.status = AE_NOT_EXIST;
900 info.gpe_device = NULL;
901 info.next_block_base_index = 0;
902
903 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
904 if (ACPI_FAILURE(status)) {
905 return_ACPI_STATUS(status);
906 }
907
908 *gpe_device = info.gpe_device;
909 return_ACPI_STATUS(info.status);
910}
911
912ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
913
914/*******************************************************************************
915 *
916 * FUNCTION: acpi_ev_get_gpe_device
917 *
918 * PARAMETERS: GPE_WALK_CALLBACK
919 *
920 * RETURN: Status
921 *
922 * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
923 * block device. NULL if the GPE is one of the FADT-defined GPEs.
924 *
925 ******************************************************************************/
Bob Mooree4c1ebf2009-04-22 13:02:06 +0800926static acpi_status
Bob Mooree97d6bf2008-12-30 09:45:17 +0800927acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
928 struct acpi_gpe_block_info *gpe_block, void *context)
929{
930 struct acpi_gpe_device_info *info = context;
931
932 /* Increment Index by the number of GPEs in this block */
933
Lin Ming0f849d22010-04-06 14:52:37 +0800934 info->next_block_base_index += gpe_block->gpe_count;
Bob Mooree97d6bf2008-12-30 09:45:17 +0800935
936 if (info->index < info->next_block_base_index) {
937 /*
938 * The GPE index is within this block, get the node. Leave the node
939 * NULL for the FADT-defined GPEs
940 */
941 if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
942 info->gpe_device = gpe_block->node;
943 }
944
945 info->status = AE_OK;
946 return (AE_CTRL_END);
947 }
948
949 return (AE_OK);
950}
Bob Moore08ac07b2008-12-30 09:55:48 +0800951
952/******************************************************************************
953 *
954 * FUNCTION: acpi_disable_all_gpes
955 *
956 * PARAMETERS: None
957 *
958 * RETURN: Status
959 *
960 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
961 *
962 ******************************************************************************/
963
964acpi_status acpi_disable_all_gpes(void)
965{
966 acpi_status status;
967
968 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
969
970 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
971 if (ACPI_FAILURE(status)) {
972 return_ACPI_STATUS(status);
973 }
974
975 status = acpi_hw_disable_all_gpes();
976 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
977
978 return_ACPI_STATUS(status);
979}
980
981/******************************************************************************
982 *
983 * FUNCTION: acpi_enable_all_runtime_gpes
984 *
985 * PARAMETERS: None
986 *
987 * RETURN: Status
988 *
989 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
990 *
991 ******************************************************************************/
992
993acpi_status acpi_enable_all_runtime_gpes(void)
994{
995 acpi_status status;
996
997 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
998
999 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
1000 if (ACPI_FAILURE(status)) {
1001 return_ACPI_STATUS(status);
1002 }
1003
1004 status = acpi_hw_enable_all_runtime_gpes();
1005 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
1006
1007 return_ACPI_STATUS(status);
1008}