]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/acpi/acpica/evxfevnt.c
Merge branch 'rc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuil...
[net-next-2.6.git] / drivers / acpi / acpica / evxfevnt.c
CommitLineData
1da177e4
LT
1/******************************************************************************
2 *
3 * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
4 *
5 *****************************************************************************/
6
7/*
a8357b0c 8 * Copyright (C) 2000 - 2010, Intel Corp.
1da177e4
LT
9 * 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
1da177e4 44#include <acpi/acpi.h>
e2f7a777
LB
45#include "accommon.h"
46#include "acevents.h"
47#include "acnamesp.h"
48#include "actables.h"
1da177e4
LT
49
50#define _COMPONENT ACPI_EVENTS
4be44fcd 51ACPI_MODULE_NAME("evxfevnt")
1da177e4 52
e97d6bf1 53/* Local prototypes */
e4c1ebfc 54static acpi_status
e97d6bf1
BM
55acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
56 struct acpi_gpe_block_info *gpe_block, void *context);
57
1da177e4
LT
58/*******************************************************************************
59 *
60 * FUNCTION: acpi_enable
61 *
62 * PARAMETERS: None
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: Transfers the system into ACPI mode.
67 *
68 ******************************************************************************/
e97d6bf1 69
4be44fcd 70acpi_status acpi_enable(void)
1da177e4 71{
b430acbd 72 acpi_status status;
1da177e4 73
b229cf92 74 ACPI_FUNCTION_TRACE(acpi_enable);
1da177e4 75
c857303a
BM
76 /* 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
1da177e4 84 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
4be44fcd
LB
85 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
86 "System is already in ACPI mode\n"));
b430acbd
LB
87 return_ACPI_STATUS(AE_OK);
88 }
1da177e4 89
b430acbd 90 /* Transition to ACPI mode */
1da177e4 91
b430acbd
LB
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);
1da177e4
LT
105 }
106
b430acbd
LB
107 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
108 "Transition to ACPI mode successful\n"));
109
110 return_ACPI_STATUS(AE_OK);
1da177e4
LT
111}
112
8313524a
BM
113ACPI_EXPORT_SYMBOL(acpi_enable)
114
1da177e4
LT
115/*******************************************************************************
116 *
117 * FUNCTION: acpi_disable
118 *
119 * PARAMETERS: None
120 *
121 * RETURN: Status
122 *
44f6c012 123 * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
1da177e4
LT
124 *
125 ******************************************************************************/
4be44fcd 126acpi_status acpi_disable(void)
1da177e4 127{
4be44fcd 128 acpi_status status = AE_OK;
1da177e4 129
b229cf92 130 ACPI_FUNCTION_TRACE(acpi_disable);
1da177e4 131
1da177e4 132 if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
4be44fcd
LB
133 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
134 "System is already in legacy (non-ACPI) mode\n"));
135 } else {
1da177e4
LT
136 /* Transition to LEGACY mode */
137
4be44fcd 138 status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
1da177e4 139
4be44fcd 140 if (ACPI_FAILURE(status)) {
b8e4d893
BM
141 ACPI_ERROR((AE_INFO,
142 "Could not exit ACPI mode to legacy mode"));
4be44fcd 143 return_ACPI_STATUS(status);
1da177e4
LT
144 }
145
4be44fcd 146 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
1da177e4
LT
147 }
148
4be44fcd 149 return_ACPI_STATUS(status);
1da177e4
LT
150}
151
8313524a
BM
152ACPI_EXPORT_SYMBOL(acpi_disable)
153
1da177e4
LT
154/*******************************************************************************
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 ******************************************************************************/
4be44fcd 166acpi_status acpi_enable_event(u32 event, u32 flags)
1da177e4 167{
4be44fcd
LB
168 acpi_status status = AE_OK;
169 u32 value;
1da177e4 170
b229cf92 171 ACPI_FUNCTION_TRACE(acpi_enable_event);
1da177e4
LT
172
173 /* Decode the Fixed Event */
174
175 if (event > ACPI_EVENT_MAX) {
4be44fcd 176 return_ACPI_STATUS(AE_BAD_PARAMETER);
1da177e4
LT
177 }
178
179 /*
9f15fc66
BM
180 * Enable the requested fixed event (by writing a one to the enable
181 * register bit)
1da177e4 182 */
4be44fcd 183 status =
50ffba1b 184 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
768aaaf1 185 enable_register_id, ACPI_ENABLE_EVENT);
4be44fcd
LB
186 if (ACPI_FAILURE(status)) {
187 return_ACPI_STATUS(status);
1da177e4
LT
188 }
189
190 /* Make sure that the hardware responded */
191
4be44fcd 192 status =
50ffba1b
BM
193 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
194 enable_register_id, &value);
4be44fcd
LB
195 if (ACPI_FAILURE(status)) {
196 return_ACPI_STATUS(status);
1da177e4
LT
197 }
198
199 if (value != 1) {
b8e4d893
BM
200 ACPI_ERROR((AE_INFO,
201 "Could not enable %s event",
202 acpi_ut_get_event_name(event)));
4be44fcd 203 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
1da177e4
LT
204 }
205
4be44fcd 206 return_ACPI_STATUS(status);
1da177e4 207}
1da177e4 208
8313524a 209ACPI_EXPORT_SYMBOL(acpi_enable_event)
1da177e4 210
fd247447
RW
211/*******************************************************************************
212 *
213 * 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
1da177e4
LT
249/*******************************************************************************
250 *
9630bdd9 251 * FUNCTION: acpi_set_gpe
1da177e4 252 *
0f849d2c 253 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
1da177e4 254 * gpe_number - GPE level within the GPE block
0f849d2c 255 * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
1da177e4
LT
256 *
257 * RETURN: Status
258 *
0f849d2c
LM
259 * 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.
1da177e4
LT
266 *
267 ******************************************************************************/
9630bdd9 268acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
1da177e4 269{
4be44fcd 270 struct acpi_gpe_event_info *gpe_event_info;
0f849d2c
LM
271 acpi_status status;
272 acpi_cpu_flags flags;
1da177e4 273
9630bdd9
RW
274 ACPI_FUNCTION_TRACE(acpi_set_gpe);
275
276 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
1da177e4
LT
277
278 /* Ensure that we have a valid GPE number */
279
4be44fcd 280 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
1da177e4
LT
281 if (!gpe_event_info) {
282 status = AE_BAD_PARAMETER;
283 goto unlock_and_exit;
284 }
285
9630bdd9
RW
286 /* Perform the action */
287
288 switch (action) {
289 case ACPI_GPE_ENABLE:
fd247447 290 status = acpi_clear_and_enable_gpe(gpe_event_info);
9630bdd9 291 break;
1da177e4 292
9630bdd9 293 case ACPI_GPE_DISABLE:
fd247447 294 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
9630bdd9 295 break;
1da177e4 296
9630bdd9 297 default:
9630bdd9
RW
298 status = AE_BAD_PARAMETER;
299 break;
300 }
1da177e4 301
4be44fcd 302 unlock_and_exit:
9630bdd9 303 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
4be44fcd 304 return_ACPI_STATUS(status);
1da177e4 305}
1da177e4 306
9630bdd9 307ACPI_EXPORT_SYMBOL(acpi_set_gpe)
1da177e4
LT
308
309/*******************************************************************************
310 *
311 * FUNCTION: acpi_enable_gpe
312 *
0f849d2c 313 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
1da177e4 314 * gpe_number - GPE level within the GPE block
0f849d2c
LM
315 * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
316 * or both
1da177e4
LT
317 *
318 * RETURN: Status
319 *
0f849d2c
LM
320 * 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).
1da177e4
LT
323 *
324 ******************************************************************************/
0f849d2c 325acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
1da177e4 326{
4be44fcd
LB
327 acpi_status status = AE_OK;
328 struct acpi_gpe_event_info *gpe_event_info;
0f849d2c 329 acpi_cpu_flags flags;
1da177e4 330
b229cf92 331 ACPI_FUNCTION_TRACE(acpi_enable_gpe);
1da177e4 332
0f849d2c
LM
333 /* Parameter validation */
334
335 if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
cbbc0de7 336 return_ACPI_STATUS(AE_BAD_PARAMETER);
0f849d2c 337 }
cbbc0de7 338
0b7084ac 339 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
1da177e4
LT
340
341 /* Ensure that we have a valid GPE number */
342
4be44fcd 343 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
1da177e4
LT
344 if (!gpe_event_info) {
345 status = AE_BAD_PARAMETER;
346 goto unlock_and_exit;
347 }
348
0f849d2c
LM
349 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) {
fd247447
RW
357 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
0f849d2c 362 if (ACPI_FAILURE(status)) {
cbbc0de7 363 gpe_event_info->runtime_count--;
0f849d2c
LM
364 goto unlock_and_exit;
365 }
cbbc0de7 366 }
9630bdd9 367 }
1da177e4 368
0f849d2c
LM
369 if (gpe_type & ACPI_GPE_TYPE_WAKE) {
370 /* The GPE must have the ability to wake the system */
371
9630bdd9 372 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
0f849d2c
LM
373 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 */
9630bdd9
RW
379 goto unlock_and_exit;
380 }
381
382 /*
0f849d2c
LM
383 * Update the enable mask on the first wakeup reference. Wake GPEs
384 * are only hardware-enabled just before sleeping.
9630bdd9 385 */
0f849d2c
LM
386 gpe_event_info->wakeup_count++;
387 if (gpe_event_info->wakeup_count == 1) {
fd247447 388 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
0f849d2c 389 }
9630bdd9
RW
390 }
391
392unlock_and_exit:
0b7084ac 393 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
4be44fcd 394 return_ACPI_STATUS(status);
1da177e4 395}
8313524a 396ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
1da177e4
LT
397
398/*******************************************************************************
399 *
400 * FUNCTION: acpi_disable_gpe
401 *
0f849d2c 402 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
1da177e4 403 * gpe_number - GPE level within the GPE block
0f849d2c
LM
404 * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
405 * or both
1da177e4
LT
406 *
407 * RETURN: Status
408 *
0f849d2c
LM
409 * 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)
1da177e4
LT
412 *
413 ******************************************************************************/
0f849d2c 414acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
1da177e4 415{
4be44fcd
LB
416 acpi_status status = AE_OK;
417 struct acpi_gpe_event_info *gpe_event_info;
0f849d2c 418 acpi_cpu_flags flags;
1da177e4 419
b229cf92 420 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
1da177e4 421
0f849d2c
LM
422 /* Parameter validation */
423
424 if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
cbbc0de7 425 return_ACPI_STATUS(AE_BAD_PARAMETER);
0f849d2c 426 }
cbbc0de7 427
0b7084ac 428 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
0f849d2c 429
1da177e4
LT
430 /* Ensure that we have a valid GPE number */
431
4be44fcd 432 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
1da177e4
LT
433 if (!gpe_event_info) {
434 status = AE_BAD_PARAMETER;
435 goto unlock_and_exit;
436 }
437
0f849d2c
LM
438 /* 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) {
fd247447
RW
448 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
0f849d2c
LM
454 if (ACPI_FAILURE(status)) {
455 gpe_event_info->runtime_count++;
456 goto unlock_and_exit;
457 }
458 }
9630bdd9
RW
459 }
460
0f849d2c
LM
461 /*
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) {
fd247447 474 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
0f849d2c 475 }
9630bdd9 476 }
1da177e4 477
0b7084ac
AS
478unlock_and_exit:
479 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
4be44fcd 480 return_ACPI_STATUS(status);
1da177e4 481}
8313524a
BM
482ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
483
1da177e4
LT
484/*******************************************************************************
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 ******************************************************************************/
4be44fcd 496acpi_status acpi_disable_event(u32 event, u32 flags)
1da177e4 497{
4be44fcd
LB
498 acpi_status status = AE_OK;
499 u32 value;
1da177e4 500
b229cf92 501 ACPI_FUNCTION_TRACE(acpi_disable_event);
1da177e4
LT
502
503 /* Decode the Fixed Event */
504
505 if (event > ACPI_EVENT_MAX) {
4be44fcd 506 return_ACPI_STATUS(AE_BAD_PARAMETER);
1da177e4
LT
507 }
508
509 /*
9f15fc66
BM
510 * Disable the requested fixed event (by writing a zero to the enable
511 * register bit)
1da177e4 512 */
4be44fcd 513 status =
50ffba1b 514 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
768aaaf1 515 enable_register_id, ACPI_DISABLE_EVENT);
4be44fcd
LB
516 if (ACPI_FAILURE(status)) {
517 return_ACPI_STATUS(status);
1da177e4
LT
518 }
519
4be44fcd 520 status =
50ffba1b
BM
521 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
522 enable_register_id, &value);
4be44fcd
LB
523 if (ACPI_FAILURE(status)) {
524 return_ACPI_STATUS(status);
1da177e4
LT
525 }
526
527 if (value != 0) {
b8e4d893
BM
528 ACPI_ERROR((AE_INFO,
529 "Could not disable %s events",
530 acpi_ut_get_event_name(event)));
4be44fcd 531 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
1da177e4
LT
532 }
533
4be44fcd 534 return_ACPI_STATUS(status);
1da177e4 535}
1da177e4 536
8313524a 537ACPI_EXPORT_SYMBOL(acpi_disable_event)
1da177e4
LT
538
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 ******************************************************************************/
4be44fcd 550acpi_status acpi_clear_event(u32 event)
1da177e4 551{
4be44fcd 552 acpi_status status = AE_OK;
1da177e4 553
b229cf92 554 ACPI_FUNCTION_TRACE(acpi_clear_event);
1da177e4
LT
555
556 /* Decode the Fixed Event */
557
558 if (event > ACPI_EVENT_MAX) {
4be44fcd 559 return_ACPI_STATUS(AE_BAD_PARAMETER);
1da177e4
LT
560 }
561
562 /*
9f15fc66
BM
563 * Clear the requested fixed event (By writing a one to the status
564 * register bit)
1da177e4 565 */
4be44fcd 566 status =
50ffba1b 567 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
768aaaf1 568 status_register_id, ACPI_CLEAR_STATUS);
1da177e4 569
4be44fcd 570 return_ACPI_STATUS(status);
1da177e4 571}
1da177e4 572
8313524a 573ACPI_EXPORT_SYMBOL(acpi_clear_event)
1da177e4
LT
574
575/*******************************************************************************
576 *
577 * FUNCTION: acpi_clear_gpe
578 *
0f849d2c 579 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
1da177e4 580 * gpe_number - GPE level within the GPE block
1da177e4
LT
581 *
582 * RETURN: Status
583 *
584 * DESCRIPTION: Clear an ACPI event (general purpose)
585 *
586 ******************************************************************************/
0f849d2c 587acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
1da177e4 588{
4be44fcd
LB
589 acpi_status status = AE_OK;
590 struct acpi_gpe_event_info *gpe_event_info;
0f849d2c 591 acpi_cpu_flags flags;
1da177e4 592
b229cf92 593 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
1da177e4 594
0f849d2c 595 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
1da177e4
LT
596
597 /* Ensure that we have a valid GPE number */
598
4be44fcd 599 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
1da177e4
LT
600 if (!gpe_event_info) {
601 status = AE_BAD_PARAMETER;
602 goto unlock_and_exit;
603 }
604
4be44fcd 605 status = acpi_hw_clear_gpe(gpe_event_info);
1da177e4 606
4be44fcd 607 unlock_and_exit:
0f849d2c 608 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
4be44fcd 609 return_ACPI_STATUS(status);
1da177e4
LT
610}
611
8313524a 612ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
1da177e4
LT
613/*******************************************************************************
614 *
615 * FUNCTION: acpi_get_event_status
616 *
617 * PARAMETERS: Event - The fixed event
44f6c012 618 * event_status - Where the current status of the event will
1da177e4
LT
619 * be returned
620 *
621 * RETURN: Status
622 *
623 * DESCRIPTION: Obtains and returns the current status of the event
624 *
625 ******************************************************************************/
4be44fcd 626acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
1da177e4 627{
4be44fcd 628 acpi_status status = AE_OK;
71b58cbb 629 u32 value;
1da177e4 630
b229cf92 631 ACPI_FUNCTION_TRACE(acpi_get_event_status);
1da177e4
LT
632
633 if (!event_status) {
4be44fcd 634 return_ACPI_STATUS(AE_BAD_PARAMETER);
1da177e4
LT
635 }
636
637 /* Decode the Fixed Event */
638
639 if (event > ACPI_EVENT_MAX) {
4be44fcd 640 return_ACPI_STATUS(AE_BAD_PARAMETER);
1da177e4
LT
641 }
642
643 /* Get the status of the requested fixed event */
644
4be44fcd 645 status =
50ffba1b 646 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
71b58cbb
ZR
647 enable_register_id, &value);
648 if (ACPI_FAILURE(status))
649 return_ACPI_STATUS(status);
650
651 *event_status = value;
652
653 status =
50ffba1b 654 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
71b58cbb
ZR
655 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;
1da177e4 661
ed206fac
ZR
662 if (acpi_gbl_fixed_event_handlers[event].handler)
663 *event_status |= ACPI_EVENT_FLAG_HANDLE;
664
4be44fcd 665 return_ACPI_STATUS(status);
1da177e4
LT
666}
667
8313524a
BM
668ACPI_EXPORT_SYMBOL(acpi_get_event_status)
669
1da177e4
LT
670/*******************************************************************************
671 *
672 * FUNCTION: acpi_get_gpe_status
673 *
0f849d2c 674 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
1da177e4 675 * gpe_number - GPE level within the GPE block
44f6c012 676 * event_status - Where the current status of the event will
1da177e4
LT
677 * be returned
678 *
679 * RETURN: Status
680 *
681 * DESCRIPTION: Get status of an event (general purpose)
682 *
683 ******************************************************************************/
1da177e4 684acpi_status
4be44fcd 685acpi_get_gpe_status(acpi_handle gpe_device,
0f849d2c 686 u32 gpe_number, acpi_event_status *event_status)
1da177e4 687{
4be44fcd
LB
688 acpi_status status = AE_OK;
689 struct acpi_gpe_event_info *gpe_event_info;
0f849d2c 690 acpi_cpu_flags flags;
1da177e4 691
b229cf92 692 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
1da177e4 693
0f849d2c 694 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
1da177e4
LT
695
696 /* Ensure that we have a valid GPE number */
697
4be44fcd 698 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
1da177e4
LT
699 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
4be44fcd 706 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
1da177e4 707
ed206fac
ZR
708 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
709 *event_status |= ACPI_EVENT_FLAG_HANDLE;
710
4be44fcd 711 unlock_and_exit:
0f849d2c 712 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
4be44fcd 713 return_ACPI_STATUS(status);
1da177e4 714}
8313524a
BM
715
716ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
1da177e4
LT
717/*******************************************************************************
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
6f42ccf2 724 * interrupt_number - H/W interrupt for the block
1da177e4
LT
725 *
726 * RETURN: Status
727 *
728 * DESCRIPTION: Create and Install a block of GPE registers
729 *
730 ******************************************************************************/
1da177e4 731acpi_status
4be44fcd
LB
732acpi_install_gpe_block(acpi_handle gpe_device,
733 struct acpi_generic_address *gpe_block_address,
734 u32 register_count, u32 interrupt_number)
1da177e4 735{
4be44fcd
LB
736 acpi_status status;
737 union acpi_operand_object *obj_desc;
738 struct acpi_namespace_node *node;
739 struct acpi_gpe_block_info *gpe_block;
1da177e4 740
b229cf92 741 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
1da177e4 742
4be44fcd
LB
743 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
744 return_ACPI_STATUS(AE_BAD_PARAMETER);
1da177e4
LT
745 }
746
4be44fcd
LB
747 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
748 if (ACPI_FAILURE(status)) {
1da177e4
LT
749 return (status);
750 }
751
f24b664d 752 node = acpi_ns_validate_handle(gpe_device);
1da177e4
LT
753 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 */
4be44fcd
LB
762 status =
763 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
764 interrupt_number, &gpe_block);
765 if (ACPI_FAILURE(status)) {
1da177e4
LT
766 goto unlock_and_exit;
767 }
768
0f849d2c 769 /* Install block in the device_object attached to the node */
1da177e4 770
4be44fcd 771 obj_desc = acpi_ns_get_attached_object(node);
1da177e4 772 if (!obj_desc) {
52fc0b02 773
0f849d2c
LM
774 /*
775 * No object, create a new one (Device nodes do not always have
776 * an attached object)
777 */
4be44fcd 778 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
1da177e4
LT
779 if (!obj_desc) {
780 status = AE_NO_MEMORY;
781 goto unlock_and_exit;
782 }
783
4be44fcd
LB
784 status =
785 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
1da177e4
LT
786
787 /* Remove local reference to the object */
788
4be44fcd 789 acpi_ut_remove_reference(obj_desc);
1da177e4 790
4be44fcd 791 if (ACPI_FAILURE(status)) {
1da177e4
LT
792 goto unlock_and_exit;
793 }
794 }
795
0f849d2c 796 /* Now install the GPE block in the device_object */
1da177e4
LT
797
798 obj_desc->device.gpe_block = gpe_block;
799
0f849d2c
LM
800 /* 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
4be44fcd
LB
804 unlock_and_exit:
805 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
806 return_ACPI_STATUS(status);
1da177e4 807}
1da177e4 808
8313524a 809ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
1da177e4
LT
810
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 ******************************************************************************/
4be44fcd 822acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
1da177e4 823{
4be44fcd
LB
824 union acpi_operand_object *obj_desc;
825 acpi_status status;
826 struct acpi_namespace_node *node;
1da177e4 827
b229cf92 828 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
1da177e4
LT
829
830 if (!gpe_device) {
4be44fcd 831 return_ACPI_STATUS(AE_BAD_PARAMETER);
1da177e4
LT
832 }
833
4be44fcd
LB
834 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
835 if (ACPI_FAILURE(status)) {
1da177e4
LT
836 return (status);
837 }
838
f24b664d 839 node = acpi_ns_validate_handle(gpe_device);
1da177e4
LT
840 if (!node) {
841 status = AE_BAD_PARAMETER;
842 goto unlock_and_exit;
843 }
844
845 /* Get the device_object attached to the node */
846
4be44fcd
LB
847 obj_desc = acpi_ns_get_attached_object(node);
848 if (!obj_desc || !obj_desc->device.gpe_block) {
849 return_ACPI_STATUS(AE_NULL_OBJECT);
1da177e4
LT
850 }
851
852 /* Delete the GPE block (but not the device_object) */
853
4be44fcd
LB
854 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
855 if (ACPI_SUCCESS(status)) {
1da177e4
LT
856 obj_desc->device.gpe_block = NULL;
857 }
858
4be44fcd
LB
859 unlock_and_exit:
860 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
861 return_ACPI_STATUS(status);
1da177e4 862}
44f6c012 863
8313524a 864ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
e97d6bf1
BM
865
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 ******************************************************************************/
e4c1ebfc 926static acpi_status
e97d6bf1
BM
927acpi_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
0f849d2c 934 info->next_block_base_index += gpe_block->gpe_count;
e97d6bf1
BM
935
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}
08ac07b8
BM
951
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}