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