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 "acpi.h" 45 #include "accommon.h" 46 #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 active (status bit == 1)? */ 284 285 Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress); 286 if (ACPI_FAILURE (Status)) 287 { 288 return (Status); 289 } 290 291 if (RegisterBit & InByte) 292 { 293 LocalEventStatus |= ACPI_EVENT_FLAG_SET; 294 } 295 296 /* Set return value */ 297 298 (*EventStatus) = LocalEventStatus; 299 return (AE_OK); 300 } 301 302 303 /****************************************************************************** 304 * 305 * FUNCTION: AcpiHwGpeEnableWrite 306 * 307 * PARAMETERS: EnableMask - Bit mask to write to the GPE register 308 * GpeRegisterInfo - Gpe Register info 309 * 310 * RETURN: Status 311 * 312 * DESCRIPTION: Write the enable mask byte to the given GPE register. 313 * 314 ******************************************************************************/ 315 316 static ACPI_STATUS 317 AcpiHwGpeEnableWrite ( 318 UINT8 EnableMask, 319 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo) 320 { 321 ACPI_STATUS Status; 322 323 324 Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); 325 if (ACPI_SUCCESS (Status)) 326 { 327 GpeRegisterInfo->EnableMask = EnableMask; 328 } 329 330 return (Status); 331 } 332 333 334 /****************************************************************************** 335 * 336 * FUNCTION: AcpiHwDisableGpeBlock 337 * 338 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 339 * GpeBlock - Gpe Block info 340 * 341 * RETURN: Status 342 * 343 * DESCRIPTION: Disable all GPEs within a single GPE block 344 * 345 ******************************************************************************/ 346 347 ACPI_STATUS 348 AcpiHwDisableGpeBlock ( 349 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 350 ACPI_GPE_BLOCK_INFO *GpeBlock, 351 void *Context) 352 { 353 UINT32 i; 354 ACPI_STATUS Status; 355 356 357 /* Examine each GPE Register within the block */ 358 359 for (i = 0; i < GpeBlock->RegisterCount; i++) 360 { 361 /* Disable all GPEs in this register */ 362 363 Status = AcpiHwGpeEnableWrite (0x00, &GpeBlock->RegisterInfo[i]); 364 if (ACPI_FAILURE (Status)) 365 { 366 return (Status); 367 } 368 } 369 370 return (AE_OK); 371 } 372 373 374 /****************************************************************************** 375 * 376 * FUNCTION: AcpiHwClearGpeBlock 377 * 378 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 379 * GpeBlock - Gpe Block info 380 * 381 * RETURN: Status 382 * 383 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block 384 * 385 ******************************************************************************/ 386 387 ACPI_STATUS 388 AcpiHwClearGpeBlock ( 389 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 390 ACPI_GPE_BLOCK_INFO *GpeBlock, 391 void *Context) 392 { 393 UINT32 i; 394 ACPI_STATUS Status; 395 396 397 /* Examine each GPE Register within the block */ 398 399 for (i = 0; i < GpeBlock->RegisterCount; i++) 400 { 401 /* Clear status on all GPEs in this register */ 402 403 Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress); 404 if (ACPI_FAILURE (Status)) 405 { 406 return (Status); 407 } 408 } 409 410 return (AE_OK); 411 } 412 413 414 /****************************************************************************** 415 * 416 * FUNCTION: AcpiHwEnableRuntimeGpeBlock 417 * 418 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 419 * GpeBlock - Gpe Block info 420 * 421 * RETURN: Status 422 * 423 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes 424 * combination wake/run GPEs. 425 * 426 ******************************************************************************/ 427 428 ACPI_STATUS 429 AcpiHwEnableRuntimeGpeBlock ( 430 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 431 ACPI_GPE_BLOCK_INFO *GpeBlock, 432 void *Context) 433 { 434 UINT32 i; 435 ACPI_STATUS Status; 436 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 437 438 439 /* NOTE: assumes that all GPEs are currently disabled */ 440 441 /* Examine each GPE Register within the block */ 442 443 for (i = 0; i < GpeBlock->RegisterCount; i++) 444 { 445 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 446 if (!GpeRegisterInfo->EnableForRun) 447 { 448 continue; 449 } 450 451 /* Enable all "runtime" GPEs in this register */ 452 453 Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForRun, 454 GpeRegisterInfo); 455 if (ACPI_FAILURE (Status)) 456 { 457 return (Status); 458 } 459 } 460 461 return (AE_OK); 462 } 463 464 465 /****************************************************************************** 466 * 467 * FUNCTION: AcpiHwEnableWakeupGpeBlock 468 * 469 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 470 * GpeBlock - Gpe Block info 471 * 472 * RETURN: Status 473 * 474 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes 475 * combination wake/run GPEs. 476 * 477 ******************************************************************************/ 478 479 static ACPI_STATUS 480 AcpiHwEnableWakeupGpeBlock ( 481 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 482 ACPI_GPE_BLOCK_INFO *GpeBlock, 483 void *Context) 484 { 485 UINT32 i; 486 ACPI_STATUS Status; 487 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 488 489 490 /* Examine each GPE Register within the block */ 491 492 for (i = 0; i < GpeBlock->RegisterCount; i++) 493 { 494 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 495 496 /* 497 * Enable all "wake" GPEs in this register and disable the 498 * remaining ones. 499 */ 500 Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForWake, 501 GpeRegisterInfo); 502 if (ACPI_FAILURE (Status)) 503 { 504 return (Status); 505 } 506 } 507 508 return (AE_OK); 509 } 510 511 512 /****************************************************************************** 513 * 514 * FUNCTION: AcpiHwDisableAllGpes 515 * 516 * PARAMETERS: None 517 * 518 * RETURN: Status 519 * 520 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 521 * 522 ******************************************************************************/ 523 524 ACPI_STATUS 525 AcpiHwDisableAllGpes ( 526 void) 527 { 528 ACPI_STATUS Status; 529 530 531 ACPI_FUNCTION_TRACE (HwDisableAllGpes); 532 533 534 Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL); 535 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 536 return_ACPI_STATUS (Status); 537 } 538 539 540 /****************************************************************************** 541 * 542 * FUNCTION: AcpiHwEnableAllRuntimeGpes 543 * 544 * PARAMETERS: None 545 * 546 * RETURN: Status 547 * 548 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 549 * 550 ******************************************************************************/ 551 552 ACPI_STATUS 553 AcpiHwEnableAllRuntimeGpes ( 554 void) 555 { 556 ACPI_STATUS Status; 557 558 559 ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes); 560 561 562 Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL); 563 return_ACPI_STATUS (Status); 564 } 565 566 567 /****************************************************************************** 568 * 569 * FUNCTION: AcpiHwEnableAllWakeupGpes 570 * 571 * PARAMETERS: None 572 * 573 * RETURN: Status 574 * 575 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks 576 * 577 ******************************************************************************/ 578 579 ACPI_STATUS 580 AcpiHwEnableAllWakeupGpes ( 581 void) 582 { 583 ACPI_STATUS Status; 584 585 586 ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes); 587 588 589 Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL); 590 return_ACPI_STATUS (Status); 591 } 592 593 #endif /* !ACPI_REDUCED_HARDWARE */ 594