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 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 216 217 /* Ensure that we have a valid GPE number */ 218 219 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 220 if (!gpe_event_info) { 221 goto unlock_and_exit; 222 } 223 224 /* 225 * If there is no method or handler for this GPE, then the 226 * wake_device will be notified whenever this GPE fires (aka 227 * "implicit notify") Note: The GPE is assumed to be 228 * level-triggered (for windows compatibility). 229 */ 230 if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == 231 ACPI_GPE_DISPATCH_NONE) && (wake_device != ACPI_ROOT_OBJECT)) { 232 233 /* Validate wake_device is of type Device */ 234 235 device_node = ACPI_CAST_PTR(struct acpi_namespace_node, 236 wake_device); 237 if (device_node->type != ACPI_TYPE_DEVICE) { 238 goto unlock_and_exit; 239 } 240 gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | 241 ACPI_GPE_LEVEL_TRIGGERED); 242 gpe_event_info->dispatch.device_node = device_node; 243 } 244 245 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; 246 status = AE_OK; 247 248 unlock_and_exit: 249 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 250 return_ACPI_STATUS(status); 251 } 252 ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake) 253 254 /******************************************************************************* 255 * 256 * FUNCTION: acpi_set_gpe_wake_mask 257 * 258 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 259 * gpe_number - GPE level within the GPE block 260 * Action - Enable or Disable 261 * 262 * RETURN: Status 263 * 264 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 265 * already be marked as a WAKE GPE. 266 * 267 ******************************************************************************/ 268 269 acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action) 270 { 271 acpi_status status = AE_OK; 272 struct acpi_gpe_event_info *gpe_event_info; 273 struct acpi_gpe_register_info *gpe_register_info; 274 acpi_cpu_flags flags; 275 u32 register_bit; 276 277 ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask); 278 279 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 280 281 /* 282 * Ensure that we have a valid GPE number and that this GPE is in 283 * fact a wake GPE 284 */ 285 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 286 if (!gpe_event_info) { 287 status = AE_BAD_PARAMETER; 288 goto unlock_and_exit; 289 } 290 291 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { 292 status = AE_TYPE; 293 goto unlock_and_exit; 294 } 295 296 gpe_register_info = gpe_event_info->register_info; 297 if (!gpe_register_info) { 298 status = AE_NOT_EXIST; 299 goto unlock_and_exit; 300 } 301 302 register_bit = 303 acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); 304 305 /* Perform the action */ 306 307 switch (action) { 308 case ACPI_GPE_ENABLE: 309 ACPI_SET_BIT(gpe_register_info->enable_for_wake, 310 (u8)register_bit); 311 break; 312 313 case ACPI_GPE_DISABLE: 314 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, 315 (u8)register_bit); 316 break; 317 318 default: 319 ACPI_ERROR((AE_INFO, "%u, Invalid action", action)); 320 status = AE_BAD_PARAMETER; 321 break; 322 } 323 324 unlock_and_exit: 325 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 326 return_ACPI_STATUS(status); 327 } 328 329 ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask) 330 331 /******************************************************************************* 332 * 333 * FUNCTION: acpi_clear_gpe 334 * 335 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 336 * gpe_number - GPE level within the GPE block 337 * 338 * RETURN: Status 339 * 340 * DESCRIPTION: Clear an ACPI event (general purpose) 341 * 342 ******************************************************************************/ 343 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number) 344 { 345 acpi_status status = AE_OK; 346 struct acpi_gpe_event_info *gpe_event_info; 347 acpi_cpu_flags flags; 348 349 ACPI_FUNCTION_TRACE(acpi_clear_gpe); 350 351 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 352 353 /* Ensure that we have a valid GPE number */ 354 355 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 356 if (!gpe_event_info) { 357 status = AE_BAD_PARAMETER; 358 goto unlock_and_exit; 359 } 360 361 status = acpi_hw_clear_gpe(gpe_event_info); 362 363 unlock_and_exit: 364 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 365 return_ACPI_STATUS(status); 366 } 367 368 ACPI_EXPORT_SYMBOL(acpi_clear_gpe) 369 370 /******************************************************************************* 371 * 372 * FUNCTION: acpi_get_gpe_status 373 * 374 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 375 * gpe_number - GPE level within the GPE block 376 * event_status - Where the current status of the event will 377 * be returned 378 * 379 * RETURN: Status 380 * 381 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 382 * 383 ******************************************************************************/ 384 acpi_status 385 acpi_get_gpe_status(acpi_handle gpe_device, 386 u32 gpe_number, acpi_event_status *event_status) 387 { 388 acpi_status status = AE_OK; 389 struct acpi_gpe_event_info *gpe_event_info; 390 acpi_cpu_flags flags; 391 392 ACPI_FUNCTION_TRACE(acpi_get_gpe_status); 393 394 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 395 396 /* Ensure that we have a valid GPE number */ 397 398 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 399 if (!gpe_event_info) { 400 status = AE_BAD_PARAMETER; 401 goto unlock_and_exit; 402 } 403 404 /* Obtain status on the requested GPE number */ 405 406 status = acpi_hw_get_gpe_status(gpe_event_info, event_status); 407 408 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) 409 *event_status |= ACPI_EVENT_FLAG_HANDLE; 410 411 unlock_and_exit: 412 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 413 return_ACPI_STATUS(status); 414 } 415 416 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) 417 418 /****************************************************************************** 419 * 420 * FUNCTION: acpi_disable_all_gpes 421 * 422 * PARAMETERS: None 423 * 424 * RETURN: Status 425 * 426 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 427 * 428 ******************************************************************************/ 429 430 acpi_status acpi_disable_all_gpes(void) 431 { 432 acpi_status status; 433 434 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes); 435 436 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 437 if (ACPI_FAILURE(status)) { 438 return_ACPI_STATUS(status); 439 } 440 441 status = acpi_hw_disable_all_gpes(); 442 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 443 444 return_ACPI_STATUS(status); 445 } 446 447 ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes) 448 449 /****************************************************************************** 450 * 451 * FUNCTION: acpi_enable_all_runtime_gpes 452 * 453 * PARAMETERS: None 454 * 455 * RETURN: Status 456 * 457 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 458 * 459 ******************************************************************************/ 460 461 acpi_status acpi_enable_all_runtime_gpes(void) 462 { 463 acpi_status status; 464 465 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes); 466 467 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 468 if (ACPI_FAILURE(status)) { 469 return_ACPI_STATUS(status); 470 } 471 472 status = acpi_hw_enable_all_runtime_gpes(); 473 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 474 475 return_ACPI_STATUS(status); 476 } 477 478 ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes) 479 480 /******************************************************************************* 481 * 482 * FUNCTION: acpi_install_gpe_block 483 * 484 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device 485 * gpe_block_address - Address and space_iD 486 * register_count - Number of GPE register pairs in the block 487 * interrupt_number - H/W interrupt for the block 488 * 489 * RETURN: Status 490 * 491 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 492 * enabled here. 493 * 494 ******************************************************************************/ 495 acpi_status 496 acpi_install_gpe_block(acpi_handle gpe_device, 497 struct acpi_generic_address *gpe_block_address, 498 u32 register_count, u32 interrupt_number) 499 { 500 acpi_status status; 501 union acpi_operand_object *obj_desc; 502 struct acpi_namespace_node *node; 503 struct acpi_gpe_block_info *gpe_block; 504 505 ACPI_FUNCTION_TRACE(acpi_install_gpe_block); 506 507 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { 508 return_ACPI_STATUS(AE_BAD_PARAMETER); 509 } 510 511 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 512 if (ACPI_FAILURE(status)) { 513 return (status); 514 } 515 516 node = acpi_ns_validate_handle(gpe_device); 517 if (!node) { 518 status = AE_BAD_PARAMETER; 519 goto unlock_and_exit; 520 } 521 522 /* 523 * For user-installed GPE Block Devices, the gpe_block_base_number 524 * is always zero 525 */ 526 status = 527 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, 528 interrupt_number, &gpe_block); 529 if (ACPI_FAILURE(status)) { 530 goto unlock_and_exit; 531 } 532 533 /* Install block in the device_object attached to the node */ 534 535 obj_desc = acpi_ns_get_attached_object(node); 536 if (!obj_desc) { 537 538 /* 539 * No object, create a new one (Device nodes do not always have 540 * an attached object) 541 */ 542 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); 543 if (!obj_desc) { 544 status = AE_NO_MEMORY; 545 goto unlock_and_exit; 546 } 547 548 status = 549 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE); 550 551 /* Remove local reference to the object */ 552 553 acpi_ut_remove_reference(obj_desc); 554 555 if (ACPI_FAILURE(status)) { 556 goto unlock_and_exit; 557 } 558 } 559 560 /* Now install the GPE block in the device_object */ 561 562 obj_desc->device.gpe_block = gpe_block; 563 564 unlock_and_exit: 565 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 566 return_ACPI_STATUS(status); 567 } 568 569 ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) 570 571 /******************************************************************************* 572 * 573 * FUNCTION: acpi_remove_gpe_block 574 * 575 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device 576 * 577 * RETURN: Status 578 * 579 * DESCRIPTION: Remove a previously installed block of GPE registers 580 * 581 ******************************************************************************/ 582 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) 583 { 584 union acpi_operand_object *obj_desc; 585 acpi_status status; 586 struct acpi_namespace_node *node; 587 588 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); 589 590 if (!gpe_device) { 591 return_ACPI_STATUS(AE_BAD_PARAMETER); 592 } 593 594 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 595 if (ACPI_FAILURE(status)) { 596 return (status); 597 } 598 599 node = acpi_ns_validate_handle(gpe_device); 600 if (!node) { 601 status = AE_BAD_PARAMETER; 602 goto unlock_and_exit; 603 } 604 605 /* Get the device_object attached to the node */ 606 607 obj_desc = acpi_ns_get_attached_object(node); 608 if (!obj_desc || !obj_desc->device.gpe_block) { 609 return_ACPI_STATUS(AE_NULL_OBJECT); 610 } 611 612 /* Delete the GPE block (but not the device_object) */ 613 614 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); 615 if (ACPI_SUCCESS(status)) { 616 obj_desc->device.gpe_block = NULL; 617 } 618 619 unlock_and_exit: 620 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 621 return_ACPI_STATUS(status); 622 } 623 624 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) 625 626 /******************************************************************************* 627 * 628 * FUNCTION: acpi_get_gpe_device 629 * 630 * PARAMETERS: Index - System GPE index (0-current_gpe_count) 631 * gpe_device - Where the parent GPE Device is returned 632 * 633 * RETURN: Status 634 * 635 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 636 * gpe device indicates that the gpe number is contained in one of 637 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 638 * 639 ******************************************************************************/ 640 acpi_status 641 acpi_get_gpe_device(u32 index, acpi_handle *gpe_device) 642 { 643 struct acpi_gpe_device_info info; 644 acpi_status status; 645 646 ACPI_FUNCTION_TRACE(acpi_get_gpe_device); 647 648 if (!gpe_device) { 649 return_ACPI_STATUS(AE_BAD_PARAMETER); 650 } 651 652 if (index >= acpi_current_gpe_count) { 653 return_ACPI_STATUS(AE_NOT_EXIST); 654 } 655 656 /* Setup and walk the GPE list */ 657 658 info.index = index; 659 info.status = AE_NOT_EXIST; 660 info.gpe_device = NULL; 661 info.next_block_base_index = 0; 662 663 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info); 664 if (ACPI_FAILURE(status)) { 665 return_ACPI_STATUS(status); 666 } 667 668 *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device); 669 return_ACPI_STATUS(info.status); 670 } 671 672 ACPI_EXPORT_SYMBOL(acpi_get_gpe_device) 673