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 "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 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 /* 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); 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 */