blob: f7550da85d348d9605d2ad0c9886d25c0cfa328e [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/*
Len Brown75a44ce2008-04-23 23:00:13 -04008 * Copyright (C) 2000 - 2008, 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>
45#include <acpi/acevents.h>
46#include <acpi/acnamesp.h>
Bob Moore1a666f82007-02-02 19:48:23 +030047#include <acpi/actables.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49#define _COMPONENT ACPI_EVENTS
Len Brown4be44fc2005-08-05 00:44:28 -040050ACPI_MODULE_NAME("evxfevnt")
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Bob Mooree97d6bf2008-12-30 09:45:17 +080052/* Local prototypes */
53acpi_status
54acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
55 struct acpi_gpe_block_info *gpe_block, void *context);
56
Linus Torvalds1da177e2005-04-16 15:20:36 -070057/*******************************************************************************
58 *
59 * FUNCTION: acpi_enable
60 *
61 * PARAMETERS: None
62 *
63 * RETURN: Status
64 *
65 * DESCRIPTION: Transfers the system into ACPI mode.
66 *
67 ******************************************************************************/
Bob Mooree97d6bf2008-12-30 09:45:17 +080068
Len Brown4be44fc2005-08-05 00:44:28 -040069acpi_status acpi_enable(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070070{
Len Brown4be44fc2005-08-05 00:44:28 -040071 acpi_status status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
Bob Mooreb229cf92006-04-21 17:15:00 -040073 ACPI_FUNCTION_TRACE(acpi_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Bob Moorec8573032007-02-02 19:48:23 +030075 /* ACPI tables must be present */
76
77 if (!acpi_tb_tables_loaded()) {
78 return_ACPI_STATUS(AE_NO_ACPI_TABLES);
79 }
80
81 /* Check current mode */
82
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
Len Brown4be44fc2005-08-05 00:44:28 -040084 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
85 "System is already in ACPI mode\n"));
86 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 /* Transition to ACPI mode */
88
Len Brown4be44fc2005-08-05 00:44:28 -040089 status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
90 if (ACPI_FAILURE(status)) {
Bob Mooreb8e4d892006-01-27 16:43:00 -050091 ACPI_ERROR((AE_INFO,
92 "Could not transition to ACPI mode"));
Len Brown4be44fc2005-08-05 00:44:28 -040093 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 }
95
Len Brown4be44fc2005-08-05 00:44:28 -040096 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
97 "Transition to ACPI mode successful\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 }
99
Len Brown4be44fc2005-08-05 00:44:28 -0400100 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101}
102
Bob Moore83135242006-10-03 00:00:00 -0400103ACPI_EXPORT_SYMBOL(acpi_enable)
104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105/*******************************************************************************
106 *
107 * FUNCTION: acpi_disable
108 *
109 * PARAMETERS: None
110 *
111 * RETURN: Status
112 *
Robert Moore44f6c012005-04-18 22:49:35 -0400113 * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 *
115 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400116acpi_status acpi_disable(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117{
Len Brown4be44fc2005-08-05 00:44:28 -0400118 acpi_status status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Bob Mooreb229cf92006-04-21 17:15:00 -0400120 ACPI_FUNCTION_TRACE(acpi_disable);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
Len Brown4be44fc2005-08-05 00:44:28 -0400123 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
124 "System is already in legacy (non-ACPI) mode\n"));
125 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 /* Transition to LEGACY mode */
127
Len Brown4be44fc2005-08-05 00:44:28 -0400128 status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Len Brown4be44fc2005-08-05 00:44:28 -0400130 if (ACPI_FAILURE(status)) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500131 ACPI_ERROR((AE_INFO,
132 "Could not exit ACPI mode to legacy mode"));
Len Brown4be44fc2005-08-05 00:44:28 -0400133 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 }
135
Len Brown4be44fc2005-08-05 00:44:28 -0400136 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 }
138
Len Brown4be44fc2005-08-05 00:44:28 -0400139 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140}
141
Bob Moore83135242006-10-03 00:00:00 -0400142ACPI_EXPORT_SYMBOL(acpi_disable)
143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144/*******************************************************************************
145 *
146 * FUNCTION: acpi_enable_event
147 *
148 * PARAMETERS: Event - The fixed eventto be enabled
149 * Flags - Reserved
150 *
151 * RETURN: Status
152 *
153 * DESCRIPTION: Enable an ACPI event (fixed)
154 *
155 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400156acpi_status acpi_enable_event(u32 event, u32 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157{
Len Brown4be44fc2005-08-05 00:44:28 -0400158 acpi_status status = AE_OK;
159 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
Bob Mooreb229cf92006-04-21 17:15:00 -0400161 ACPI_FUNCTION_TRACE(acpi_enable_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
163 /* Decode the Fixed Event */
164
165 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400166 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 }
168
169 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800170 * Enable the requested fixed event (by writing a one to the enable
171 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 */
Len Brown4be44fc2005-08-05 00:44:28 -0400173 status =
174 acpi_set_register(acpi_gbl_fixed_event_info[event].
Bob Moored8c71b62007-02-02 19:48:21 +0300175 enable_register_id, 1);
Len Brown4be44fc2005-08-05 00:44:28 -0400176 if (ACPI_FAILURE(status)) {
177 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 }
179
180 /* Make sure that the hardware responded */
181
Len Brown4be44fc2005-08-05 00:44:28 -0400182 status =
183 acpi_get_register(acpi_gbl_fixed_event_info[event].
Bob Moored8c71b62007-02-02 19:48:21 +0300184 enable_register_id, &value);
Len Brown4be44fc2005-08-05 00:44:28 -0400185 if (ACPI_FAILURE(status)) {
186 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 }
188
189 if (value != 1) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500190 ACPI_ERROR((AE_INFO,
191 "Could not enable %s event",
192 acpi_ut_get_event_name(event)));
Len Brown4be44fc2005-08-05 00:44:28 -0400193 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 }
195
Len Brown4be44fc2005-08-05 00:44:28 -0400196 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
Bob Moore83135242006-10-03 00:00:00 -0400199ACPI_EXPORT_SYMBOL(acpi_enable_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201/*******************************************************************************
202 *
203 * FUNCTION: acpi_set_gpe_type
204 *
205 * PARAMETERS: gpe_device - Parent GPE Device
206 * gpe_number - GPE level within the GPE block
207 * Type - New GPE type
208 *
209 * RETURN: Status
210 *
Robert Moore44f6c012005-04-18 22:49:35 -0400211 * DESCRIPTION: Set the type of an individual GPE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 *
213 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400214acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215{
Len Brown4be44fc2005-08-05 00:44:28 -0400216 acpi_status status = AE_OK;
217 struct acpi_gpe_event_info *gpe_event_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Bob Mooreb229cf92006-04-21 17:15:00 -0400219 ACPI_FUNCTION_TRACE(acpi_set_gpe_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
221 /* Ensure that we have a valid GPE number */
222
Len Brown4be44fc2005-08-05 00:44:28 -0400223 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 if (!gpe_event_info) {
225 status = AE_BAD_PARAMETER;
226 goto unlock_and_exit;
227 }
228
229 if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
Len Brown4be44fc2005-08-05 00:44:28 -0400230 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 }
232
233 /* Set the new type (will disable GPE if currently enabled) */
234
Len Brown4be44fc2005-08-05 00:44:28 -0400235 status = acpi_ev_set_gpe_type(gpe_event_info, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
Len Brown4be44fc2005-08-05 00:44:28 -0400237 unlock_and_exit:
238 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
Bob Moore83135242006-10-03 00:00:00 -0400241ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
243/*******************************************************************************
244 *
245 * FUNCTION: acpi_enable_gpe
246 *
247 * PARAMETERS: gpe_device - Parent GPE Device
248 * gpe_number - GPE level within the GPE block
249 * Flags - Just enable, or also wake enable?
250 * Called from ISR or not
251 *
252 * RETURN: Status
253 *
254 * DESCRIPTION: Enable an ACPI event (general purpose)
255 *
256 ******************************************************************************/
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400257acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258{
Len Brown4be44fc2005-08-05 00:44:28 -0400259 acpi_status status = AE_OK;
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400260 acpi_cpu_flags flags;
Len Brown4be44fc2005-08-05 00:44:28 -0400261 struct acpi_gpe_event_info *gpe_event_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Bob Mooreb229cf92006-04-21 17:15:00 -0400263 ACPI_FUNCTION_TRACE(acpi_enable_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400265 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
267 /* Ensure that we have a valid GPE number */
268
Len Brown4be44fc2005-08-05 00:44:28 -0400269 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 if (!gpe_event_info) {
271 status = AE_BAD_PARAMETER;
272 goto unlock_and_exit;
273 }
274
275 /* Perform the enable */
276
Len Brown4be44fc2005-08-05 00:44:28 -0400277 status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Len Brown4be44fc2005-08-05 00:44:28 -0400279 unlock_and_exit:
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400280 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400281 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
Bob Moore83135242006-10-03 00:00:00 -0400284ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286/*******************************************************************************
287 *
288 * FUNCTION: acpi_disable_gpe
289 *
290 * PARAMETERS: gpe_device - Parent GPE Device
291 * gpe_number - GPE level within the GPE block
292 * Flags - Just disable, or also wake disable?
293 * Called from ISR or not
294 *
295 * RETURN: Status
296 *
297 * DESCRIPTION: Disable an ACPI event (general purpose)
298 *
299 ******************************************************************************/
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400300acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301{
Len Brown4be44fc2005-08-05 00:44:28 -0400302 acpi_status status = AE_OK;
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400303 acpi_cpu_flags flags;
Len Brown4be44fc2005-08-05 00:44:28 -0400304 struct acpi_gpe_event_info *gpe_event_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Bob Mooreb229cf92006-04-21 17:15:00 -0400306 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400308 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 /* Ensure that we have a valid GPE number */
310
Len Brown4be44fc2005-08-05 00:44:28 -0400311 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 if (!gpe_event_info) {
313 status = AE_BAD_PARAMETER;
314 goto unlock_and_exit;
315 }
316
Len Brown4be44fc2005-08-05 00:44:28 -0400317 status = acpi_ev_disable_gpe(gpe_event_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400319unlock_and_exit:
320 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400321 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322}
323
Bob Moore83135242006-10-03 00:00:00 -0400324ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326/*******************************************************************************
327 *
328 * FUNCTION: acpi_disable_event
329 *
330 * PARAMETERS: Event - The fixed eventto be enabled
331 * Flags - Reserved
332 *
333 * RETURN: Status
334 *
335 * DESCRIPTION: Disable an ACPI event (fixed)
336 *
337 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400338acpi_status acpi_disable_event(u32 event, u32 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339{
Len Brown4be44fc2005-08-05 00:44:28 -0400340 acpi_status status = AE_OK;
341 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
Bob Mooreb229cf92006-04-21 17:15:00 -0400343 ACPI_FUNCTION_TRACE(acpi_disable_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
345 /* Decode the Fixed Event */
346
347 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400348 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 }
350
351 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800352 * Disable the requested fixed event (by writing a zero to the enable
353 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 */
Len Brown4be44fc2005-08-05 00:44:28 -0400355 status =
356 acpi_set_register(acpi_gbl_fixed_event_info[event].
Bob Moored8c71b62007-02-02 19:48:21 +0300357 enable_register_id, 0);
Len Brown4be44fc2005-08-05 00:44:28 -0400358 if (ACPI_FAILURE(status)) {
359 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 }
361
Len Brown4be44fc2005-08-05 00:44:28 -0400362 status =
363 acpi_get_register(acpi_gbl_fixed_event_info[event].
Bob Moored8c71b62007-02-02 19:48:21 +0300364 enable_register_id, &value);
Len Brown4be44fc2005-08-05 00:44:28 -0400365 if (ACPI_FAILURE(status)) {
366 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 }
368
369 if (value != 0) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500370 ACPI_ERROR((AE_INFO,
371 "Could not disable %s events",
372 acpi_ut_get_event_name(event)));
Len Brown4be44fc2005-08-05 00:44:28 -0400373 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 }
375
Len Brown4be44fc2005-08-05 00:44:28 -0400376 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
Bob Moore83135242006-10-03 00:00:00 -0400379ACPI_EXPORT_SYMBOL(acpi_disable_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
381/*******************************************************************************
382 *
383 * FUNCTION: acpi_clear_event
384 *
385 * PARAMETERS: Event - The fixed event to be cleared
386 *
387 * RETURN: Status
388 *
389 * DESCRIPTION: Clear an ACPI event (fixed)
390 *
391 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400392acpi_status acpi_clear_event(u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393{
Len Brown4be44fc2005-08-05 00:44:28 -0400394 acpi_status status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Bob Mooreb229cf92006-04-21 17:15:00 -0400396 ACPI_FUNCTION_TRACE(acpi_clear_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
398 /* Decode the Fixed Event */
399
400 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400401 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 }
403
404 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800405 * Clear the requested fixed event (By writing a one to the status
406 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 */
Len Brown4be44fc2005-08-05 00:44:28 -0400408 status =
409 acpi_set_register(acpi_gbl_fixed_event_info[event].
Bob Moored8c71b62007-02-02 19:48:21 +0300410 status_register_id, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Len Brown4be44fc2005-08-05 00:44:28 -0400412 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Bob Moore83135242006-10-03 00:00:00 -0400415ACPI_EXPORT_SYMBOL(acpi_clear_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
417/*******************************************************************************
418 *
419 * FUNCTION: acpi_clear_gpe
420 *
421 * PARAMETERS: gpe_device - Parent GPE Device
422 * gpe_number - GPE level within the GPE block
423 * Flags - Called from an ISR or not
424 *
425 * RETURN: Status
426 *
427 * DESCRIPTION: Clear an ACPI event (general purpose)
428 *
429 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400430acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
Len Brown4be44fc2005-08-05 00:44:28 -0400432 acpi_status status = AE_OK;
433 struct acpi_gpe_event_info *gpe_event_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Bob Mooreb229cf92006-04-21 17:15:00 -0400435 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
437 /* Use semaphore lock if not executing at interrupt level */
438
439 if (flags & ACPI_NOT_ISR) {
Len Brown4be44fc2005-08-05 00:44:28 -0400440 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
441 if (ACPI_FAILURE(status)) {
442 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 }
444 }
445
446 /* Ensure that we have a valid GPE number */
447
Len Brown4be44fc2005-08-05 00:44:28 -0400448 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 if (!gpe_event_info) {
450 status = AE_BAD_PARAMETER;
451 goto unlock_and_exit;
452 }
453
Len Brown4be44fc2005-08-05 00:44:28 -0400454 status = acpi_hw_clear_gpe(gpe_event_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
Len Brown4be44fc2005-08-05 00:44:28 -0400456 unlock_and_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 if (flags & ACPI_NOT_ISR) {
Len Brown4be44fc2005-08-05 00:44:28 -0400458 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 }
Len Brown4be44fc2005-08-05 00:44:28 -0400460 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461}
462
Bob Moore83135242006-10-03 00:00:00 -0400463ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464/*******************************************************************************
465 *
466 * FUNCTION: acpi_get_event_status
467 *
468 * PARAMETERS: Event - The fixed event
Robert Moore44f6c012005-04-18 22:49:35 -0400469 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 * be returned
471 *
472 * RETURN: Status
473 *
474 * DESCRIPTION: Obtains and returns the current status of the event
475 *
476 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400477acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478{
Len Brown4be44fc2005-08-05 00:44:28 -0400479 acpi_status status = AE_OK;
Zhang Rui71b58cb2008-06-20 09:42:47 +0800480 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
Bob Mooreb229cf92006-04-21 17:15:00 -0400482 ACPI_FUNCTION_TRACE(acpi_get_event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 if (!event_status) {
Len Brown4be44fc2005-08-05 00:44:28 -0400485 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 }
487
488 /* Decode the Fixed Event */
489
490 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400491 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 }
493
494 /* Get the status of the requested fixed event */
495
Len Brown4be44fc2005-08-05 00:44:28 -0400496 status =
497 acpi_get_register(acpi_gbl_fixed_event_info[event].
Zhang Rui71b58cb2008-06-20 09:42:47 +0800498 enable_register_id, &value);
499 if (ACPI_FAILURE(status))
500 return_ACPI_STATUS(status);
501
502 *event_status = value;
503
504 status =
505 acpi_get_register(acpi_gbl_fixed_event_info[event].
506 status_register_id, &value);
507 if (ACPI_FAILURE(status))
508 return_ACPI_STATUS(status);
509
510 if (value)
511 *event_status |= ACPI_EVENT_FLAG_SET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Zhang Ruied206fa2008-10-27 14:01:02 -0700513 if (acpi_gbl_fixed_event_handlers[event].handler)
514 *event_status |= ACPI_EVENT_FLAG_HANDLE;
515
Len Brown4be44fc2005-08-05 00:44:28 -0400516 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517}
518
Bob Moore83135242006-10-03 00:00:00 -0400519ACPI_EXPORT_SYMBOL(acpi_get_event_status)
520
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521/*******************************************************************************
522 *
523 * FUNCTION: acpi_get_gpe_status
524 *
525 * PARAMETERS: gpe_device - Parent GPE Device
526 * gpe_number - GPE level within the GPE block
527 * Flags - Called from an ISR or not
Robert Moore44f6c012005-04-18 22:49:35 -0400528 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 * be returned
530 *
531 * RETURN: Status
532 *
533 * DESCRIPTION: Get status of an event (general purpose)
534 *
535 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400537acpi_get_gpe_status(acpi_handle gpe_device,
538 u32 gpe_number, u32 flags, acpi_event_status * event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539{
Len Brown4be44fc2005-08-05 00:44:28 -0400540 acpi_status status = AE_OK;
541 struct acpi_gpe_event_info *gpe_event_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
Bob Mooreb229cf92006-04-21 17:15:00 -0400543 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544
545 /* Use semaphore lock if not executing at interrupt level */
546
547 if (flags & ACPI_NOT_ISR) {
Len Brown4be44fc2005-08-05 00:44:28 -0400548 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
549 if (ACPI_FAILURE(status)) {
550 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 }
552 }
553
554 /* Ensure that we have a valid GPE number */
555
Len Brown4be44fc2005-08-05 00:44:28 -0400556 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 if (!gpe_event_info) {
558 status = AE_BAD_PARAMETER;
559 goto unlock_and_exit;
560 }
561
562 /* Obtain status on the requested GPE number */
563
Len Brown4be44fc2005-08-05 00:44:28 -0400564 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Zhang Ruied206fa2008-10-27 14:01:02 -0700566 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
567 *event_status |= ACPI_EVENT_FLAG_HANDLE;
568
Len Brown4be44fc2005-08-05 00:44:28 -0400569 unlock_and_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 if (flags & ACPI_NOT_ISR) {
Len Brown4be44fc2005-08-05 00:44:28 -0400571 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 }
Len Brown4be44fc2005-08-05 00:44:28 -0400573 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574}
Bob Moore83135242006-10-03 00:00:00 -0400575
576ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577/*******************************************************************************
578 *
579 * FUNCTION: acpi_install_gpe_block
580 *
581 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
582 * gpe_block_address - Address and space_iD
583 * register_count - Number of GPE register pairs in the block
Robert Moore6f42ccf2005-05-13 00:00:00 -0400584 * interrupt_number - H/W interrupt for the block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 *
586 * RETURN: Status
587 *
588 * DESCRIPTION: Create and Install a block of GPE registers
589 *
590 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400592acpi_install_gpe_block(acpi_handle gpe_device,
593 struct acpi_generic_address *gpe_block_address,
594 u32 register_count, u32 interrupt_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595{
Len Brown4be44fc2005-08-05 00:44:28 -0400596 acpi_status status;
597 union acpi_operand_object *obj_desc;
598 struct acpi_namespace_node *node;
599 struct acpi_gpe_block_info *gpe_block;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Bob Mooreb229cf92006-04-21 17:15:00 -0400601 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Len Brown4be44fc2005-08-05 00:44:28 -0400603 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
604 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 }
606
Len Brown4be44fc2005-08-05 00:44:28 -0400607 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
608 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 return (status);
610 }
611
Len Brown4be44fc2005-08-05 00:44:28 -0400612 node = acpi_ns_map_handle_to_node(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 if (!node) {
614 status = AE_BAD_PARAMETER;
615 goto unlock_and_exit;
616 }
617
618 /*
619 * For user-installed GPE Block Devices, the gpe_block_base_number
620 * is always zero
621 */
Len Brown4be44fc2005-08-05 00:44:28 -0400622 status =
623 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
624 interrupt_number, &gpe_block);
625 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 goto unlock_and_exit;
627 }
628
Bob Moore96db2552005-11-02 00:00:00 -0500629 /* Run the _PRW methods and enable the GPEs */
630
631 status = acpi_ev_initialize_gpe_block(node, gpe_block);
632 if (ACPI_FAILURE(status)) {
633 goto unlock_and_exit;
634 }
635
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 /* Get the device_object attached to the node */
637
Len Brown4be44fc2005-08-05 00:44:28 -0400638 obj_desc = acpi_ns_get_attached_object(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 if (!obj_desc) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400640
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 /* No object, create a new one */
642
Len Brown4be44fc2005-08-05 00:44:28 -0400643 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 if (!obj_desc) {
645 status = AE_NO_MEMORY;
646 goto unlock_and_exit;
647 }
648
Len Brown4be44fc2005-08-05 00:44:28 -0400649 status =
650 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
652 /* Remove local reference to the object */
653
Len Brown4be44fc2005-08-05 00:44:28 -0400654 acpi_ut_remove_reference(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Len Brown4be44fc2005-08-05 00:44:28 -0400656 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 goto unlock_and_exit;
658 }
659 }
660
661 /* Install the GPE block in the device_object */
662
663 obj_desc->device.gpe_block = gpe_block;
664
Len Brown4be44fc2005-08-05 00:44:28 -0400665 unlock_and_exit:
666 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
667 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
Bob Moore83135242006-10-03 00:00:00 -0400670ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
672/*******************************************************************************
673 *
674 * FUNCTION: acpi_remove_gpe_block
675 *
676 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
677 *
678 * RETURN: Status
679 *
680 * DESCRIPTION: Remove a previously installed block of GPE registers
681 *
682 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400683acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684{
Len Brown4be44fc2005-08-05 00:44:28 -0400685 union acpi_operand_object *obj_desc;
686 acpi_status status;
687 struct acpi_namespace_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
Bob Mooreb229cf92006-04-21 17:15:00 -0400689 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
691 if (!gpe_device) {
Len Brown4be44fc2005-08-05 00:44:28 -0400692 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 }
694
Len Brown4be44fc2005-08-05 00:44:28 -0400695 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
696 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 return (status);
698 }
699
Len Brown4be44fc2005-08-05 00:44:28 -0400700 node = acpi_ns_map_handle_to_node(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 if (!node) {
702 status = AE_BAD_PARAMETER;
703 goto unlock_and_exit;
704 }
705
706 /* Get the device_object attached to the node */
707
Len Brown4be44fc2005-08-05 00:44:28 -0400708 obj_desc = acpi_ns_get_attached_object(node);
709 if (!obj_desc || !obj_desc->device.gpe_block) {
710 return_ACPI_STATUS(AE_NULL_OBJECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 }
712
713 /* Delete the GPE block (but not the device_object) */
714
Len Brown4be44fc2005-08-05 00:44:28 -0400715 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
716 if (ACPI_SUCCESS(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 obj_desc->device.gpe_block = NULL;
718 }
719
Len Brown4be44fc2005-08-05 00:44:28 -0400720 unlock_and_exit:
721 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
722 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723}
Robert Moore44f6c012005-04-18 22:49:35 -0400724
Bob Moore83135242006-10-03 00:00:00 -0400725ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
Bob Mooree97d6bf2008-12-30 09:45:17 +0800726
727/*******************************************************************************
728 *
729 * FUNCTION: acpi_get_gpe_device
730 *
731 * PARAMETERS: Index - System GPE index (0-current_gpe_count)
732 * gpe_device - Where the parent GPE Device is returned
733 *
734 * RETURN: Status
735 *
736 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
737 * gpe device indicates that the gpe number is contained in one of
738 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
739 *
740 ******************************************************************************/
741acpi_status
742acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
743{
744 struct acpi_gpe_device_info info;
745 acpi_status status;
746
747 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
748
749 if (!gpe_device) {
750 return_ACPI_STATUS(AE_BAD_PARAMETER);
751 }
752
753 if (index >= acpi_current_gpe_count) {
754 return_ACPI_STATUS(AE_NOT_EXIST);
755 }
756
757 /* Setup and walk the GPE list */
758
759 info.index = index;
760 info.status = AE_NOT_EXIST;
761 info.gpe_device = NULL;
762 info.next_block_base_index = 0;
763
764 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
765 if (ACPI_FAILURE(status)) {
766 return_ACPI_STATUS(status);
767 }
768
769 *gpe_device = info.gpe_device;
770 return_ACPI_STATUS(info.status);
771}
772
773ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
774
775/*******************************************************************************
776 *
777 * FUNCTION: acpi_ev_get_gpe_device
778 *
779 * PARAMETERS: GPE_WALK_CALLBACK
780 *
781 * RETURN: Status
782 *
783 * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
784 * block device. NULL if the GPE is one of the FADT-defined GPEs.
785 *
786 ******************************************************************************/
787acpi_status
788acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
789 struct acpi_gpe_block_info *gpe_block, void *context)
790{
791 struct acpi_gpe_device_info *info = context;
792
793 /* Increment Index by the number of GPEs in this block */
794
795 info->next_block_base_index +=
796 (gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH);
797
798 if (info->index < info->next_block_base_index) {
799 /*
800 * The GPE index is within this block, get the node. Leave the node
801 * NULL for the FADT-defined GPEs
802 */
803 if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
804 info->gpe_device = gpe_block->node;
805 }
806
807 info->status = AE_OK;
808 return (AE_CTRL_END);
809 }
810
811 return (AE_OK);
812}
Bob Moore08ac07b2008-12-30 09:55:48 +0800813
814/******************************************************************************
815 *
816 * FUNCTION: acpi_disable_all_gpes
817 *
818 * PARAMETERS: None
819 *
820 * RETURN: Status
821 *
822 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
823 *
824 ******************************************************************************/
825
826acpi_status acpi_disable_all_gpes(void)
827{
828 acpi_status status;
829
830 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
831
832 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
833 if (ACPI_FAILURE(status)) {
834 return_ACPI_STATUS(status);
835 }
836
837 status = acpi_hw_disable_all_gpes();
838 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
839
840 return_ACPI_STATUS(status);
841}
842
843/******************************************************************************
844 *
845 * FUNCTION: acpi_enable_all_runtime_gpes
846 *
847 * PARAMETERS: None
848 *
849 * RETURN: Status
850 *
851 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
852 *
853 ******************************************************************************/
854
855acpi_status acpi_enable_all_runtime_gpes(void)
856{
857 acpi_status status;
858
859 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
860
861 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
862 if (ACPI_FAILURE(status)) {
863 return_ACPI_STATUS(status);
864 }
865
866 status = acpi_hw_enable_all_runtime_gpes();
867 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
868
869 return_ACPI_STATUS(status);
870}