hwgpe.c (18406B)
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2/****************************************************************************** 3 * 4 * Module Name: hwgpe - Low level GPE enable/disable/clear functions 5 * 6 * Copyright (C) 2000 - 2022, Intel Corp. 7 * 8 *****************************************************************************/ 9 10#include <acpi/acpi.h> 11#include "accommon.h" 12#include "acevents.h" 13 14#define _COMPONENT ACPI_HARDWARE 15ACPI_MODULE_NAME("hwgpe") 16#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 17/* Local prototypes */ 18static acpi_status 19acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 20 struct acpi_gpe_block_info *gpe_block, 21 void *context); 22 23static acpi_status 24acpi_hw_gpe_enable_write(u8 enable_mask, 25 struct acpi_gpe_register_info *gpe_register_info); 26 27/****************************************************************************** 28 * 29 * FUNCTION: acpi_hw_gpe_read 30 * 31 * PARAMETERS: value - Where the value is returned 32 * reg - GPE register structure 33 * 34 * RETURN: Status 35 * 36 * DESCRIPTION: Read from a GPE register in either memory or IO space. 37 * 38 * LIMITATIONS: <These limitations also apply to acpi_hw_gpe_write> 39 * space_ID must be system_memory or system_IO. 40 * 41 ******************************************************************************/ 42 43acpi_status acpi_hw_gpe_read(u64 *value, struct acpi_gpe_address *reg) 44{ 45 acpi_status status; 46 u32 value32; 47 48 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { 49#ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES 50 *value = (u64)ACPI_GET8((unsigned long)reg->address); 51 return_ACPI_STATUS(AE_OK); 52#else 53 return acpi_os_read_memory((acpi_physical_address)reg->address, 54 value, ACPI_GPE_REGISTER_WIDTH); 55#endif 56 } 57 58 status = acpi_os_read_port((acpi_io_address)reg->address, 59 &value32, ACPI_GPE_REGISTER_WIDTH); 60 if (ACPI_FAILURE(status)) 61 return_ACPI_STATUS(status); 62 63 *value = (u64)value32; 64 65 return_ACPI_STATUS(AE_OK); 66} 67 68/****************************************************************************** 69 * 70 * FUNCTION: acpi_hw_gpe_write 71 * 72 * PARAMETERS: value - Value to be written 73 * reg - GPE register structure 74 * 75 * RETURN: Status 76 * 77 * DESCRIPTION: Write to a GPE register in either memory or IO space. 78 * 79 ******************************************************************************/ 80 81acpi_status acpi_hw_gpe_write(u64 value, struct acpi_gpe_address *reg) 82{ 83 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { 84#ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES 85 ACPI_SET8((unsigned long)reg->address, value); 86 return_ACPI_STATUS(AE_OK); 87#else 88 return acpi_os_write_memory((acpi_physical_address)reg->address, 89 value, ACPI_GPE_REGISTER_WIDTH); 90#endif 91 } 92 93 return acpi_os_write_port((acpi_io_address)reg->address, (u32)value, 94 ACPI_GPE_REGISTER_WIDTH); 95} 96 97/****************************************************************************** 98 * 99 * FUNCTION: acpi_hw_get_gpe_register_bit 100 * 101 * PARAMETERS: gpe_event_info - Info block for the GPE 102 * 103 * RETURN: Register mask with a one in the GPE bit position 104 * 105 * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the 106 * correct position for the input GPE. 107 * 108 ******************************************************************************/ 109 110u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info) 111{ 112 113 return ((u32)1 << 114 (gpe_event_info->gpe_number - 115 gpe_event_info->register_info->base_gpe_number)); 116} 117 118/****************************************************************************** 119 * 120 * FUNCTION: acpi_hw_low_set_gpe 121 * 122 * PARAMETERS: gpe_event_info - Info block for the GPE to be disabled 123 * action - Enable or disable 124 * 125 * RETURN: Status 126 * 127 * DESCRIPTION: Enable or disable a single GPE in the parent enable register. 128 * The enable_mask field of the involved GPE register must be 129 * updated by the caller if necessary. 130 * 131 ******************************************************************************/ 132 133acpi_status 134acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) 135{ 136 struct acpi_gpe_register_info *gpe_register_info; 137 acpi_status status = AE_OK; 138 u64 enable_mask; 139 u32 register_bit; 140 141 ACPI_FUNCTION_ENTRY(); 142 143 /* Get the info block for the entire GPE register */ 144 145 gpe_register_info = gpe_event_info->register_info; 146 if (!gpe_register_info) { 147 return (AE_NOT_EXIST); 148 } 149 150 /* Get current value of the enable register that contains this GPE */ 151 152 status = acpi_hw_gpe_read(&enable_mask, 153 &gpe_register_info->enable_address); 154 if (ACPI_FAILURE(status)) { 155 return (status); 156 } 157 158 /* Set or clear just the bit that corresponds to this GPE */ 159 160 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 161 switch (action) { 162 case ACPI_GPE_CONDITIONAL_ENABLE: 163 164 /* Only enable if the corresponding enable_mask bit is set */ 165 166 if (!(register_bit & gpe_register_info->enable_mask)) { 167 return (AE_BAD_PARAMETER); 168 } 169 170 ACPI_FALLTHROUGH; 171 172 case ACPI_GPE_ENABLE: 173 174 ACPI_SET_BIT(enable_mask, register_bit); 175 break; 176 177 case ACPI_GPE_DISABLE: 178 179 ACPI_CLEAR_BIT(enable_mask, register_bit); 180 break; 181 182 default: 183 184 ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action)); 185 return (AE_BAD_PARAMETER); 186 } 187 188 if (!(register_bit & gpe_register_info->mask_for_run)) { 189 190 /* Write the updated enable mask */ 191 192 status = acpi_hw_gpe_write(enable_mask, 193 &gpe_register_info->enable_address); 194 } 195 return (status); 196} 197 198/****************************************************************************** 199 * 200 * FUNCTION: acpi_hw_clear_gpe 201 * 202 * PARAMETERS: gpe_event_info - Info block for the GPE to be cleared 203 * 204 * RETURN: Status 205 * 206 * DESCRIPTION: Clear the status bit for a single GPE. 207 * 208 ******************************************************************************/ 209 210acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info) 211{ 212 struct acpi_gpe_register_info *gpe_register_info; 213 acpi_status status; 214 u32 register_bit; 215 216 ACPI_FUNCTION_ENTRY(); 217 218 /* Get the info block for the entire GPE register */ 219 220 gpe_register_info = gpe_event_info->register_info; 221 if (!gpe_register_info) { 222 return (AE_NOT_EXIST); 223 } 224 225 /* 226 * Write a one to the appropriate bit in the status register to 227 * clear this GPE. 228 */ 229 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 230 231 status = acpi_hw_gpe_write(register_bit, 232 &gpe_register_info->status_address); 233 return (status); 234} 235 236/****************************************************************************** 237 * 238 * FUNCTION: acpi_hw_get_gpe_status 239 * 240 * PARAMETERS: gpe_event_info - Info block for the GPE to queried 241 * event_status - Where the GPE status is returned 242 * 243 * RETURN: Status 244 * 245 * DESCRIPTION: Return the status of a single GPE. 246 * 247 ******************************************************************************/ 248 249acpi_status 250acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info, 251 acpi_event_status *event_status) 252{ 253 u64 in_byte; 254 u32 register_bit; 255 struct acpi_gpe_register_info *gpe_register_info; 256 acpi_event_status local_event_status = 0; 257 acpi_status status; 258 259 ACPI_FUNCTION_ENTRY(); 260 261 if (!event_status) { 262 return (AE_BAD_PARAMETER); 263 } 264 265 /* GPE currently handled? */ 266 267 if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) != 268 ACPI_GPE_DISPATCH_NONE) { 269 local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER; 270 } 271 272 /* Get the info block for the entire GPE register */ 273 274 gpe_register_info = gpe_event_info->register_info; 275 276 /* Get the register bitmask for this GPE */ 277 278 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 279 280 /* GPE currently enabled? (enabled for runtime?) */ 281 282 if (register_bit & gpe_register_info->enable_for_run) { 283 local_event_status |= ACPI_EVENT_FLAG_ENABLED; 284 } 285 286 /* GPE currently masked? (masked for runtime?) */ 287 288 if (register_bit & gpe_register_info->mask_for_run) { 289 local_event_status |= ACPI_EVENT_FLAG_MASKED; 290 } 291 292 /* GPE enabled for wake? */ 293 294 if (register_bit & gpe_register_info->enable_for_wake) { 295 local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED; 296 } 297 298 /* GPE currently enabled (enable bit == 1)? */ 299 300 status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->enable_address); 301 if (ACPI_FAILURE(status)) { 302 return (status); 303 } 304 305 if (register_bit & in_byte) { 306 local_event_status |= ACPI_EVENT_FLAG_ENABLE_SET; 307 } 308 309 /* GPE currently active (status bit == 1)? */ 310 311 status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->status_address); 312 if (ACPI_FAILURE(status)) { 313 return (status); 314 } 315 316 if (register_bit & in_byte) { 317 local_event_status |= ACPI_EVENT_FLAG_STATUS_SET; 318 } 319 320 /* Set return value */ 321 322 (*event_status) = local_event_status; 323 return (AE_OK); 324} 325 326/****************************************************************************** 327 * 328 * FUNCTION: acpi_hw_gpe_enable_write 329 * 330 * PARAMETERS: enable_mask - Bit mask to write to the GPE register 331 * gpe_register_info - Gpe Register info 332 * 333 * RETURN: Status 334 * 335 * DESCRIPTION: Write the enable mask byte to the given GPE register. 336 * 337 ******************************************************************************/ 338 339static acpi_status 340acpi_hw_gpe_enable_write(u8 enable_mask, 341 struct acpi_gpe_register_info *gpe_register_info) 342{ 343 acpi_status status; 344 345 gpe_register_info->enable_mask = enable_mask; 346 347 status = acpi_hw_gpe_write(enable_mask, 348 &gpe_register_info->enable_address); 349 return (status); 350} 351 352/****************************************************************************** 353 * 354 * FUNCTION: acpi_hw_disable_gpe_block 355 * 356 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 357 * gpe_block - Gpe Block info 358 * 359 * RETURN: Status 360 * 361 * DESCRIPTION: Disable all GPEs within a single GPE block 362 * 363 ******************************************************************************/ 364 365acpi_status 366acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 367 struct acpi_gpe_block_info *gpe_block, void *context) 368{ 369 u32 i; 370 acpi_status status; 371 372 /* Examine each GPE Register within the block */ 373 374 for (i = 0; i < gpe_block->register_count; i++) { 375 376 /* Disable all GPEs in this register */ 377 378 status = 379 acpi_hw_gpe_enable_write(0x00, 380 &gpe_block->register_info[i]); 381 if (ACPI_FAILURE(status)) { 382 return (status); 383 } 384 } 385 386 return (AE_OK); 387} 388 389/****************************************************************************** 390 * 391 * FUNCTION: acpi_hw_clear_gpe_block 392 * 393 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 394 * gpe_block - Gpe Block info 395 * 396 * RETURN: Status 397 * 398 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block 399 * 400 ******************************************************************************/ 401 402acpi_status 403acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 404 struct acpi_gpe_block_info *gpe_block, void *context) 405{ 406 u32 i; 407 acpi_status status; 408 409 /* Examine each GPE Register within the block */ 410 411 for (i = 0; i < gpe_block->register_count; i++) { 412 413 /* Clear status on all GPEs in this register */ 414 415 status = acpi_hw_gpe_write(0xFF, 416 &gpe_block->register_info[i].status_address); 417 if (ACPI_FAILURE(status)) { 418 return (status); 419 } 420 } 421 422 return (AE_OK); 423} 424 425/****************************************************************************** 426 * 427 * FUNCTION: acpi_hw_enable_runtime_gpe_block 428 * 429 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 430 * gpe_block - Gpe Block info 431 * 432 * RETURN: Status 433 * 434 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes 435 * combination wake/run GPEs. 436 * 437 ******************************************************************************/ 438 439acpi_status 440acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 441 struct acpi_gpe_block_info *gpe_block, 442 void *context) 443{ 444 u32 i; 445 acpi_status status; 446 struct acpi_gpe_register_info *gpe_register_info; 447 u8 enable_mask; 448 449 /* NOTE: assumes that all GPEs are currently disabled */ 450 451 /* Examine each GPE Register within the block */ 452 453 for (i = 0; i < gpe_block->register_count; i++) { 454 gpe_register_info = &gpe_block->register_info[i]; 455 if (!gpe_register_info->enable_for_run) { 456 continue; 457 } 458 459 /* Enable all "runtime" GPEs in this register */ 460 461 enable_mask = gpe_register_info->enable_for_run & 462 ~gpe_register_info->mask_for_run; 463 status = 464 acpi_hw_gpe_enable_write(enable_mask, gpe_register_info); 465 if (ACPI_FAILURE(status)) { 466 return (status); 467 } 468 } 469 470 return (AE_OK); 471} 472 473/****************************************************************************** 474 * 475 * FUNCTION: acpi_hw_enable_wakeup_gpe_block 476 * 477 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 478 * gpe_block - Gpe Block info 479 * 480 * RETURN: Status 481 * 482 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes 483 * combination wake/run GPEs. 484 * 485 ******************************************************************************/ 486 487static acpi_status 488acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 489 struct acpi_gpe_block_info *gpe_block, 490 void *context) 491{ 492 u32 i; 493 acpi_status status; 494 struct acpi_gpe_register_info *gpe_register_info; 495 496 /* Examine each GPE Register within the block */ 497 498 for (i = 0; i < gpe_block->register_count; i++) { 499 gpe_register_info = &gpe_block->register_info[i]; 500 501 /* 502 * Enable all "wake" GPEs in this register and disable the 503 * remaining ones. 504 */ 505 506 status = 507 acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake, 508 gpe_register_info); 509 if (ACPI_FAILURE(status)) { 510 return (status); 511 } 512 } 513 514 return (AE_OK); 515} 516 517struct acpi_gpe_block_status_context { 518 struct acpi_gpe_register_info *gpe_skip_register_info; 519 u8 gpe_skip_mask; 520 u8 retval; 521}; 522 523/****************************************************************************** 524 * 525 * FUNCTION: acpi_hw_get_gpe_block_status 526 * 527 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 528 * gpe_block - Gpe Block info 529 * context - GPE list walk context data 530 * 531 * RETURN: Success 532 * 533 * DESCRIPTION: Produce a combined GPE status bits mask for the given block. 534 * 535 ******************************************************************************/ 536 537static acpi_status 538acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 539 struct acpi_gpe_block_info *gpe_block, 540 void *context) 541{ 542 struct acpi_gpe_block_status_context *c = context; 543 struct acpi_gpe_register_info *gpe_register_info; 544 u64 in_enable, in_status; 545 acpi_status status; 546 u8 ret_mask; 547 u32 i; 548 549 /* Examine each GPE Register within the block */ 550 551 for (i = 0; i < gpe_block->register_count; i++) { 552 gpe_register_info = &gpe_block->register_info[i]; 553 554 status = acpi_hw_gpe_read(&in_enable, 555 &gpe_register_info->enable_address); 556 if (ACPI_FAILURE(status)) { 557 continue; 558 } 559 560 status = acpi_hw_gpe_read(&in_status, 561 &gpe_register_info->status_address); 562 if (ACPI_FAILURE(status)) { 563 continue; 564 } 565 566 ret_mask = in_enable & in_status; 567 if (ret_mask && c->gpe_skip_register_info == gpe_register_info) { 568 ret_mask &= ~c->gpe_skip_mask; 569 } 570 c->retval |= ret_mask; 571 } 572 573 return (AE_OK); 574} 575 576/****************************************************************************** 577 * 578 * FUNCTION: acpi_hw_disable_all_gpes 579 * 580 * PARAMETERS: None 581 * 582 * RETURN: Status 583 * 584 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 585 * 586 ******************************************************************************/ 587 588acpi_status acpi_hw_disable_all_gpes(void) 589{ 590 acpi_status status; 591 592 ACPI_FUNCTION_TRACE(hw_disable_all_gpes); 593 594 status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); 595 return_ACPI_STATUS(status); 596} 597 598/****************************************************************************** 599 * 600 * FUNCTION: acpi_hw_enable_all_runtime_gpes 601 * 602 * PARAMETERS: None 603 * 604 * RETURN: Status 605 * 606 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 607 * 608 ******************************************************************************/ 609 610acpi_status acpi_hw_enable_all_runtime_gpes(void) 611{ 612 acpi_status status; 613 614 ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes); 615 616 status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL); 617 return_ACPI_STATUS(status); 618} 619 620/****************************************************************************** 621 * 622 * FUNCTION: acpi_hw_enable_all_wakeup_gpes 623 * 624 * PARAMETERS: None 625 * 626 * RETURN: Status 627 * 628 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks 629 * 630 ******************************************************************************/ 631 632acpi_status acpi_hw_enable_all_wakeup_gpes(void) 633{ 634 acpi_status status; 635 636 ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes); 637 638 status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL); 639 return_ACPI_STATUS(status); 640} 641 642/****************************************************************************** 643 * 644 * FUNCTION: acpi_hw_check_all_gpes 645 * 646 * PARAMETERS: gpe_skip_device - GPE devoce of the GPE to skip 647 * gpe_skip_number - Number of the GPE to skip 648 * 649 * RETURN: Combined status of all GPEs 650 * 651 * DESCRIPTION: Check all enabled GPEs in all GPE blocks, except for the one 652 * represented by the "skip" arguments, and return TRUE if the 653 * status bit is set for at least one of them of FALSE otherwise. 654 * 655 ******************************************************************************/ 656 657u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number) 658{ 659 struct acpi_gpe_block_status_context context = { 660 .gpe_skip_register_info = NULL, 661 .retval = 0, 662 }; 663 struct acpi_gpe_event_info *gpe_event_info; 664 acpi_cpu_flags flags; 665 666 ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes); 667 668 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 669 670 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_skip_device, 671 gpe_skip_number); 672 if (gpe_event_info) { 673 context.gpe_skip_register_info = gpe_event_info->register_info; 674 context.gpe_skip_mask = acpi_hw_get_gpe_register_bit(gpe_event_info); 675 } 676 677 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 678 679 (void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &context); 680 return (context.retval != 0); 681} 682 683#endif /* !ACPI_REDUCED_HARDWARE */