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