Branch data Line data Source code
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 : 294 : u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info) 41 : : { 42 : : 43 : 294 : return ((u32)1 << 44 : 294 : (gpe_event_info->gpe_number - 45 : 294 : 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 : 84 : acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) 65 : : { 66 : 84 : struct acpi_gpe_register_info *gpe_register_info; 67 : 84 : acpi_status status = AE_OK; 68 : 84 : u64 enable_mask; 69 : 84 : u32 register_bit; 70 : : 71 : 84 : ACPI_FUNCTION_ENTRY(); 72 : : 73 : : /* Get the info block for the entire GPE register */ 74 : : 75 : 84 : gpe_register_info = gpe_event_info->register_info; 76 [ + - ]: 84 : 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 : 84 : status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address); 83 [ + - ]: 84 : if (ACPI_FAILURE(status)) { 84 : : return (status); 85 : : } 86 : : 87 : : /* Set or clear just the bit that corresponds to this GPE */ 88 : : 89 : 84 : register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 90 [ - + + - ]: 84 : switch (action) { 91 : 0 : case ACPI_GPE_CONDITIONAL_ENABLE: 92 : : 93 : : /* Only enable if the corresponding enable_mask bit is set */ 94 : : 95 [ # # ]: 0 : 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 : 42 : ACPI_SET_BIT(enable_mask, register_bit); 104 : 42 : break; 105 : : 106 : 42 : case ACPI_GPE_DISABLE: 107 : : 108 : 42 : ACPI_CLEAR_BIT(enable_mask, register_bit); 109 : 42 : break; 110 : : 111 : 0 : default: 112 : : 113 : 0 : ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action)); 114 : 0 : return (AE_BAD_PARAMETER); 115 : : } 116 : : 117 [ + - ]: 84 : if (!(register_bit & gpe_register_info->mask_for_run)) { 118 : : 119 : : /* Write the updated enable mask */ 120 : : 121 : 84 : status = 122 : 84 : 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 : 0 : acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info) 141 : : { 142 : 0 : struct acpi_gpe_register_info *gpe_register_info; 143 : 0 : acpi_status status; 144 : 0 : u32 register_bit; 145 : : 146 : 0 : ACPI_FUNCTION_ENTRY(); 147 : : 148 : : /* Get the info block for the entire GPE register */ 149 : : 150 : 0 : gpe_register_info = gpe_event_info->register_info; 151 [ # # ]: 0 : 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 : 0 : register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 160 : : 161 : 0 : status = 162 : 0 : acpi_hw_write(register_bit, &gpe_register_info->status_address); 163 : 0 : 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 : 0 : acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info, 181 : : acpi_event_status *event_status) 182 : : { 183 : 0 : u64 in_byte; 184 : 0 : u32 register_bit; 185 : 0 : struct acpi_gpe_register_info *gpe_register_info; 186 : 0 : acpi_event_status local_event_status = 0; 187 : 0 : acpi_status status; 188 : : 189 : 0 : ACPI_FUNCTION_ENTRY(); 190 : : 191 [ # # ]: 0 : if (!event_status) { 192 : : return (AE_BAD_PARAMETER); 193 : : } 194 : : 195 : : /* GPE currently handled? */ 196 : : 197 [ # # ]: 0 : if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) != 198 : : ACPI_GPE_DISPATCH_NONE) { 199 : 0 : local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER; 200 : : } 201 : : 202 : : /* Get the info block for the entire GPE register */ 203 : : 204 : 0 : gpe_register_info = gpe_event_info->register_info; 205 : : 206 : : /* Get the register bitmask for this GPE */ 207 : : 208 : 0 : register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); 209 : : 210 : : /* GPE currently enabled? (enabled for runtime?) */ 211 : : 212 [ # # ]: 0 : if (register_bit & gpe_register_info->enable_for_run) { 213 : 0 : local_event_status |= ACPI_EVENT_FLAG_ENABLED; 214 : : } 215 : : 216 : : /* GPE currently masked? (masked for runtime?) */ 217 : : 218 [ # # ]: 0 : if (register_bit & gpe_register_info->mask_for_run) { 219 : 0 : local_event_status |= ACPI_EVENT_FLAG_MASKED; 220 : : } 221 : : 222 : : /* GPE enabled for wake? */ 223 : : 224 [ # # ]: 0 : if (register_bit & gpe_register_info->enable_for_wake) { 225 : 0 : local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED; 226 : : } 227 : : 228 : : /* GPE currently enabled (enable bit == 1)? */ 229 : : 230 : 0 : status = acpi_hw_read(&in_byte, &gpe_register_info->enable_address); 231 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 232 : : return (status); 233 : : } 234 : : 235 [ # # ]: 0 : if (register_bit & in_byte) { 236 : 0 : local_event_status |= ACPI_EVENT_FLAG_ENABLE_SET; 237 : : } 238 : : 239 : : /* GPE currently active (status bit == 1)? */ 240 : : 241 : 0 : status = acpi_hw_read(&in_byte, &gpe_register_info->status_address); 242 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 243 : : return (status); 244 : : } 245 : : 246 [ # # ]: 0 : if (register_bit & in_byte) { 247 : 0 : local_event_status |= ACPI_EVENT_FLAG_STATUS_SET; 248 : : } 249 : : 250 : : /* Set return value */ 251 : : 252 : 0 : (*event_status) = local_event_status; 253 : 0 : 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 : 0 : acpi_hw_gpe_enable_write(u8 enable_mask, 271 : : struct acpi_gpe_register_info *gpe_register_info) 272 : : { 273 : 0 : acpi_status status; 274 : : 275 : 0 : gpe_register_info->enable_mask = enable_mask; 276 : : 277 : 0 : status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); 278 : 0 : 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 : 0 : 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 : 0 : u32 i; 299 : 0 : acpi_status status; 300 : : 301 : : /* Examine each GPE Register within the block */ 302 : : 303 [ # # ]: 0 : for (i = 0; i < gpe_block->register_count; i++) { 304 : : 305 : : /* Disable all GPEs in this register */ 306 : : 307 : 0 : status = 308 : 0 : acpi_hw_gpe_enable_write(0x00, 309 : 0 : &gpe_block->register_info[i]); 310 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 311 : 0 : 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 : 0 : 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 : 0 : u32 i; 336 : 0 : acpi_status status; 337 : : 338 : : /* Examine each GPE Register within the block */ 339 : : 340 [ # # ]: 0 : for (i = 0; i < gpe_block->register_count; i++) { 341 : : 342 : : /* Clear status on all GPEs in this register */ 343 : : 344 : 0 : status = 345 : 0 : acpi_hw_write(0xFF, 346 : 0 : &gpe_block->register_info[i].status_address); 347 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 348 : 0 : 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 : 0 : 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 : 0 : u32 i; 375 : 0 : acpi_status status; 376 : 0 : struct acpi_gpe_register_info *gpe_register_info; 377 : 0 : u8 enable_mask; 378 : : 379 : : /* NOTE: assumes that all GPEs are currently disabled */ 380 : : 381 : : /* Examine each GPE Register within the block */ 382 : : 383 [ # # ]: 0 : for (i = 0; i < gpe_block->register_count; i++) { 384 : 0 : gpe_register_info = &gpe_block->register_info[i]; 385 [ # # ]: 0 : if (!gpe_register_info->enable_for_run) { 386 : 0 : continue; 387 : : } 388 : : 389 : : /* Enable all "runtime" GPEs in this register */ 390 : : 391 : 0 : enable_mask = gpe_register_info->enable_for_run & 392 : 0 : ~gpe_register_info->mask_for_run; 393 : 0 : status = 394 : 0 : acpi_hw_gpe_enable_write(enable_mask, gpe_register_info); 395 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 396 : 0 : 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 : 0 : 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 : 0 : u32 i; 423 : 0 : acpi_status status; 424 : 0 : struct acpi_gpe_register_info *gpe_register_info; 425 : : 426 : : /* Examine each GPE Register within the block */ 427 : : 428 [ # # ]: 0 : for (i = 0; i < gpe_block->register_count; i++) { 429 : 0 : 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 : 0 : status = 437 : 0 : acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake, 438 : : gpe_register_info); 439 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 440 : 0 : 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 : 0 : 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 : 0 : struct acpi_gpe_register_info *gpe_register_info; 466 : 0 : u64 in_enable, in_status; 467 : 0 : acpi_status status; 468 : 0 : u8 *ret = ret_ptr; 469 : 0 : u32 i; 470 : : 471 : : /* Examine each GPE Register within the block */ 472 : : 473 [ # # ]: 0 : for (i = 0; i < gpe_block->register_count; i++) { 474 : 0 : gpe_register_info = &gpe_block->register_info[i]; 475 : : 476 : 0 : status = acpi_hw_read(&in_enable, 477 : : &gpe_register_info->enable_address); 478 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 479 : 0 : continue; 480 : : } 481 : : 482 : 0 : status = acpi_hw_read(&in_status, 483 : : &gpe_register_info->status_address); 484 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 485 : 0 : continue; 486 : : } 487 : : 488 : 0 : *ret |= in_enable & in_status; 489 : : } 490 : : 491 : 0 : 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 : 0 : acpi_status acpi_hw_disable_all_gpes(void) 507 : : { 508 : 0 : acpi_status status; 509 : : 510 : 0 : ACPI_FUNCTION_TRACE(hw_disable_all_gpes); 511 : : 512 : 0 : status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); 513 : 0 : 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 : 0 : acpi_status acpi_hw_enable_all_runtime_gpes(void) 529 : : { 530 : 0 : acpi_status status; 531 : : 532 : 0 : ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes); 533 : : 534 : 0 : status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL); 535 : 0 : 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 : 0 : acpi_status acpi_hw_enable_all_wakeup_gpes(void) 551 : : { 552 : 0 : acpi_status status; 553 : : 554 : 0 : ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes); 555 : : 556 : 0 : status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL); 557 : 0 : 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 : 0 : u8 acpi_hw_check_all_gpes(void) 574 : : { 575 : 0 : u8 ret = 0; 576 : : 577 : 0 : ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes); 578 : : 579 : 0 : (void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &ret); 580 : : 581 : 0 : return (ret != 0); 582 : : } 583 : : 584 : : #endif /* !ACPI_REDUCED_HARDWARE */