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