1 /****************************************************************************** 2 * 3 * Module Name: hwgpe - Low level GPE enable/disable/clear functions 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 * 101 ******************************************************************************/ 102 103 ACPI_STATUS 104 AcpiHwLowSetGpe ( 105 ACPI_GPE_EVENT_INFO *GpeEventInfo, 106 UINT32 Action) 107 { 108 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 109 ACPI_STATUS Status; 110 UINT32 EnableMask; 111 UINT32 RegisterBit; 112 113 114 ACPI_FUNCTION_ENTRY (); 115 116 117 /* Get the info block for the entire GPE register */ 118 119 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 120 if (!GpeRegisterInfo) 121 { 122 return (AE_NOT_EXIST); 123 } 124 125 /* Get current value of the enable register that contains this GPE */ 126 127 Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress); 128 if (ACPI_FAILURE (Status)) 129 { 130 return (Status); 131 } 132 133 /* Set or clear just the bit that corresponds to this GPE */ 134 135 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 136 switch (Action & ~ACPI_GPE_SAVE_MASK) 137 { 138 case ACPI_GPE_CONDITIONAL_ENABLE: 139 140 /* Only enable if the corresponding EnableMask bit is set */ 141 142 if (!(RegisterBit & GpeRegisterInfo->EnableMask)) 143 { 144 return (AE_BAD_PARAMETER); 145 } 146 147 /*lint -fallthrough */ 148 149 case ACPI_GPE_ENABLE: 150 151 ACPI_SET_BIT (EnableMask, RegisterBit); 152 break; 153 154 case ACPI_GPE_DISABLE: 155 156 ACPI_CLEAR_BIT (EnableMask, RegisterBit); 157 break; 158 159 default: 160 161 ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u", Action)); 162 return (AE_BAD_PARAMETER); 163 } 164 165 /* Write the updated enable mask */ 166 167 Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); 168 if (ACPI_SUCCESS (Status) && (Action & ACPI_GPE_SAVE_MASK)) 169 { 170 GpeRegisterInfo->EnableMask = (UINT8) EnableMask; 171 } 172 return (Status); 173 } 174 175 176 /****************************************************************************** 177 * 178 * FUNCTION: AcpiHwClearGpe 179 * 180 * PARAMETERS: GpeEventInfo - Info block for the GPE to be cleared 181 * 182 * RETURN: Status 183 * 184 * DESCRIPTION: Clear the status bit for a single GPE. 185 * 186 ******************************************************************************/ 187 188 ACPI_STATUS 189 AcpiHwClearGpe ( 190 ACPI_GPE_EVENT_INFO *GpeEventInfo) 191 { 192 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 193 ACPI_STATUS Status; 194 UINT32 RegisterBit; 195 196 197 ACPI_FUNCTION_ENTRY (); 198 199 /* Get the info block for the entire GPE register */ 200 201 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 202 if (!GpeRegisterInfo) 203 { 204 return (AE_NOT_EXIST); 205 } 206 207 /* 208 * Write a one to the appropriate bit in the status register to 209 * clear this GPE. 210 */ 211 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 212 213 Status = AcpiHwWrite (RegisterBit, 214 &GpeRegisterInfo->StatusAddress); 215 216 return (Status); 217 } 218 219 220 /****************************************************************************** 221 * 222 * FUNCTION: AcpiHwGetGpeStatus 223 * 224 * PARAMETERS: GpeEventInfo - Info block for the GPE to queried 225 * EventStatus - Where the GPE status is returned 226 * 227 * RETURN: Status 228 * 229 * DESCRIPTION: Return the status of a single GPE. 230 * 231 ******************************************************************************/ 232 233 ACPI_STATUS 234 AcpiHwGetGpeStatus ( 235 ACPI_GPE_EVENT_INFO *GpeEventInfo, 236 ACPI_EVENT_STATUS *EventStatus) 237 { 238 UINT32 InByte; 239 UINT32 RegisterBit; 240 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 241 ACPI_EVENT_STATUS LocalEventStatus = 0; 242 ACPI_STATUS Status; 243 244 245 ACPI_FUNCTION_ENTRY (); 246 247 248 if (!EventStatus) 249 { 250 return (AE_BAD_PARAMETER); 251 } 252 253 /* GPE currently handled? */ 254 255 if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != 256 ACPI_GPE_DISPATCH_NONE) 257 { 258 LocalEventStatus |= ACPI_EVENT_FLAG_HAS_HANDLER; 259 } 260 261 /* Get the info block for the entire GPE register */ 262 263 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 264 265 /* Get the register bitmask for this GPE */ 266 267 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 268 269 /* GPE currently enabled? (enabled for runtime?) */ 270 271 if (RegisterBit & GpeRegisterInfo->EnableForRun) 272 { 273 LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED; 274 } 275 276 /* GPE enabled for wake? */ 277 278 if (RegisterBit & GpeRegisterInfo->EnableForWake) 279 { 280 LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED; 281 } 282 283 /* GPE currently enabled (enable bit == 1)? */ 284 285 Status = AcpiHwRead (&InByte, &GpeRegisterInfo->EnableAddress); 286 if (ACPI_FAILURE (Status)) 287 { 288 return (Status); 289 } 290 291 if (RegisterBit & InByte) 292 { 293 LocalEventStatus |= ACPI_EVENT_FLAG_ENABLE_SET; 294 } 295 296 /* GPE currently active (status bit == 1)? */ 297 298 Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress); 299 if (ACPI_FAILURE (Status)) 300 { 301 return (Status); 302 } 303 304 if (RegisterBit & InByte) 305 { 306 LocalEventStatus |= ACPI_EVENT_FLAG_STATUS_SET; 307 } 308 309 /* Set return value */ 310 311 (*EventStatus) = LocalEventStatus; 312 return (AE_OK); 313 } 314 315 316 /****************************************************************************** 317 * 318 * FUNCTION: AcpiHwGpeEnableWrite 319 * 320 * PARAMETERS: EnableMask - Bit mask to write to the GPE register 321 * GpeRegisterInfo - Gpe Register info 322 * 323 * RETURN: Status 324 * 325 * DESCRIPTION: Write the enable mask byte to the given GPE register. 326 * 327 ******************************************************************************/ 328 329 static ACPI_STATUS 330 AcpiHwGpeEnableWrite ( 331 UINT8 EnableMask, 332 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo) 333 { 334 ACPI_STATUS Status; 335 336 337 Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); 338 if (ACPI_SUCCESS (Status)) 339 { 340 GpeRegisterInfo->EnableMask = EnableMask; 341 } 342 343 return (Status); 344 } 345 346 347 /****************************************************************************** 348 * 349 * FUNCTION: AcpiHwDisableGpeBlock 350 * 351 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 352 * GpeBlock - Gpe Block info 353 * 354 * RETURN: Status 355 * 356 * DESCRIPTION: Disable all GPEs within a single GPE block 357 * 358 ******************************************************************************/ 359 360 ACPI_STATUS 361 AcpiHwDisableGpeBlock ( 362 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 363 ACPI_GPE_BLOCK_INFO *GpeBlock, 364 void *Context) 365 { 366 UINT32 i; 367 ACPI_STATUS Status; 368 369 370 /* Examine each GPE Register within the block */ 371 372 for (i = 0; i < GpeBlock->RegisterCount; i++) 373 { 374 /* Disable all GPEs in this register */ 375 376 Status = AcpiHwGpeEnableWrite (0x00, &GpeBlock->RegisterInfo[i]); 377 if (ACPI_FAILURE (Status)) 378 { 379 return (Status); 380 } 381 } 382 383 return (AE_OK); 384 } 385 386 387 /****************************************************************************** 388 * 389 * FUNCTION: AcpiHwClearGpeBlock 390 * 391 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 392 * GpeBlock - Gpe Block info 393 * 394 * RETURN: Status 395 * 396 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block 397 * 398 ******************************************************************************/ 399 400 ACPI_STATUS 401 AcpiHwClearGpeBlock ( 402 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 403 ACPI_GPE_BLOCK_INFO *GpeBlock, 404 void *Context) 405 { 406 UINT32 i; 407 ACPI_STATUS Status; 408 409 410 /* Examine each GPE Register within the block */ 411 412 for (i = 0; i < GpeBlock->RegisterCount; i++) 413 { 414 /* Clear status on all GPEs in this register */ 415 416 Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress); 417 if (ACPI_FAILURE (Status)) 418 { 419 return (Status); 420 } 421 } 422 423 return (AE_OK); 424 } 425 426 427 /****************************************************************************** 428 * 429 * FUNCTION: AcpiHwEnableRuntimeGpeBlock 430 * 431 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 432 * GpeBlock - Gpe Block info 433 * 434 * RETURN: Status 435 * 436 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes 437 * combination wake/run GPEs. 438 * 439 ******************************************************************************/ 440 441 ACPI_STATUS 442 AcpiHwEnableRuntimeGpeBlock ( 443 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 444 ACPI_GPE_BLOCK_INFO *GpeBlock, 445 void *Context) 446 { 447 UINT32 i; 448 ACPI_STATUS Status; 449 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 450 451 452 /* NOTE: assumes that all GPEs are currently disabled */ 453 454 /* Examine each GPE Register within the block */ 455 456 for (i = 0; i < GpeBlock->RegisterCount; i++) 457 { 458 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 459 if (!GpeRegisterInfo->EnableForRun) 460 { 461 continue; 462 } 463 464 /* Enable all "runtime" GPEs in this register */ 465 466 Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForRun, 467 GpeRegisterInfo); 468 if (ACPI_FAILURE (Status)) 469 { 470 return (Status); 471 } 472 } 473 474 return (AE_OK); 475 } 476 477 478 /****************************************************************************** 479 * 480 * FUNCTION: AcpiHwEnableWakeupGpeBlock 481 * 482 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 483 * GpeBlock - Gpe Block info 484 * 485 * RETURN: Status 486 * 487 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes 488 * combination wake/run GPEs. 489 * 490 ******************************************************************************/ 491 492 static ACPI_STATUS 493 AcpiHwEnableWakeupGpeBlock ( 494 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 495 ACPI_GPE_BLOCK_INFO *GpeBlock, 496 void *Context) 497 { 498 UINT32 i; 499 ACPI_STATUS Status; 500 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 501 502 503 /* Examine each GPE Register within the block */ 504 505 for (i = 0; i < GpeBlock->RegisterCount; i++) 506 { 507 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 508 509 /* 510 * Enable all "wake" GPEs in this register and disable the 511 * remaining ones. 512 */ 513 Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForWake, 514 GpeRegisterInfo); 515 if (ACPI_FAILURE (Status)) 516 { 517 return (Status); 518 } 519 } 520 521 return (AE_OK); 522 } 523 524 525 /****************************************************************************** 526 * 527 * FUNCTION: AcpiHwDisableAllGpes 528 * 529 * PARAMETERS: None 530 * 531 * RETURN: Status 532 * 533 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 534 * 535 ******************************************************************************/ 536 537 ACPI_STATUS 538 AcpiHwDisableAllGpes ( 539 void) 540 { 541 ACPI_STATUS Status; 542 543 544 ACPI_FUNCTION_TRACE (HwDisableAllGpes); 545 546 547 Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL); 548 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 549 return_ACPI_STATUS (Status); 550 } 551 552 553 /****************************************************************************** 554 * 555 * FUNCTION: AcpiHwEnableAllRuntimeGpes 556 * 557 * PARAMETERS: None 558 * 559 * RETURN: Status 560 * 561 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 562 * 563 ******************************************************************************/ 564 565 ACPI_STATUS 566 AcpiHwEnableAllRuntimeGpes ( 567 void) 568 { 569 ACPI_STATUS Status; 570 571 572 ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes); 573 574 575 Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL); 576 return_ACPI_STATUS (Status); 577 } 578 579 580 /****************************************************************************** 581 * 582 * FUNCTION: AcpiHwEnableAllWakeupGpes 583 * 584 * PARAMETERS: None 585 * 586 * RETURN: Status 587 * 588 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks 589 * 590 ******************************************************************************/ 591 592 ACPI_STATUS 593 AcpiHwEnableAllWakeupGpes ( 594 void) 595 { 596 ACPI_STATUS Status; 597 598 599 ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes); 600 601 602 Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL); 603 return_ACPI_STATUS (Status); 604 } 605 606 #endif /* !ACPI_REDUCED_HARDWARE */ 607