| .. | .. |
|---|
| 3 | 3 | * |
|---|
| 4 | 4 | * Module Name: hwgpe - Low level GPE enable/disable/clear functions |
|---|
| 5 | 5 | * |
|---|
| 6 | | - * Copyright (C) 2000 - 2018, Intel Corp. |
|---|
| 6 | + * Copyright (C) 2000 - 2020, Intel Corp. |
|---|
| 7 | 7 | * |
|---|
| 8 | 8 | *****************************************************************************/ |
|---|
| 9 | 9 | |
|---|
| .. | .. |
|---|
| 23 | 23 | static acpi_status |
|---|
| 24 | 24 | acpi_hw_gpe_enable_write(u8 enable_mask, |
|---|
| 25 | 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 | + |
|---|
| 43 | +acpi_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 | + |
|---|
| 81 | +acpi_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 | +} |
|---|
| 26 | 96 | |
|---|
| 27 | 97 | /****************************************************************************** |
|---|
| 28 | 98 | * |
|---|
| .. | .. |
|---|
| 79 | 149 | |
|---|
| 80 | 150 | /* Get current value of the enable register that contains this GPE */ |
|---|
| 81 | 151 | |
|---|
| 82 | | - status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address); |
|---|
| 152 | + status = acpi_hw_gpe_read(&enable_mask, |
|---|
| 153 | + &gpe_register_info->enable_address); |
|---|
| 83 | 154 | if (ACPI_FAILURE(status)) { |
|---|
| 84 | 155 | return (status); |
|---|
| 85 | 156 | } |
|---|
| .. | .. |
|---|
| 118 | 189 | |
|---|
| 119 | 190 | /* Write the updated enable mask */ |
|---|
| 120 | 191 | |
|---|
| 121 | | - status = |
|---|
| 122 | | - acpi_hw_write(enable_mask, |
|---|
| 123 | | - &gpe_register_info->enable_address); |
|---|
| 192 | + status = acpi_hw_gpe_write(enable_mask, |
|---|
| 193 | + &gpe_register_info->enable_address); |
|---|
| 124 | 194 | } |
|---|
| 125 | 195 | return (status); |
|---|
| 126 | 196 | } |
|---|
| .. | .. |
|---|
| 158 | 228 | */ |
|---|
| 159 | 229 | register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); |
|---|
| 160 | 230 | |
|---|
| 161 | | - status = |
|---|
| 162 | | - acpi_hw_write(register_bit, &gpe_register_info->status_address); |
|---|
| 231 | + status = acpi_hw_gpe_write(register_bit, |
|---|
| 232 | + &gpe_register_info->status_address); |
|---|
| 163 | 233 | return (status); |
|---|
| 164 | 234 | } |
|---|
| 165 | 235 | |
|---|
| .. | .. |
|---|
| 227 | 297 | |
|---|
| 228 | 298 | /* GPE currently enabled (enable bit == 1)? */ |
|---|
| 229 | 299 | |
|---|
| 230 | | - status = acpi_hw_read(&in_byte, &gpe_register_info->enable_address); |
|---|
| 300 | + status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->enable_address); |
|---|
| 231 | 301 | if (ACPI_FAILURE(status)) { |
|---|
| 232 | 302 | return (status); |
|---|
| 233 | 303 | } |
|---|
| .. | .. |
|---|
| 238 | 308 | |
|---|
| 239 | 309 | /* GPE currently active (status bit == 1)? */ |
|---|
| 240 | 310 | |
|---|
| 241 | | - status = acpi_hw_read(&in_byte, &gpe_register_info->status_address); |
|---|
| 311 | + status = acpi_hw_gpe_read(&in_byte, &gpe_register_info->status_address); |
|---|
| 242 | 312 | if (ACPI_FAILURE(status)) { |
|---|
| 243 | 313 | return (status); |
|---|
| 244 | 314 | } |
|---|
| .. | .. |
|---|
| 274 | 344 | |
|---|
| 275 | 345 | gpe_register_info->enable_mask = enable_mask; |
|---|
| 276 | 346 | |
|---|
| 277 | | - status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); |
|---|
| 347 | + status = acpi_hw_gpe_write(enable_mask, |
|---|
| 348 | + &gpe_register_info->enable_address); |
|---|
| 278 | 349 | return (status); |
|---|
| 279 | 350 | } |
|---|
| 280 | 351 | |
|---|
| .. | .. |
|---|
| 341 | 412 | |
|---|
| 342 | 413 | /* Clear status on all GPEs in this register */ |
|---|
| 343 | 414 | |
|---|
| 344 | | - status = |
|---|
| 345 | | - acpi_hw_write(0xFF, |
|---|
| 346 | | - &gpe_block->register_info[i].status_address); |
|---|
| 415 | + status = acpi_hw_gpe_write(0xFF, |
|---|
| 416 | + &gpe_block->register_info[i].status_address); |
|---|
| 347 | 417 | if (ACPI_FAILURE(status)) { |
|---|
| 348 | 418 | return (status); |
|---|
| 349 | 419 | } |
|---|
| .. | .. |
|---|
| 444 | 514 | return (AE_OK); |
|---|
| 445 | 515 | } |
|---|
| 446 | 516 | |
|---|
| 517 | +struct 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 | + |
|---|
| 537 | +static acpi_status |
|---|
| 538 | +acpi_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 | + |
|---|
| 447 | 576 | /****************************************************************************** |
|---|
| 448 | 577 | * |
|---|
| 449 | 578 | * FUNCTION: acpi_hw_disable_all_gpes |
|---|
| .. | .. |
|---|
| 510 | 639 | return_ACPI_STATUS(status); |
|---|
| 511 | 640 | } |
|---|
| 512 | 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 | + |
|---|
| 657 | +u8 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 | + |
|---|
| 513 | 683 | #endif /* !ACPI_REDUCED_HARDWARE */ |
|---|