1 2 /****************************************************************************** 3 * 4 * Module Name: hwgpe - Low level GPE enable/disable/clear functions 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2012, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #include <contrib/dev/acpica/include/acpi.h> 46 #include <contrib/dev/acpica/include/accommon.h> 47 #include <contrib/dev/acpica/include/acevents.h> 48 49 #define _COMPONENT ACPI_HARDWARE 50 ACPI_MODULE_NAME ("hwgpe") 51 52 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 53 54 /* Local prototypes */ 55 56 static ACPI_STATUS 57 AcpiHwEnableWakeupGpeBlock ( 58 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 59 ACPI_GPE_BLOCK_INFO *GpeBlock, 60 void *Context); 61 62 63 /****************************************************************************** 64 * 65 * FUNCTION: AcpiHwGetGpeRegisterBit 66 * 67 * PARAMETERS: GpeEventInfo - Info block for the GPE 68 * GpeRegisterInfo - Info block for the GPE register 69 * 70 * RETURN: Register mask with a one in the GPE bit position 71 * 72 * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the 73 * correct position for the input GPE. 74 * 75 ******************************************************************************/ 76 77 UINT32 78 AcpiHwGetGpeRegisterBit ( 79 ACPI_GPE_EVENT_INFO *GpeEventInfo, 80 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo) 81 { 82 83 return ((UINT32) 1 << 84 (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber)); 85 } 86 87 88 /****************************************************************************** 89 * 90 * FUNCTION: AcpiHwLowSetGpe 91 * 92 * PARAMETERS: GpeEventInfo - Info block for the GPE to be disabled 93 * Action - Enable or disable 94 * 95 * RETURN: Status 96 * 97 * DESCRIPTION: Enable or disable a single GPE in the parent enable register. 98 * 99 ******************************************************************************/ 100 101 ACPI_STATUS 102 AcpiHwLowSetGpe ( 103 ACPI_GPE_EVENT_INFO *GpeEventInfo, 104 UINT32 Action) 105 { 106 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 107 ACPI_STATUS Status; 108 UINT32 EnableMask; 109 UINT32 RegisterBit; 110 111 112 ACPI_FUNCTION_ENTRY (); 113 114 115 /* Get the info block for the entire GPE register */ 116 117 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 118 if (!GpeRegisterInfo) 119 { 120 return (AE_NOT_EXIST); 121 } 122 123 /* Get current value of the enable register that contains this GPE */ 124 125 Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress); 126 if (ACPI_FAILURE (Status)) 127 { 128 return (Status); 129 } 130 131 /* Set or clear just the bit that corresponds to this GPE */ 132 133 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); 134 switch (Action) 135 { 136 case ACPI_GPE_CONDITIONAL_ENABLE: 137 138 /* Only enable if the EnableForRun bit is set */ 139 140 if (!(RegisterBit & GpeRegisterInfo->EnableForRun)) 141 { 142 return (AE_BAD_PARAMETER); 143 } 144 145 /*lint -fallthrough */ 146 147 case ACPI_GPE_ENABLE: 148 ACPI_SET_BIT (EnableMask, RegisterBit); 149 break; 150 151 case ACPI_GPE_DISABLE: 152 ACPI_CLEAR_BIT (EnableMask, RegisterBit); 153 break; 154 155 default: 156 ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u\n", 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, GpeRegisterInfo); 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 /* Get the info block for the entire GPE register */ 245 246 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 247 248 /* Get the register bitmask for this GPE */ 249 250 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); 251 252 /* GPE currently enabled? (enabled for runtime?) */ 253 254 if (RegisterBit & GpeRegisterInfo->EnableForRun) 255 { 256 LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED; 257 } 258 259 /* GPE enabled for wake? */ 260 261 if (RegisterBit & GpeRegisterInfo->EnableForWake) 262 { 263 LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED; 264 } 265 266 /* GPE currently active (status bit == 1)? */ 267 268 Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress); 269 if (ACPI_FAILURE (Status)) 270 { 271 return (Status); 272 } 273 274 if (RegisterBit & InByte) 275 { 276 LocalEventStatus |= ACPI_EVENT_FLAG_SET; 277 } 278 279 /* Set return value */ 280 281 (*EventStatus) = LocalEventStatus; 282 return (AE_OK); 283 } 284 285 286 /****************************************************************************** 287 * 288 * FUNCTION: AcpiHwDisableGpeBlock 289 * 290 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 291 * GpeBlock - Gpe Block info 292 * 293 * RETURN: Status 294 * 295 * DESCRIPTION: Disable all GPEs within a single GPE block 296 * 297 ******************************************************************************/ 298 299 ACPI_STATUS 300 AcpiHwDisableGpeBlock ( 301 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 302 ACPI_GPE_BLOCK_INFO *GpeBlock, 303 void *Context) 304 { 305 UINT32 i; 306 ACPI_STATUS Status; 307 308 309 /* Examine each GPE Register within the block */ 310 311 for (i = 0; i < GpeBlock->RegisterCount; i++) 312 { 313 /* Disable all GPEs in this register */ 314 315 Status = AcpiHwWrite (0x00, &GpeBlock->RegisterInfo[i].EnableAddress); 316 if (ACPI_FAILURE (Status)) 317 { 318 return (Status); 319 } 320 } 321 322 return (AE_OK); 323 } 324 325 326 /****************************************************************************** 327 * 328 * FUNCTION: AcpiHwClearGpeBlock 329 * 330 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 331 * GpeBlock - Gpe Block info 332 * 333 * RETURN: Status 334 * 335 * DESCRIPTION: Clear status bits for all GPEs within a single GPE block 336 * 337 ******************************************************************************/ 338 339 ACPI_STATUS 340 AcpiHwClearGpeBlock ( 341 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 342 ACPI_GPE_BLOCK_INFO *GpeBlock, 343 void *Context) 344 { 345 UINT32 i; 346 ACPI_STATUS Status; 347 348 349 /* Examine each GPE Register within the block */ 350 351 for (i = 0; i < GpeBlock->RegisterCount; i++) 352 { 353 /* Clear status on all GPEs in this register */ 354 355 Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress); 356 if (ACPI_FAILURE (Status)) 357 { 358 return (Status); 359 } 360 } 361 362 return (AE_OK); 363 } 364 365 366 /****************************************************************************** 367 * 368 * FUNCTION: AcpiHwEnableRuntimeGpeBlock 369 * 370 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 371 * GpeBlock - Gpe Block info 372 * 373 * RETURN: Status 374 * 375 * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes 376 * combination wake/run GPEs. 377 * 378 ******************************************************************************/ 379 380 ACPI_STATUS 381 AcpiHwEnableRuntimeGpeBlock ( 382 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 383 ACPI_GPE_BLOCK_INFO *GpeBlock, 384 void *Context) 385 { 386 UINT32 i; 387 ACPI_STATUS Status; 388 389 390 /* NOTE: assumes that all GPEs are currently disabled */ 391 392 /* Examine each GPE Register within the block */ 393 394 for (i = 0; i < GpeBlock->RegisterCount; i++) 395 { 396 if (!GpeBlock->RegisterInfo[i].EnableForRun) 397 { 398 continue; 399 } 400 401 /* Enable all "runtime" GPEs in this register */ 402 403 Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun, 404 &GpeBlock->RegisterInfo[i].EnableAddress); 405 if (ACPI_FAILURE (Status)) 406 { 407 return (Status); 408 } 409 } 410 411 return (AE_OK); 412 } 413 414 415 /****************************************************************************** 416 * 417 * FUNCTION: AcpiHwEnableWakeupGpeBlock 418 * 419 * PARAMETERS: GpeXruptInfo - GPE Interrupt info 420 * GpeBlock - Gpe Block info 421 * 422 * RETURN: Status 423 * 424 * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes 425 * combination wake/run GPEs. 426 * 427 ******************************************************************************/ 428 429 static ACPI_STATUS 430 AcpiHwEnableWakeupGpeBlock ( 431 ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 432 ACPI_GPE_BLOCK_INFO *GpeBlock, 433 void *Context) 434 { 435 UINT32 i; 436 ACPI_STATUS Status; 437 438 439 /* Examine each GPE Register within the block */ 440 441 for (i = 0; i < GpeBlock->RegisterCount; i++) 442 { 443 if (!GpeBlock->RegisterInfo[i].EnableForWake) 444 { 445 continue; 446 } 447 448 /* Enable all "wake" GPEs in this register */ 449 450 Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake, 451 &GpeBlock->RegisterInfo[i].EnableAddress); 452 if (ACPI_FAILURE (Status)) 453 { 454 return (Status); 455 } 456 } 457 458 return (AE_OK); 459 } 460 461 462 /****************************************************************************** 463 * 464 * FUNCTION: AcpiHwDisableAllGpes 465 * 466 * PARAMETERS: None 467 * 468 * RETURN: Status 469 * 470 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 471 * 472 ******************************************************************************/ 473 474 ACPI_STATUS 475 AcpiHwDisableAllGpes ( 476 void) 477 { 478 ACPI_STATUS Status; 479 480 481 ACPI_FUNCTION_TRACE (HwDisableAllGpes); 482 483 484 Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL); 485 Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); 486 return_ACPI_STATUS (Status); 487 } 488 489 490 /****************************************************************************** 491 * 492 * FUNCTION: AcpiHwEnableAllRuntimeGpes 493 * 494 * PARAMETERS: None 495 * 496 * RETURN: Status 497 * 498 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 499 * 500 ******************************************************************************/ 501 502 ACPI_STATUS 503 AcpiHwEnableAllRuntimeGpes ( 504 void) 505 { 506 ACPI_STATUS Status; 507 508 509 ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes); 510 511 512 Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL); 513 return_ACPI_STATUS (Status); 514 } 515 516 517 /****************************************************************************** 518 * 519 * FUNCTION: AcpiHwEnableAllWakeupGpes 520 * 521 * PARAMETERS: None 522 * 523 * RETURN: Status 524 * 525 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks 526 * 527 ******************************************************************************/ 528 529 ACPI_STATUS 530 AcpiHwEnableAllWakeupGpes ( 531 void) 532 { 533 ACPI_STATUS Status; 534 535 536 ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes); 537 538 539 Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL); 540 return_ACPI_STATUS (Status); 541 } 542 543 #endif /* !ACPI_REDUCED_HARDWARE */ 544