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