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