]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/acpi/acpica/evxfgpe.c
ACPICA: Move GPE functions to new file evxfgpe.c
[mirror_ubuntu-bionic-kernel.git] / drivers / acpi / acpica / evxfgpe.c
CommitLineData
3cfd53d5
LM
1/******************************************************************************
2 *
3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2010, Intel Corp.
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
44#include <acpi/acpi.h>
45#include "accommon.h"
46#include "acevents.h"
47#include "acnamesp.h"
48
49#define _COMPONENT ACPI_EVENTS
50ACPI_MODULE_NAME("evxfgpe")
51
52/******************************************************************************
53 *
54 * FUNCTION: acpi_update_gpes
55 *
56 * PARAMETERS: None
57 *
58 * RETURN: None
59 *
60 * DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and
61 * are not pointed to by any device _PRW methods indicating that
62 * these GPEs are generally intended for system or device wakeup
63 * (such GPEs have to be enabled directly when the devices whose
64 * _PRW methods point to them are set up for wakeup signaling).
65 *
66 ******************************************************************************/
67
68acpi_status acpi_update_gpes(void)
69{
70 acpi_status status;
71
72 ACPI_FUNCTION_TRACE(acpi_update_gpes);
73
74 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
75 if (ACPI_FAILURE(status)) {
76 return_ACPI_STATUS(status);
77 } else if (acpi_all_gpes_initialized) {
78 goto unlock;
79 }
80
81 status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
82 if (ACPI_SUCCESS(status)) {
83 acpi_all_gpes_initialized = TRUE;
84 }
85
86unlock:
87 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
88
89 return_ACPI_STATUS(status);
90}
91
92/*******************************************************************************
93 *
94 * FUNCTION: acpi_enable_gpe
95 *
96 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
97 * gpe_number - GPE level within the GPE block
98 *
99 * RETURN: Status
100 *
101 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
102 * hardware-enabled.
103 *
104 ******************************************************************************/
105
106acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
107{
108 acpi_status status = AE_BAD_PARAMETER;
109 struct acpi_gpe_event_info *gpe_event_info;
110 acpi_cpu_flags flags;
111
112 ACPI_FUNCTION_TRACE(acpi_enable_gpe);
113
114 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
115
116 /* Ensure that we have a valid GPE number */
117
118 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
119 if (gpe_event_info) {
120 status = acpi_raw_enable_gpe(gpe_event_info);
121 }
122
123 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
124 return_ACPI_STATUS(status);
125}
126ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
127
128/*******************************************************************************
129 *
130 * FUNCTION: acpi_disable_gpe
131 *
132 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
133 * gpe_number - GPE level within the GPE block
134 *
135 * RETURN: Status
136 *
137 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
138 * removed, only then is the GPE disabled (for runtime GPEs), or
139 * the GPE mask bit disabled (for wake GPEs)
140 *
141 ******************************************************************************/
142
143acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
144{
145 acpi_status status = AE_BAD_PARAMETER;
146 struct acpi_gpe_event_info *gpe_event_info;
147 acpi_cpu_flags flags;
148
149 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
150
151 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
152
153 /* Ensure that we have a valid GPE number */
154
155 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
156 if (gpe_event_info) {
157 status = acpi_raw_disable_gpe(gpe_event_info) ;
158 }
159
160 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
161 return_ACPI_STATUS(status);
162}
163ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
164
165/*******************************************************************************
166 *
167 * FUNCTION: acpi_gpe_can_wake
168 *
169 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
170 * gpe_number - GPE level within the GPE block
171 *
172 * RETURN: Status
173 *
174 * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE. If the GPE
175 * has a corresponding method and is currently enabled, disable it
176 * (GPEs with corresponding methods are enabled unconditionally
177 * during initialization, but GPEs that can wake up are expected
178 * to be initially disabled).
179 *
180 ******************************************************************************/
181acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
182{
183 acpi_status status = AE_OK;
184 struct acpi_gpe_event_info *gpe_event_info;
185 acpi_cpu_flags flags;
186
187 ACPI_FUNCTION_TRACE(acpi_gpe_can_wake);
188
189 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
190
191 /* Ensure that we have a valid GPE number */
192
193 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
194 if (gpe_event_info) {
195 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
196 } else {
197 status = AE_BAD_PARAMETER;
198 }
199
200 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
201 return_ACPI_STATUS(status);
202}
203ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake)
204
205/*******************************************************************************
206 *
207 * FUNCTION: acpi_gpe_wakeup
208 *
209 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
210 * gpe_number - GPE level within the GPE block
211 * Action - Enable or Disable
212 *
213 * RETURN: Status
214 *
215 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
216 *
217 ******************************************************************************/
218
219acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action)
220{
221 acpi_status status = AE_OK;
222 struct acpi_gpe_event_info *gpe_event_info;
223 struct acpi_gpe_register_info *gpe_register_info;
224 acpi_cpu_flags flags;
225 u32 register_bit;
226
227 ACPI_FUNCTION_TRACE(acpi_gpe_wakeup);
228
229 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
230
231 /* Ensure that we have a valid GPE number */
232
233 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
234 if (!gpe_event_info || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
235 status = AE_BAD_PARAMETER;
236 goto unlock_and_exit;
237 }
238
239 gpe_register_info = gpe_event_info->register_info;
240 if (!gpe_register_info) {
241 status = AE_NOT_EXIST;
242 goto unlock_and_exit;
243 }
244
245 register_bit =
246 acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
247
248 /* Perform the action */
249
250 switch (action) {
251 case ACPI_GPE_ENABLE:
252 ACPI_SET_BIT(gpe_register_info->enable_for_wake,
253 (u8)register_bit);
254 break;
255
256 case ACPI_GPE_DISABLE:
257 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
258 (u8)register_bit);
259 break;
260
261 default:
262 ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
263 status = AE_BAD_PARAMETER;
264 break;
265 }
266
267unlock_and_exit:
268 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
269 return_ACPI_STATUS(status);
270}
271
272ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup)
273
274/*******************************************************************************
275 *
276 * FUNCTION: acpi_clear_gpe
277 *
278 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
279 * gpe_number - GPE level within the GPE block
280 *
281 * RETURN: Status
282 *
283 * DESCRIPTION: Clear an ACPI event (general purpose)
284 *
285 ******************************************************************************/
286acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
287{
288 acpi_status status = AE_OK;
289 struct acpi_gpe_event_info *gpe_event_info;
290 acpi_cpu_flags flags;
291
292 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
293
294 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
295
296 /* Ensure that we have a valid GPE number */
297
298 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
299 if (!gpe_event_info) {
300 status = AE_BAD_PARAMETER;
301 goto unlock_and_exit;
302 }
303
304 status = acpi_hw_clear_gpe(gpe_event_info);
305
306 unlock_and_exit:
307 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
308 return_ACPI_STATUS(status);
309}
310
311ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
312
313/*******************************************************************************
314 *
315 * FUNCTION: acpi_get_gpe_status
316 *
317 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
318 * gpe_number - GPE level within the GPE block
319 * event_status - Where the current status of the event will
320 * be returned
321 *
322 * RETURN: Status
323 *
324 * DESCRIPTION: Get status of an event (general purpose)
325 *
326 ******************************************************************************/
327acpi_status
328acpi_get_gpe_status(acpi_handle gpe_device,
329 u32 gpe_number, acpi_event_status *event_status)
330{
331 acpi_status status = AE_OK;
332 struct acpi_gpe_event_info *gpe_event_info;
333 acpi_cpu_flags flags;
334
335 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
336
337 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
338
339 /* Ensure that we have a valid GPE number */
340
341 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
342 if (!gpe_event_info) {
343 status = AE_BAD_PARAMETER;
344 goto unlock_and_exit;
345 }
346
347 /* Obtain status on the requested GPE number */
348
349 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
350
351 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
352 *event_status |= ACPI_EVENT_FLAG_HANDLE;
353
354 unlock_and_exit:
355 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
356 return_ACPI_STATUS(status);
357}
358
359ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
360
361/******************************************************************************
362 *
363 * FUNCTION: acpi_disable_all_gpes
364 *
365 * PARAMETERS: None
366 *
367 * RETURN: Status
368 *
369 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
370 *
371 ******************************************************************************/
372
373acpi_status acpi_disable_all_gpes(void)
374{
375 acpi_status status;
376
377 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
378
379 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
380 if (ACPI_FAILURE(status)) {
381 return_ACPI_STATUS(status);
382 }
383
384 status = acpi_hw_disable_all_gpes();
385 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
386
387 return_ACPI_STATUS(status);
388}
389
390/******************************************************************************
391 *
392 * FUNCTION: acpi_enable_all_runtime_gpes
393 *
394 * PARAMETERS: None
395 *
396 * RETURN: Status
397 *
398 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
399 *
400 ******************************************************************************/
401
402acpi_status acpi_enable_all_runtime_gpes(void)
403{
404 acpi_status status;
405
406 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
407
408 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
409 if (ACPI_FAILURE(status)) {
410 return_ACPI_STATUS(status);
411 }
412
413 status = acpi_hw_enable_all_runtime_gpes();
414 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
415
416 return_ACPI_STATUS(status);
417}
418
419/*******************************************************************************
420 *
421 * FUNCTION: acpi_install_gpe_block
422 *
423 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
424 * gpe_block_address - Address and space_iD
425 * register_count - Number of GPE register pairs in the block
426 * interrupt_number - H/W interrupt for the block
427 *
428 * RETURN: Status
429 *
430 * DESCRIPTION: Create and Install a block of GPE registers
431 *
432 ******************************************************************************/
433acpi_status
434acpi_install_gpe_block(acpi_handle gpe_device,
435 struct acpi_generic_address *gpe_block_address,
436 u32 register_count, u32 interrupt_number)
437{
438 acpi_status status = AE_OK;
439 union acpi_operand_object *obj_desc;
440 struct acpi_namespace_node *node;
441 struct acpi_gpe_block_info *gpe_block;
442
443 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
444
445 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
446 return_ACPI_STATUS(AE_BAD_PARAMETER);
447 }
448
449 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
450 if (ACPI_FAILURE(status)) {
451 return (status);
452 }
453
454 node = acpi_ns_validate_handle(gpe_device);
455 if (!node) {
456 status = AE_BAD_PARAMETER;
457 goto unlock_and_exit;
458 }
459
460 /*
461 * For user-installed GPE Block Devices, the gpe_block_base_number
462 * is always zero
463 */
464 status =
465 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
466 interrupt_number, &gpe_block);
467 if (ACPI_FAILURE(status)) {
468 goto unlock_and_exit;
469 }
470
471 /* Install block in the device_object attached to the node */
472
473 obj_desc = acpi_ns_get_attached_object(node);
474 if (!obj_desc) {
475
476 /*
477 * No object, create a new one (Device nodes do not always have
478 * an attached object)
479 */
480 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
481 if (!obj_desc) {
482 status = AE_NO_MEMORY;
483 goto unlock_and_exit;
484 }
485
486 status =
487 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
488
489 /* Remove local reference to the object */
490
491 acpi_ut_remove_reference(obj_desc);
492
493 if (ACPI_FAILURE(status)) {
494 goto unlock_and_exit;
495 }
496 }
497
498 /* Now install the GPE block in the device_object */
499
500 obj_desc->device.gpe_block = gpe_block;
501
502 unlock_and_exit:
503 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
504 return_ACPI_STATUS(status);
505}
506
507ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
508
509/*******************************************************************************
510 *
511 * FUNCTION: acpi_remove_gpe_block
512 *
513 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
514 *
515 * RETURN: Status
516 *
517 * DESCRIPTION: Remove a previously installed block of GPE registers
518 *
519 ******************************************************************************/
520acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
521{
522 union acpi_operand_object *obj_desc;
523 acpi_status status;
524 struct acpi_namespace_node *node;
525
526 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
527
528 if (!gpe_device) {
529 return_ACPI_STATUS(AE_BAD_PARAMETER);
530 }
531
532 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
533 if (ACPI_FAILURE(status)) {
534 return (status);
535 }
536
537 node = acpi_ns_validate_handle(gpe_device);
538 if (!node) {
539 status = AE_BAD_PARAMETER;
540 goto unlock_and_exit;
541 }
542
543 /* Get the device_object attached to the node */
544
545 obj_desc = acpi_ns_get_attached_object(node);
546 if (!obj_desc || !obj_desc->device.gpe_block) {
547 return_ACPI_STATUS(AE_NULL_OBJECT);
548 }
549
550 /* Delete the GPE block (but not the device_object) */
551
552 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
553 if (ACPI_SUCCESS(status)) {
554 obj_desc->device.gpe_block = NULL;
555 }
556
557 unlock_and_exit:
558 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
559 return_ACPI_STATUS(status);
560}
561
562ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
563
564/*******************************************************************************
565 *
566 * FUNCTION: acpi_get_gpe_device
567 *
568 * PARAMETERS: Index - System GPE index (0-current_gpe_count)
569 * gpe_device - Where the parent GPE Device is returned
570 *
571 * RETURN: Status
572 *
573 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
574 * gpe device indicates that the gpe number is contained in one of
575 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
576 *
577 ******************************************************************************/
578acpi_status
579acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
580{
581 struct acpi_gpe_device_info info;
582 acpi_status status;
583
584 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
585
586 if (!gpe_device) {
587 return_ACPI_STATUS(AE_BAD_PARAMETER);
588 }
589
590 if (index >= acpi_current_gpe_count) {
591 return_ACPI_STATUS(AE_NOT_EXIST);
592 }
593
594 /* Setup and walk the GPE list */
595
596 info.index = index;
597 info.status = AE_NOT_EXIST;
598 info.gpe_device = NULL;
599 info.next_block_base_index = 0;
600
601 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
602 if (ACPI_FAILURE(status)) {
603 return_ACPI_STATUS(status);
604 }
605
606 *gpe_device = info.gpe_device;
607 return_ACPI_STATUS(info.status);
608}
609
610ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)