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