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