1 /****************************************************************************** 2 * 3 * Module Name: hwgpe - Low level GPE enable/disable/clear functions 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/acevents.h> 47 48 #define _COMPONENT ACPI_HARDWARE 49 ACPI_MODULE_NAME ("hwgpe") 50 51 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 52 53 /* Local prototypes */ 54 55 static ACPI_STATUS 56 AcpiHwEnableWakeupGpeBlock ( 57 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 58 ACPI_GPE_BLOCK_INFO *GpeBlock, 59 void *Context); 60 61 static ACPI_STATUS 62 AcpiHwGpeEnableWrite ( 63 UINT8 EnableMask, 64 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo); 65 66 67 /****************************************************************************** 68 * 69 * FUNCTION: AcpiHwGetGpeRegisterBit 70 * 71 * PARAMETERS: GpeEventInfo - Info block for the GPE 72 * 73 * RETURN: Register mask with a one in the GPE bit position 74 * 75 * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the 76 * correct position for the input GPE. 77 * 78 ******************************************************************************/ 79 80 UINT32 81 AcpiHwGetGpeRegisterBit ( 82 ACPI_GPE_EVENT_INFO *GpeEventInfo) 83 { 84 85 return ((UINT32) 1 << 86 (GpeEventInfo->GpeNumber - GpeEventInfo->RegisterInfo->BaseGpeNumber)); 87 } 88 89 90 /****************************************************************************** 91 * 92 * FUNCTION: AcpiHwLowSetGpe 93 * 94 * PARAMETERS: GpeEventInfo - Info block for the GPE to be disabled 95 * Action - Enable or disable 96 * 97 * RETURN: Status 98 * 99 * DESCRIPTION: Enable or disable a single GPE in the parent enable register. 100 * The EnableMask field of the involved GPE register must be 101 * updated by the caller if necessary. 102 * 103 ******************************************************************************/ 104 105 ACPI_STATUS 106 AcpiHwLowSetGpe ( 107 ACPI_GPE_EVENT_INFO *GpeEventInfo, 108 UINT32 Action) 109 { 110 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 111 ACPI_STATUS Status = AE_OK; 112 UINT32 EnableMask; 113 UINT32 RegisterBit; 114 115 116 ACPI_FUNCTION_ENTRY (); 117 118 119 /* Get the info block for the entire GPE register */ 120 121 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 122 if (!GpeRegisterInfo) 123 { 124 return (AE_NOT_EXIST); 125 } 126 127 /* Get current value of the enable register that contains this GPE */ 128 129 Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress); 130 if (ACPI_FAILURE (Status)) 131 { 132 return (Status); 133 } 134 135 /* Set or clear just the bit that corresponds to this GPE */ 136 137 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 138 switch (Action) 139 { 140 case ACPI_GPE_CONDITIONAL_ENABLE: 141 142 /* Only enable if the corresponding EnableMask bit is set */ 143 144 if (!(RegisterBit & GpeRegisterInfo->EnableMask)) 145 { 146 return (AE_BAD_PARAMETER); 147 } 148 149 /*lint -fallthrough */ 150 151 case ACPI_GPE_ENABLE: 152 153 ACPI_SET_BIT (EnableMask, RegisterBit); 154 break; 155 156 case ACPI_GPE_DISABLE: 157 158 ACPI_CLEAR_BIT (EnableMask, RegisterBit); 159 break; 160 161 default: 162 163 ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u", Action)); 164 return (AE_BAD_PARAMETER); 165 } 166 167 if (!(RegisterBit & GpeRegisterInfo->MaskForRun)) 168 { 169 /* Write the updated enable mask */ 170 171 Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); 172 } 173 return (Status); 174 } 175 176 177 /****************************************************************************** 178 * 179 * FUNCTION: AcpiHwClearGpe 180 * 181 * PARAMETERS: GpeEventInfo - Info block for the GPE to be cleared 182 * 183 * RETURN: Status 184 * 185 * DESCRIPTION: Clear the status bit for a single GPE. 186 * 187 ******************************************************************************/ 188 189 ACPI_STATUS 190 AcpiHwClearGpe ( 191 ACPI_GPE_EVENT_INFO *GpeEventInfo) 192 { 193 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 194 ACPI_STATUS Status; 195 UINT32 RegisterBit; 196 197 198 ACPI_FUNCTION_ENTRY (); 199 200 /* Get the info block for the entire GPE register */ 201 202 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 203 if (!GpeRegisterInfo) 204 { 205 return (AE_NOT_EXIST); 206 } 207 208 /* 209 * Write a one to the appropriate bit in the status register to 210 * clear this GPE. 211 */ 212 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 213 214 Status = AcpiHwWrite (RegisterBit, &GpeRegisterInfo->StatusAddress); 215 return (Status); 216 } 217 218 219 /****************************************************************************** 220 * 221 * FUNCTION: AcpiHwGetGpeStatus 222 * 223 * PARAMETERS: GpeEventInfo - Info block for the GPE to queried 224 * EventStatus - Where the GPE status is returned 225 * 226 * RETURN: Status 227 * 228 * DESCRIPTION: Return the status of a single GPE. 229 * 230 ******************************************************************************/ 231 232 ACPI_STATUS 233 AcpiHwGetGpeStatus ( 234 ACPI_GPE_EVENT_INFO *GpeEventInfo, 235 ACPI_EVENT_STATUS *EventStatus) 236 { 237 UINT32 InByte; 238 UINT32 RegisterBit; 239 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 240 ACPI_EVENT_STATUS LocalEventStatus = 0; 241 ACPI_STATUS Status; 242 243 244 ACPI_FUNCTION_ENTRY (); 245 246 247 if (!EventStatus) 248 { 249 return (AE_BAD_PARAMETER); 250 } 251 252 /* GPE currently handled? */ 253 254 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != 255 ACPI_GPE_DISPATCH_NONE) 256 { 257 LocalEventStatus |= ACPI_EVENT_FLAG_HAS_HANDLER; 258 } 259 260 /* Get the info block for the entire GPE register */ 261 262 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 263 264 /* Get the register bitmask for this GPE */ 265 266 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 267 268 /* GPE currently enabled? (enabled for runtime?) */ 269 270 if (RegisterBit & GpeRegisterInfo->EnableForRun) 271 { 272 LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED; 273 } 274 275 /* GPE currently masked? (masked for runtime?) */ 276 277 if (RegisterBit & GpeRegisterInfo->MaskForRun) 278 { 279 LocalEventStatus |= ACPI_EVENT_FLAG_MASKED; 280 } 281 282 /* GPE enabled for wake? */ 283 284 if (RegisterBit & GpeRegisterInfo->EnableForWake) 285 { 286 LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED; 287 } 288 289 /* GPE currently enabled (enable bit == 1)? */ 290 291 Status = AcpiHwRead (&InByte, &GpeRegisterInfo->EnableAddress); 292 if (ACPI_FAILURE (Status)) 293 { 294 return (Status); 295 } 296 297 if (RegisterBit & InByte) 298 { 299 LocalEventStatus |= ACPI_EVENT_FLAG_ENABLE_SET; 300 } 301 302 /* GPE currently active (status bit == 1)? */ 303 304 Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress); 305 if (ACPI_FAILURE (Status)) 306 { 307 return (Status); 308 } 309 310 if (RegisterBit & InByte) 311 { 312 LocalEventStatus |= ACPI_EVENT_FLAG_STATUS_SET; 313 } 314 315 /* Set return value */ 316 317 (*EventStatus) = LocalEventStatus; 318 return (AE_OK); 319 } 320 321 322 /****************************************************************************** 323 * 324 * FUNCTION: AcpiHwGpeEnableWrite 325 * 326 * PARAMETERS: EnableMask - Bit mask to write to the GPE register 327 * GpeRegisterInfo - Gpe Register info 328 * 329 * RETURN: Status 330 * 331 * DESCRIPTION: Write the enable mask byte to the given GPE register. 332 * 333 ******************************************************************************/ 334 335 static ACPI_STATUS 336 AcpiHwGpeEnableWrite ( 337 UINT8 EnableMask, 338 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo) 339 { 340 ACPI_STATUS Status; 341 342 343 GpeRegisterInfo->EnableMask = EnableMask; 344 345 Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); 346 return (Status); 347 } 348 349 350 /****************************************************************************** 351 * 352 * FUNCTION: AcpiHwDisableGpeBlock 353 * 354 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 355 * GpeBlock - Gpe Block info 356 * 357 * RETURN: Status 358 * 359 * DESCRIPTION: Disable all GPEs within a single GPE block 360 * 361 ******************************************************************************/ 362 363 ACPI_STATUS 364 AcpiHwDisableGpeBlock ( 365 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 366 ACPI_GPE_BLOCK_INFO *GpeBlock, 367 void *Context) 368 { 369 UINT32 i; 370 ACPI_STATUS Status; 371 372 373 /* Examine each GPE Register within the block */ 374 375 for (i = 0; i < GpeBlock->RegisterCount; i++) 376 { 377 /* Disable all GPEs in this register */ 378 379 Status = AcpiHwGpeEnableWrite (0x00, &GpeBlock->RegisterInfo[i]); 380 if (ACPI_FAILURE (Status)) 381 { 382 return (Status); 383 } 384 } 385 386 return (AE_OK); 387 } 388 389 390 /****************************************************************************** 391 * 392 * FUNCTION: AcpiHwClearGpeBlock 393 * 394 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 395 * GpeBlock - Gpe Block info 396 * 397 * RETURN: Status 398 * 399 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block 400 * 401 ******************************************************************************/ 402 403 ACPI_STATUS 404 AcpiHwClearGpeBlock ( 405 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 406 ACPI_GPE_BLOCK_INFO *GpeBlock, 407 void *Context) 408 { 409 UINT32 i; 410 ACPI_STATUS Status; 411 412 413 /* Examine each GPE Register within the block */ 414 415 for (i = 0; i < GpeBlock->RegisterCount; i++) 416 { 417 /* Clear status on all GPEs in this register */ 418 419 Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress); 420 if (ACPI_FAILURE (Status)) 421 { 422 return (Status); 423 } 424 } 425 426 return (AE_OK); 427 } 428 429 430 /****************************************************************************** 431 * 432 * FUNCTION: AcpiHwEnableRuntimeGpeBlock 433 * 434 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 435 * GpeBlock - Gpe Block info 436 * 437 * RETURN: Status 438 * 439 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes 440 * combination wake/run GPEs. 441 * 442 ******************************************************************************/ 443 444 ACPI_STATUS 445 AcpiHwEnableRuntimeGpeBlock ( 446 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 447 ACPI_GPE_BLOCK_INFO *GpeBlock, 448 void *Context) 449 { 450 UINT32 i; 451 ACPI_STATUS Status; 452 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 453 UINT8 EnableMask; 454 455 456 /* NOTE: assumes that all GPEs are currently disabled */ 457 458 /* Examine each GPE Register within the block */ 459 460 for (i = 0; i < GpeBlock->RegisterCount; i++) 461 { 462 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 463 if (!GpeRegisterInfo->EnableForRun) 464 { 465 continue; 466 } 467 468 /* Enable all "runtime" GPEs in this register */ 469 470 EnableMask = GpeRegisterInfo->EnableForRun & 471 ~GpeRegisterInfo->MaskForRun; 472 Status = AcpiHwGpeEnableWrite (EnableMask, GpeRegisterInfo); 473 if (ACPI_FAILURE (Status)) 474 { 475 return (Status); 476 } 477 } 478 479 return (AE_OK); 480 } 481 482 483 /****************************************************************************** 484 * 485 * FUNCTION: AcpiHwEnableWakeupGpeBlock 486 * 487 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 488 * GpeBlock - Gpe Block info 489 * 490 * RETURN: Status 491 * 492 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes 493 * combination wake/run GPEs. 494 * 495 ******************************************************************************/ 496 497 static ACPI_STATUS 498 AcpiHwEnableWakeupGpeBlock ( 499 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 500 ACPI_GPE_BLOCK_INFO *GpeBlock, 501 void *Context) 502 { 503 UINT32 i; 504 ACPI_STATUS Status; 505 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 506 507 508 /* Examine each GPE Register within the block */ 509 510 for (i = 0; i < GpeBlock->RegisterCount; i++) 511 { 512 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 513 514 /* 515 * Enable all "wake" GPEs in this register and disable the 516 * remaining ones. 517 */ 518 Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForWake, 519 GpeRegisterInfo); 520 if (ACPI_FAILURE (Status)) 521 { 522 return (Status); 523 } 524 } 525 526 return (AE_OK); 527 } 528 529 530 /****************************************************************************** 531 * 532 * FUNCTION: AcpiHwDisableAllGpes 533 * 534 * PARAMETERS: None 535 * 536 * RETURN: Status 537 * 538 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 539 * 540 ******************************************************************************/ 541 542 ACPI_STATUS 543 AcpiHwDisableAllGpes ( 544 void) 545 { 546 ACPI_STATUS Status; 547 548 549 ACPI_FUNCTION_TRACE (HwDisableAllGpes); 550 551 552 Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL); 553 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 554 return_ACPI_STATUS (Status); 555 } 556 557 558 /****************************************************************************** 559 * 560 * FUNCTION: AcpiHwEnableAllRuntimeGpes 561 * 562 * PARAMETERS: None 563 * 564 * RETURN: Status 565 * 566 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 567 * 568 ******************************************************************************/ 569 570 ACPI_STATUS 571 AcpiHwEnableAllRuntimeGpes ( 572 void) 573 { 574 ACPI_STATUS Status; 575 576 577 ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes); 578 579 580 Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL); 581 return_ACPI_STATUS (Status); 582 } 583 584 585 /****************************************************************************** 586 * 587 * FUNCTION: AcpiHwEnableAllWakeupGpes 588 * 589 * PARAMETERS: None 590 * 591 * RETURN: Status 592 * 593 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks 594 * 595 ******************************************************************************/ 596 597 ACPI_STATUS 598 AcpiHwEnableAllWakeupGpes ( 599 void) 600 { 601 ACPI_STATUS Status; 602 603 604 ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes); 605 606 607 Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL); 608 return_ACPI_STATUS (Status); 609 } 610 611 #endif /* !ACPI_REDUCED_HARDWARE */ 612