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 /****************************************************************************** 448 * 449 * FUNCTION: acpi_hw_get_gpe_block_status 450 * 451 * PARAMETERS: gpe_xrupt_info - GPE Interrupt info 452 * gpe_block - Gpe Block info 453 * 454 * RETURN: Success 455 * 456 * DESCRIPTION: Produce a combined GPE status bits mask for the given block. 457 * 458 ******************************************************************************/ 459 460 static acpi_status 461 acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 462 struct acpi_gpe_block_info *gpe_block, 463 void *ret_ptr) 464 { 465 struct acpi_gpe_register_info *gpe_register_info; 466 u64 in_enable, in_status; 467 acpi_status status; 468 u8 *ret = ret_ptr; 469 u32 i; 470 471 /* Examine each GPE Register within the block */ 472 473 for (i = 0; i < gpe_block->register_count; i++) { 474 gpe_register_info = &gpe_block->register_info[i]; 475 476 status = acpi_hw_read(&in_enable, 477 &gpe_register_info->enable_address); 478 if (ACPI_FAILURE(status)) { 479 continue; 480 } 481 482 status = acpi_hw_read(&in_status, 483 &gpe_register_info->status_address); 484 if (ACPI_FAILURE(status)) { 485 continue; 486 } 487 488 *ret |= in_enable & in_status; 489 } 490 491 return (AE_OK); 492 } 493 494 /****************************************************************************** 495 * 496 * FUNCTION: acpi_hw_disable_all_gpes 497 * 498 * PARAMETERS: None 499 * 500 * RETURN: Status 501 * 502 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 503 * 504 ******************************************************************************/ 505 506 acpi_status acpi_hw_disable_all_gpes(void) 507 { 508 acpi_status status; 509 510 ACPI_FUNCTION_TRACE(hw_disable_all_gpes); 511 512 status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); 513 return_ACPI_STATUS(status); 514 } 515 516 /****************************************************************************** 517 * 518 * FUNCTION: acpi_hw_enable_all_runtime_gpes 519 * 520 * PARAMETERS: None 521 * 522 * RETURN: Status 523 * 524 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 525 * 526 ******************************************************************************/ 527 528 acpi_status acpi_hw_enable_all_runtime_gpes(void) 529 { 530 acpi_status status; 531 532 ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes); 533 534 status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL); 535 return_ACPI_STATUS(status); 536 } 537 538 /****************************************************************************** 539 * 540 * FUNCTION: acpi_hw_enable_all_wakeup_gpes 541 * 542 * PARAMETERS: None 543 * 544 * RETURN: Status 545 * 546 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks 547 * 548 ******************************************************************************/ 549 550 acpi_status acpi_hw_enable_all_wakeup_gpes(void) 551 { 552 acpi_status status; 553 554 ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes); 555 556 status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL); 557 return_ACPI_STATUS(status); 558 } 559 560 /****************************************************************************** 561 * 562 * FUNCTION: acpi_hw_check_all_gpes 563 * 564 * PARAMETERS: None 565 * 566 * RETURN: Combined status of all GPEs 567 * 568 * DESCRIPTION: Check all enabled GPEs in all GPE blocks and return TRUE if the 569 * status bit is set for at least one of them of FALSE otherwise. 570 * 571 ******************************************************************************/ 572 573 u8 acpi_hw_check_all_gpes(void) 574 { 575 u8 ret = 0; 576 577 ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes); 578 579 (void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &ret); 580 581 return (ret != 0); 582 } 583 584 #endif /* !ACPI_REDUCED_HARDWARE */ 585