blob: d5a5efc043bf7a43ac446c815370576deaa5b096 [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. Wysocki9630bdd2010-02-17 23:41:07 +0100213 * FUNCTION: acpi_set_gpe
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 *
Lin Ming0f849d22010-04-06 14:52:37 +0800215 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 * gpe_number - GPE level within the GPE block
Lin Ming0f849d22010-04-06 14:52:37 +0800217 * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 *
219 * RETURN: Status
220 *
Lin Ming0f849d22010-04-06 14:52:37 +0800221 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
222 * the reference count mechanism used in the acpi_enable_gpe and
223 * acpi_disable_gpe interfaces -- and should be used with care.
224 *
225 * Note: Typically used to disable a runtime GPE for short period of time,
226 * then re-enable it, without disturbing the existing reference counts. This
227 * is useful, for example, in the Embedded Controller (EC) driver.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 *
229 ******************************************************************************/
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100230acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231{
Len Brown4be44fc2005-08-05 00:44:28 -0400232 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800233 acpi_status status;
234 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100236 ACPI_FUNCTION_TRACE(acpi_set_gpe);
237
238 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
240 /* Ensure that we have a valid GPE number */
241
Len Brown4be44fc2005-08-05 00:44:28 -0400242 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 if (!gpe_event_info) {
244 status = AE_BAD_PARAMETER;
245 goto unlock_and_exit;
246 }
247
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100248 /* Perform the action */
249
250 switch (action) {
251 case ACPI_GPE_ENABLE:
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100252 status = acpi_ev_enable_gpe(gpe_event_info);
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100253 break;
254
255 case ACPI_GPE_DISABLE:
256 status = acpi_ev_disable_gpe(gpe_event_info);
257 break;
258
259 default:
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100260 status = AE_BAD_PARAMETER;
261 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 }
263
Len Brown4be44fc2005-08-05 00:44:28 -0400264 unlock_and_exit:
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100265 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400266 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100269ACPI_EXPORT_SYMBOL(acpi_set_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
271/*******************************************************************************
272 *
273 * FUNCTION: acpi_enable_gpe
274 *
Lin Ming0f849d22010-04-06 14:52:37 +0800275 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 * gpe_number - GPE level within the GPE block
Lin Ming0f849d22010-04-06 14:52:37 +0800277 * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
278 * or both
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 *
280 * RETURN: Status
281 *
Lin Ming0f849d22010-04-06 14:52:37 +0800282 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
283 * hardware-enabled (for runtime GPEs), or the GPE register mask
284 * is updated (for wake GPEs).
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 *
286 ******************************************************************************/
Lin Ming0f849d22010-04-06 14:52:37 +0800287acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288{
Len Brown4be44fc2005-08-05 00:44:28 -0400289 acpi_status status = AE_OK;
290 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800291 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
Bob Mooreb229cf92006-04-21 17:15:00 -0400293 ACPI_FUNCTION_TRACE(acpi_enable_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
Lin Ming0f849d22010-04-06 14:52:37 +0800295 /* Parameter validation */
296
297 if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100298 return_ACPI_STATUS(AE_BAD_PARAMETER);
Lin Ming0f849d22010-04-06 14:52:37 +0800299 }
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100300
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400301 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
303 /* Ensure that we have a valid GPE number */
304
Len Brown4be44fc2005-08-05 00:44:28 -0400305 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 if (!gpe_event_info) {
307 status = AE_BAD_PARAMETER;
308 goto unlock_and_exit;
309 }
310
Lin Ming0f849d22010-04-06 14:52:37 +0800311 if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
312 if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
313 status = AE_LIMIT; /* Too many references */
314 goto unlock_and_exit;
315 }
316
317 gpe_event_info->runtime_count++;
318 if (gpe_event_info->runtime_count == 1) {
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100319 status = acpi_ev_enable_gpe(gpe_event_info);
Lin Ming0f849d22010-04-06 14:52:37 +0800320 if (ACPI_FAILURE(status)) {
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100321 gpe_event_info->runtime_count--;
Lin Ming0f849d22010-04-06 14:52:37 +0800322 goto unlock_and_exit;
323 }
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100324 }
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100325 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
Lin Ming0f849d22010-04-06 14:52:37 +0800327 if (gpe_type & ACPI_GPE_TYPE_WAKE) {
328 /* The GPE must have the ability to wake the system */
329
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100330 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
Lin Ming0f849d22010-04-06 14:52:37 +0800331 status = AE_TYPE;
332 goto unlock_and_exit;
333 }
334
335 if (gpe_event_info->wakeup_count == ACPI_UINT8_MAX) {
336 status = AE_LIMIT; /* Too many references */
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100337 goto unlock_and_exit;
338 }
339
340 /*
Lin Ming0f849d22010-04-06 14:52:37 +0800341 * Update the enable mask on the first wakeup reference. Wake GPEs
342 * are only hardware-enabled just before sleeping.
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100343 */
Lin Ming0f849d22010-04-06 14:52:37 +0800344 gpe_event_info->wakeup_count++;
345 if (gpe_event_info->wakeup_count == 1) {
346 (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
347 }
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100348 }
349
350unlock_and_exit:
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400351 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400352 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353}
Bob Moore83135242006-10-03 00:00:00 -0400354ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
356/*******************************************************************************
357 *
358 * FUNCTION: acpi_disable_gpe
359 *
Lin Ming0f849d22010-04-06 14:52:37 +0800360 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 * gpe_number - GPE level within the GPE block
Lin Ming0f849d22010-04-06 14:52:37 +0800362 * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
363 * or both
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 *
365 * RETURN: Status
366 *
Lin Ming0f849d22010-04-06 14:52:37 +0800367 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
368 * removed, only then is the GPE disabled (for runtime GPEs), or
369 * the GPE mask bit disabled (for wake GPEs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 *
371 ******************************************************************************/
Lin Ming0f849d22010-04-06 14:52:37 +0800372acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
Len Brown4be44fc2005-08-05 00:44:28 -0400374 acpi_status status = AE_OK;
375 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800376 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
Bob Mooreb229cf92006-04-21 17:15:00 -0400378 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
Lin Ming0f849d22010-04-06 14:52:37 +0800380 /* Parameter validation */
381
382 if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100383 return_ACPI_STATUS(AE_BAD_PARAMETER);
Lin Ming0f849d22010-04-06 14:52:37 +0800384 }
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100385
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400386 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Lin Ming0f849d22010-04-06 14:52:37 +0800387
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 /* Ensure that we have a valid GPE number */
389
Len Brown4be44fc2005-08-05 00:44:28 -0400390 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 if (!gpe_event_info) {
392 status = AE_BAD_PARAMETER;
393 goto unlock_and_exit;
394 }
395
Lin Ming0f849d22010-04-06 14:52:37 +0800396 /* Hardware-disable a runtime GPE on removal of the last reference */
397
398 if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
399 if (!gpe_event_info->runtime_count) {
400 status = AE_LIMIT; /* There are no references to remove */
401 goto unlock_and_exit;
402 }
403
404 gpe_event_info->runtime_count--;
405 if (!gpe_event_info->runtime_count) {
Rafael J. Wysockicbbc0de2010-02-24 00:52:08 +0100406 status = acpi_ev_disable_gpe(gpe_event_info);
Lin Ming0f849d22010-04-06 14:52:37 +0800407 if (ACPI_FAILURE(status)) {
408 gpe_event_info->runtime_count++;
409 goto unlock_and_exit;
410 }
411 }
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100412 }
413
Lin Ming0f849d22010-04-06 14:52:37 +0800414 /*
415 * Update masks for wake GPE on removal of the last reference.
416 * No need to hardware-disable wake GPEs here, they are not currently
417 * enabled.
418 */
419 if (gpe_type & ACPI_GPE_TYPE_WAKE) {
420 if (!gpe_event_info->wakeup_count) {
421 status = AE_LIMIT; /* There are no references to remove */
422 goto unlock_and_exit;
423 }
424
425 gpe_event_info->wakeup_count--;
426 if (!gpe_event_info->wakeup_count) {
427 (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
428 }
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Alexey Starikovskiy0b7084a2008-10-25 21:48:46 +0400431unlock_and_exit:
432 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400433 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434}
Bob Moore83135242006-10-03 00:00:00 -0400435ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437/*******************************************************************************
438 *
439 * FUNCTION: acpi_disable_event
440 *
441 * PARAMETERS: Event - The fixed eventto be enabled
442 * Flags - Reserved
443 *
444 * RETURN: Status
445 *
446 * DESCRIPTION: Disable an ACPI event (fixed)
447 *
448 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400449acpi_status acpi_disable_event(u32 event, u32 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450{
Len Brown4be44fc2005-08-05 00:44:28 -0400451 acpi_status status = AE_OK;
452 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453
Bob Mooreb229cf92006-04-21 17:15:00 -0400454 ACPI_FUNCTION_TRACE(acpi_disable_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
456 /* Decode the Fixed Event */
457
458 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400459 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 }
461
462 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800463 * Disable the requested fixed event (by writing a zero to the enable
464 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 */
Len Brown4be44fc2005-08-05 00:44:28 -0400466 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800467 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
Bob Moore768aaaf2009-03-06 09:49:25 +0800468 enable_register_id, ACPI_DISABLE_EVENT);
Len Brown4be44fc2005-08-05 00:44:28 -0400469 if (ACPI_FAILURE(status)) {
470 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 }
472
Len Brown4be44fc2005-08-05 00:44:28 -0400473 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800474 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
475 enable_register_id, &value);
Len Brown4be44fc2005-08-05 00:44:28 -0400476 if (ACPI_FAILURE(status)) {
477 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 }
479
480 if (value != 0) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500481 ACPI_ERROR((AE_INFO,
482 "Could not disable %s events",
483 acpi_ut_get_event_name(event)));
Len Brown4be44fc2005-08-05 00:44:28 -0400484 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 }
486
Len Brown4be44fc2005-08-05 00:44:28 -0400487 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
Bob Moore83135242006-10-03 00:00:00 -0400490ACPI_EXPORT_SYMBOL(acpi_disable_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
492/*******************************************************************************
493 *
494 * FUNCTION: acpi_clear_event
495 *
496 * PARAMETERS: Event - The fixed event to be cleared
497 *
498 * RETURN: Status
499 *
500 * DESCRIPTION: Clear an ACPI event (fixed)
501 *
502 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400503acpi_status acpi_clear_event(u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
Len Brown4be44fc2005-08-05 00:44:28 -0400505 acpi_status status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Bob Mooreb229cf92006-04-21 17:15:00 -0400507 ACPI_FUNCTION_TRACE(acpi_clear_event);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
509 /* Decode the Fixed Event */
510
511 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400512 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 }
514
515 /*
Bob Moore9f15fc62008-11-12 16:01:56 +0800516 * Clear the requested fixed event (By writing a one to the status
517 * register bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 */
Len Brown4be44fc2005-08-05 00:44:28 -0400519 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800520 acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
Bob Moore768aaaf2009-03-06 09:49:25 +0800521 status_register_id, ACPI_CLEAR_STATUS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
Len Brown4be44fc2005-08-05 00:44:28 -0400523 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Bob Moore83135242006-10-03 00:00:00 -0400526ACPI_EXPORT_SYMBOL(acpi_clear_event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
528/*******************************************************************************
529 *
530 * FUNCTION: acpi_clear_gpe
531 *
Lin Ming0f849d22010-04-06 14:52:37 +0800532 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 * gpe_number - GPE level within the GPE block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 *
535 * RETURN: Status
536 *
537 * DESCRIPTION: Clear an ACPI event (general purpose)
538 *
539 ******************************************************************************/
Lin Ming0f849d22010-04-06 14:52:37 +0800540acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541{
Len Brown4be44fc2005-08-05 00:44:28 -0400542 acpi_status status = AE_OK;
543 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800544 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
Bob Mooreb229cf92006-04-21 17:15:00 -0400546 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Lin Ming0f849d22010-04-06 14:52:37 +0800548 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
550 /* Ensure that we have a valid GPE number */
551
Len Brown4be44fc2005-08-05 00:44:28 -0400552 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 if (!gpe_event_info) {
554 status = AE_BAD_PARAMETER;
555 goto unlock_and_exit;
556 }
557
Len Brown4be44fc2005-08-05 00:44:28 -0400558 status = acpi_hw_clear_gpe(gpe_event_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
Len Brown4be44fc2005-08-05 00:44:28 -0400560 unlock_and_exit:
Lin Ming0f849d22010-04-06 14:52:37 +0800561 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400562 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563}
564
Bob Moore83135242006-10-03 00:00:00 -0400565ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566/*******************************************************************************
567 *
568 * FUNCTION: acpi_get_event_status
569 *
570 * PARAMETERS: Event - The fixed event
Robert Moore44f6c012005-04-18 22:49:35 -0400571 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 * be returned
573 *
574 * RETURN: Status
575 *
576 * DESCRIPTION: Obtains and returns the current status of the event
577 *
578 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400579acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
Len Brown4be44fc2005-08-05 00:44:28 -0400581 acpi_status status = AE_OK;
Zhang Rui71b58cb2008-06-20 09:42:47 +0800582 u32 value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583
Bob Mooreb229cf92006-04-21 17:15:00 -0400584 ACPI_FUNCTION_TRACE(acpi_get_event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
586 if (!event_status) {
Len Brown4be44fc2005-08-05 00:44:28 -0400587 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 }
589
590 /* Decode the Fixed Event */
591
592 if (event > ACPI_EVENT_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400593 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 }
595
596 /* Get the status of the requested fixed event */
597
Len Brown4be44fc2005-08-05 00:44:28 -0400598 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800599 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
Zhang Rui71b58cb2008-06-20 09:42:47 +0800600 enable_register_id, &value);
601 if (ACPI_FAILURE(status))
602 return_ACPI_STATUS(status);
603
604 *event_status = value;
605
606 status =
Bob Moore50ffba12009-02-23 15:02:07 +0800607 acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
Zhang Rui71b58cb2008-06-20 09:42:47 +0800608 status_register_id, &value);
609 if (ACPI_FAILURE(status))
610 return_ACPI_STATUS(status);
611
612 if (value)
613 *event_status |= ACPI_EVENT_FLAG_SET;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Zhang Ruied206fa2008-10-27 14:01:02 -0700615 if (acpi_gbl_fixed_event_handlers[event].handler)
616 *event_status |= ACPI_EVENT_FLAG_HANDLE;
617
Len Brown4be44fc2005-08-05 00:44:28 -0400618 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619}
620
Bob Moore83135242006-10-03 00:00:00 -0400621ACPI_EXPORT_SYMBOL(acpi_get_event_status)
622
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623/*******************************************************************************
624 *
625 * FUNCTION: acpi_get_gpe_status
626 *
Lin Ming0f849d22010-04-06 14:52:37 +0800627 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 * gpe_number - GPE level within the GPE block
Robert Moore44f6c012005-04-18 22:49:35 -0400629 * event_status - Where the current status of the event will
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 * be returned
631 *
632 * RETURN: Status
633 *
634 * DESCRIPTION: Get status of an event (general purpose)
635 *
636 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400638acpi_get_gpe_status(acpi_handle gpe_device,
Lin Ming0f849d22010-04-06 14:52:37 +0800639 u32 gpe_number, acpi_event_status *event_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640{
Len Brown4be44fc2005-08-05 00:44:28 -0400641 acpi_status status = AE_OK;
642 struct acpi_gpe_event_info *gpe_event_info;
Lin Ming0f849d22010-04-06 14:52:37 +0800643 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Bob Mooreb229cf92006-04-21 17:15:00 -0400645 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Lin Ming0f849d22010-04-06 14:52:37 +0800647 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
649 /* Ensure that we have a valid GPE number */
650
Len Brown4be44fc2005-08-05 00:44:28 -0400651 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 if (!gpe_event_info) {
653 status = AE_BAD_PARAMETER;
654 goto unlock_and_exit;
655 }
656
657 /* Obtain status on the requested GPE number */
658
Len Brown4be44fc2005-08-05 00:44:28 -0400659 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
Zhang Ruied206fa2008-10-27 14:01:02 -0700661 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
662 *event_status |= ACPI_EVENT_FLAG_HANDLE;
663
Len Brown4be44fc2005-08-05 00:44:28 -0400664 unlock_and_exit:
Lin Ming0f849d22010-04-06 14:52:37 +0800665 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Len Brown4be44fc2005-08-05 00:44:28 -0400666 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667}
Bob Moore83135242006-10-03 00:00:00 -0400668
669ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670/*******************************************************************************
671 *
672 * FUNCTION: acpi_install_gpe_block
673 *
674 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
675 * gpe_block_address - Address and space_iD
676 * register_count - Number of GPE register pairs in the block
Robert Moore6f42ccf2005-05-13 00:00:00 -0400677 * interrupt_number - H/W interrupt for the block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 *
679 * RETURN: Status
680 *
681 * DESCRIPTION: Create and Install a block of GPE registers
682 *
683 ******************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400685acpi_install_gpe_block(acpi_handle gpe_device,
686 struct acpi_generic_address *gpe_block_address,
687 u32 register_count, u32 interrupt_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
Len Brown4be44fc2005-08-05 00:44:28 -0400689 acpi_status status;
690 union acpi_operand_object *obj_desc;
691 struct acpi_namespace_node *node;
692 struct acpi_gpe_block_info *gpe_block;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Bob Mooreb229cf92006-04-21 17:15:00 -0400694 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
Len Brown4be44fc2005-08-05 00:44:28 -0400696 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
697 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 }
699
Len Brown4be44fc2005-08-05 00:44:28 -0400700 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
701 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 return (status);
703 }
704
Bob Mooref24b6642009-12-11 14:57:00 +0800705 node = acpi_ns_validate_handle(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 if (!node) {
707 status = AE_BAD_PARAMETER;
708 goto unlock_and_exit;
709 }
710
711 /*
712 * For user-installed GPE Block Devices, the gpe_block_base_number
713 * is always zero
714 */
Len Brown4be44fc2005-08-05 00:44:28 -0400715 status =
716 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
717 interrupt_number, &gpe_block);
718 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 goto unlock_and_exit;
720 }
721
Lin Ming0f849d22010-04-06 14:52:37 +0800722 /* Install block in the device_object attached to the node */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723
Len Brown4be44fc2005-08-05 00:44:28 -0400724 obj_desc = acpi_ns_get_attached_object(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 if (!obj_desc) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400726
Lin Ming0f849d22010-04-06 14:52:37 +0800727 /*
728 * No object, create a new one (Device nodes do not always have
729 * an attached object)
730 */
Len Brown4be44fc2005-08-05 00:44:28 -0400731 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 if (!obj_desc) {
733 status = AE_NO_MEMORY;
734 goto unlock_and_exit;
735 }
736
Len Brown4be44fc2005-08-05 00:44:28 -0400737 status =
738 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
740 /* Remove local reference to the object */
741
Len Brown4be44fc2005-08-05 00:44:28 -0400742 acpi_ut_remove_reference(obj_desc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Len Brown4be44fc2005-08-05 00:44:28 -0400744 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 goto unlock_and_exit;
746 }
747 }
748
Lin Ming0f849d22010-04-06 14:52:37 +0800749 /* Now install the GPE block in the device_object */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
751 obj_desc->device.gpe_block = gpe_block;
752
Lin Ming0f849d22010-04-06 14:52:37 +0800753 /* Run the _PRW methods and enable the runtime GPEs in the new block */
754
755 status = acpi_ev_initialize_gpe_block(node, gpe_block);
756
Len Brown4be44fc2005-08-05 00:44:28 -0400757 unlock_and_exit:
758 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
759 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
Bob Moore83135242006-10-03 00:00:00 -0400762ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
764/*******************************************************************************
765 *
766 * FUNCTION: acpi_remove_gpe_block
767 *
768 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
769 *
770 * RETURN: Status
771 *
772 * DESCRIPTION: Remove a previously installed block of GPE registers
773 *
774 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -0400775acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776{
Len Brown4be44fc2005-08-05 00:44:28 -0400777 union acpi_operand_object *obj_desc;
778 acpi_status status;
779 struct acpi_namespace_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
Bob Mooreb229cf92006-04-21 17:15:00 -0400781 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782
783 if (!gpe_device) {
Len Brown4be44fc2005-08-05 00:44:28 -0400784 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 }
786
Len Brown4be44fc2005-08-05 00:44:28 -0400787 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
788 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 return (status);
790 }
791
Bob Mooref24b6642009-12-11 14:57:00 +0800792 node = acpi_ns_validate_handle(gpe_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 if (!node) {
794 status = AE_BAD_PARAMETER;
795 goto unlock_and_exit;
796 }
797
798 /* Get the device_object attached to the node */
799
Len Brown4be44fc2005-08-05 00:44:28 -0400800 obj_desc = acpi_ns_get_attached_object(node);
801 if (!obj_desc || !obj_desc->device.gpe_block) {
802 return_ACPI_STATUS(AE_NULL_OBJECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 }
804
805 /* Delete the GPE block (but not the device_object) */
806
Len Brown4be44fc2005-08-05 00:44:28 -0400807 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
808 if (ACPI_SUCCESS(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 obj_desc->device.gpe_block = NULL;
810 }
811
Len Brown4be44fc2005-08-05 00:44:28 -0400812 unlock_and_exit:
813 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
814 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815}
Robert Moore44f6c012005-04-18 22:49:35 -0400816
Bob Moore83135242006-10-03 00:00:00 -0400817ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
Bob Mooree97d6bf2008-12-30 09:45:17 +0800818
819/*******************************************************************************
820 *
821 * FUNCTION: acpi_get_gpe_device
822 *
823 * PARAMETERS: Index - System GPE index (0-current_gpe_count)
824 * gpe_device - Where the parent GPE Device is returned
825 *
826 * RETURN: Status
827 *
828 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
829 * gpe device indicates that the gpe number is contained in one of
830 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
831 *
832 ******************************************************************************/
833acpi_status
834acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
835{
836 struct acpi_gpe_device_info info;
837 acpi_status status;
838
839 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
840
841 if (!gpe_device) {
842 return_ACPI_STATUS(AE_BAD_PARAMETER);
843 }
844
845 if (index >= acpi_current_gpe_count) {
846 return_ACPI_STATUS(AE_NOT_EXIST);
847 }
848
849 /* Setup and walk the GPE list */
850
851 info.index = index;
852 info.status = AE_NOT_EXIST;
853 info.gpe_device = NULL;
854 info.next_block_base_index = 0;
855
856 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
857 if (ACPI_FAILURE(status)) {
858 return_ACPI_STATUS(status);
859 }
860
861 *gpe_device = info.gpe_device;
862 return_ACPI_STATUS(info.status);
863}
864
865ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
866
867/*******************************************************************************
868 *
869 * FUNCTION: acpi_ev_get_gpe_device
870 *
871 * PARAMETERS: GPE_WALK_CALLBACK
872 *
873 * RETURN: Status
874 *
875 * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
876 * block device. NULL if the GPE is one of the FADT-defined GPEs.
877 *
878 ******************************************************************************/
Bob Mooree4c1ebf2009-04-22 13:02:06 +0800879static acpi_status
Bob Mooree97d6bf2008-12-30 09:45:17 +0800880acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
881 struct acpi_gpe_block_info *gpe_block, void *context)
882{
883 struct acpi_gpe_device_info *info = context;
884
885 /* Increment Index by the number of GPEs in this block */
886
Lin Ming0f849d22010-04-06 14:52:37 +0800887 info->next_block_base_index += gpe_block->gpe_count;
Bob Mooree97d6bf2008-12-30 09:45:17 +0800888
889 if (info->index < info->next_block_base_index) {
890 /*
891 * The GPE index is within this block, get the node. Leave the node
892 * NULL for the FADT-defined GPEs
893 */
894 if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
895 info->gpe_device = gpe_block->node;
896 }
897
898 info->status = AE_OK;
899 return (AE_CTRL_END);
900 }
901
902 return (AE_OK);
903}
Bob Moore08ac07b2008-12-30 09:55:48 +0800904
905/******************************************************************************
906 *
907 * FUNCTION: acpi_disable_all_gpes
908 *
909 * PARAMETERS: None
910 *
911 * RETURN: Status
912 *
913 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
914 *
915 ******************************************************************************/
916
917acpi_status acpi_disable_all_gpes(void)
918{
919 acpi_status status;
920
921 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
922
923 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
924 if (ACPI_FAILURE(status)) {
925 return_ACPI_STATUS(status);
926 }
927
928 status = acpi_hw_disable_all_gpes();
929 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
930
931 return_ACPI_STATUS(status);
932}
933
934/******************************************************************************
935 *
936 * FUNCTION: acpi_enable_all_runtime_gpes
937 *
938 * PARAMETERS: None
939 *
940 * RETURN: Status
941 *
942 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
943 *
944 ******************************************************************************/
945
946acpi_status acpi_enable_all_runtime_gpes(void)
947{
948 acpi_status status;
949
950 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
951
952 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
953 if (ACPI_FAILURE(status)) {
954 return_ACPI_STATUS(status);
955 }
956
957 status = acpi_hw_enable_all_runtime_gpes();
958 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
959
960 return_ACPI_STATUS(status);
961}