1114239Snjl/****************************************************************************** 2114239Snjl * 3114239Snjl * Module Name: evgpeblk - GPE block creation and initialization. 4114239Snjl * 5114239Snjl *****************************************************************************/ 6114239Snjl 7217365Sjkim/* 8281075Sdim * Copyright (C) 2000 - 2015, Intel Corp. 9114239Snjl * All rights reserved. 10114239Snjl * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25114239Snjl * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29114239Snjl * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43114239Snjl 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46193341Sjkim#include <contrib/dev/acpica/include/acevents.h> 47193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 48114239Snjl 49114239Snjl#define _COMPONENT ACPI_EVENTS 50117521Snjl ACPI_MODULE_NAME ("evgpeblk") 51114239Snjl 52231844Sjkim#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 53231844Sjkim 54151937Sjkim/* Local prototypes */ 55114239Snjl 56151937Sjkimstatic ACPI_STATUS 57151937SjkimAcpiEvInstallGpeBlock ( 58151937Sjkim ACPI_GPE_BLOCK_INFO *GpeBlock, 59151937Sjkim UINT32 InterruptNumber); 60151937Sjkim 61151937Sjkimstatic ACPI_STATUS 62151937SjkimAcpiEvCreateGpeInfoBlocks ( 63151937Sjkim ACPI_GPE_BLOCK_INFO *GpeBlock); 64151937Sjkim 65151937Sjkim 66114239Snjl/******************************************************************************* 67114239Snjl * 68114239Snjl * FUNCTION: AcpiEvInstallGpeBlock 69114239Snjl * 70193267Sjkim * PARAMETERS: GpeBlock - New GPE block 71193267Sjkim * InterruptNumber - Xrupt to be associated with this 72193267Sjkim * GPE block 73114239Snjl * 74114239Snjl * RETURN: Status 75114239Snjl * 76114239Snjl * DESCRIPTION: Install new GPE block with mutex support 77114239Snjl * 78114239Snjl ******************************************************************************/ 79114239Snjl 80117521Snjlstatic ACPI_STATUS 81114239SnjlAcpiEvInstallGpeBlock ( 82117521Snjl ACPI_GPE_BLOCK_INFO *GpeBlock, 83151937Sjkim UINT32 InterruptNumber) 84114239Snjl{ 85114239Snjl ACPI_GPE_BLOCK_INFO *NextGpeBlock; 86117521Snjl ACPI_GPE_XRUPT_INFO *GpeXruptBlock; 87114239Snjl ACPI_STATUS Status; 88167802Sjkim ACPI_CPU_FLAGS Flags; 89114239Snjl 90114239Snjl 91167802Sjkim ACPI_FUNCTION_TRACE (EvInstallGpeBlock); 92117521Snjl 93117521Snjl 94114239Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 95114239Snjl if (ACPI_FAILURE (Status)) 96114239Snjl { 97117521Snjl return_ACPI_STATUS (Status); 98114239Snjl } 99114239Snjl 100281075Sdim Status = AcpiEvGetGpeXruptBlock (InterruptNumber, &GpeXruptBlock); 101281075Sdim if (ACPI_FAILURE (Status)) 102117521Snjl { 103117521Snjl goto UnlockAndExit; 104117521Snjl } 105114239Snjl 106151937Sjkim /* Install the new block at the end of the list with lock */ 107117521Snjl 108151937Sjkim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 109117521Snjl if (GpeXruptBlock->GpeBlockListHead) 110114239Snjl { 111117521Snjl NextGpeBlock = GpeXruptBlock->GpeBlockListHead; 112114239Snjl while (NextGpeBlock->Next) 113114239Snjl { 114114239Snjl NextGpeBlock = NextGpeBlock->Next; 115114239Snjl } 116114239Snjl 117114239Snjl NextGpeBlock->Next = GpeBlock; 118114239Snjl GpeBlock->Previous = NextGpeBlock; 119114239Snjl } 120114239Snjl else 121114239Snjl { 122117521Snjl GpeXruptBlock->GpeBlockListHead = GpeBlock; 123114239Snjl } 124114239Snjl 125117521Snjl GpeBlock->XruptBlock = GpeXruptBlock; 126151937Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 127117521Snjl 128167802Sjkim 129117521SnjlUnlockAndExit: 130281075Sdim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 131117521Snjl return_ACPI_STATUS (Status); 132114239Snjl} 133114239Snjl 134114239Snjl 135114239Snjl/******************************************************************************* 136114239Snjl * 137117521Snjl * FUNCTION: AcpiEvDeleteGpeBlock 138117521Snjl * 139193267Sjkim * PARAMETERS: GpeBlock - Existing GPE block 140117521Snjl * 141117521Snjl * RETURN: Status 142117521Snjl * 143123315Snjl * DESCRIPTION: Remove a GPE block 144117521Snjl * 145117521Snjl ******************************************************************************/ 146117521Snjl 147117521SnjlACPI_STATUS 148117521SnjlAcpiEvDeleteGpeBlock ( 149117521Snjl ACPI_GPE_BLOCK_INFO *GpeBlock) 150117521Snjl{ 151117521Snjl ACPI_STATUS Status; 152167802Sjkim ACPI_CPU_FLAGS Flags; 153117521Snjl 154117521Snjl 155167802Sjkim ACPI_FUNCTION_TRACE (EvInstallGpeBlock); 156117521Snjl 157117521Snjl 158117521Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 159117521Snjl if (ACPI_FAILURE (Status)) 160117521Snjl { 161117521Snjl return_ACPI_STATUS (Status); 162117521Snjl } 163117521Snjl 164117521Snjl /* Disable all GPEs in this block */ 165117521Snjl 166193267Sjkim Status = AcpiHwDisableGpeBlock (GpeBlock->XruptBlock, GpeBlock, NULL); 167117521Snjl 168117521Snjl if (!GpeBlock->Previous && !GpeBlock->Next) 169117521Snjl { 170117521Snjl /* This is the last GpeBlock on this interrupt */ 171117521Snjl 172117521Snjl Status = AcpiEvDeleteGpeXrupt (GpeBlock->XruptBlock); 173117521Snjl if (ACPI_FAILURE (Status)) 174117521Snjl { 175117521Snjl goto UnlockAndExit; 176117521Snjl } 177117521Snjl } 178117521Snjl else 179117521Snjl { 180117521Snjl /* Remove the block on this interrupt with lock */ 181117521Snjl 182151937Sjkim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 183117521Snjl if (GpeBlock->Previous) 184117521Snjl { 185117521Snjl GpeBlock->Previous->Next = GpeBlock->Next; 186117521Snjl } 187117521Snjl else 188117521Snjl { 189117521Snjl GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next; 190117521Snjl } 191117521Snjl 192117521Snjl if (GpeBlock->Next) 193117521Snjl { 194117521Snjl GpeBlock->Next->Previous = GpeBlock->Previous; 195117521Snjl } 196151937Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 197117521Snjl } 198117521Snjl 199206117Sjkim AcpiCurrentGpeCount -= GpeBlock->GpeCount; 200193267Sjkim 201117521Snjl /* Free the GpeBlock */ 202117521Snjl 203167802Sjkim ACPI_FREE (GpeBlock->RegisterInfo); 204167802Sjkim ACPI_FREE (GpeBlock->EventInfo); 205167802Sjkim ACPI_FREE (GpeBlock); 206117521Snjl 207117521SnjlUnlockAndExit: 208117521Snjl Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 209117521Snjl return_ACPI_STATUS (Status); 210117521Snjl} 211117521Snjl 212117521Snjl 213117521Snjl/******************************************************************************* 214117521Snjl * 215114239Snjl * FUNCTION: AcpiEvCreateGpeInfoBlocks 216114239Snjl * 217114239Snjl * PARAMETERS: GpeBlock - New GPE block 218114239Snjl * 219114239Snjl * RETURN: Status 220114239Snjl * 221114239Snjl * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block 222114239Snjl * 223114239Snjl ******************************************************************************/ 224114239Snjl 225117521Snjlstatic ACPI_STATUS 226114239SnjlAcpiEvCreateGpeInfoBlocks ( 227114239Snjl ACPI_GPE_BLOCK_INFO *GpeBlock) 228114239Snjl{ 229114239Snjl ACPI_GPE_REGISTER_INFO *GpeRegisterInfo = NULL; 230114239Snjl ACPI_GPE_EVENT_INFO *GpeEventInfo = NULL; 231114239Snjl ACPI_GPE_EVENT_INFO *ThisEvent; 232114239Snjl ACPI_GPE_REGISTER_INFO *ThisRegister; 233193267Sjkim UINT32 i; 234193267Sjkim UINT32 j; 235114239Snjl ACPI_STATUS Status; 236114239Snjl 237114239Snjl 238167802Sjkim ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks); 239114239Snjl 240114239Snjl 241114239Snjl /* Allocate the GPE register information block */ 242114239Snjl 243167802Sjkim GpeRegisterInfo = ACPI_ALLOCATE_ZEROED ( 244206117Sjkim (ACPI_SIZE) GpeBlock->RegisterCount * 245206117Sjkim sizeof (ACPI_GPE_REGISTER_INFO)); 246114239Snjl if (!GpeRegisterInfo) 247114239Snjl { 248167802Sjkim ACPI_ERROR ((AE_INFO, 249167802Sjkim "Could not allocate the GpeRegisterInfo table")); 250114239Snjl return_ACPI_STATUS (AE_NO_MEMORY); 251114239Snjl } 252114239Snjl 253114239Snjl /* 254167802Sjkim * Allocate the GPE EventInfo block. There are eight distinct GPEs 255167802Sjkim * per register. Initialization to zeros is sufficient. 256114239Snjl */ 257206117Sjkim GpeEventInfo = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) GpeBlock->GpeCount * 258206117Sjkim sizeof (ACPI_GPE_EVENT_INFO)); 259114239Snjl if (!GpeEventInfo) 260114239Snjl { 261167802Sjkim ACPI_ERROR ((AE_INFO, 262167802Sjkim "Could not allocate the GpeEventInfo table")); 263114239Snjl Status = AE_NO_MEMORY; 264114239Snjl goto ErrorExit; 265114239Snjl } 266114239Snjl 267117521Snjl /* Save the new Info arrays in the GPE block */ 268117521Snjl 269117521Snjl GpeBlock->RegisterInfo = GpeRegisterInfo; 270117521Snjl GpeBlock->EventInfo = GpeEventInfo; 271117521Snjl 272114239Snjl /* 273167802Sjkim * Initialize the GPE Register and Event structures. A goal of these 274193267Sjkim * tables is to hide the fact that there are two separate GPE register 275193267Sjkim * sets in a given GPE hardware block, the status registers occupy the 276193267Sjkim * first half, and the enable registers occupy the second half. 277114239Snjl */ 278114239Snjl ThisRegister = GpeRegisterInfo; 279114239Snjl ThisEvent = GpeEventInfo; 280114239Snjl 281114239Snjl for (i = 0; i < GpeBlock->RegisterCount; i++) 282114239Snjl { 283114239Snjl /* Init the RegisterInfo for this GPE register (8 GPEs) */ 284114239Snjl 285281075Sdim ThisRegister->BaseGpeNumber = (UINT16) 286281075Sdim (GpeBlock->BlockBaseNumber + (i * ACPI_GPE_REGISTER_WIDTH)); 287114239Snjl 288167802Sjkim ThisRegister->StatusAddress.Address = 289281075Sdim GpeBlock->Address + i; 290114239Snjl 291167802Sjkim ThisRegister->EnableAddress.Address = 292281075Sdim GpeBlock->Address + i + GpeBlock->RegisterCount; 293114239Snjl 294281075Sdim ThisRegister->StatusAddress.SpaceId = GpeBlock->SpaceId; 295281075Sdim ThisRegister->EnableAddress.SpaceId = GpeBlock->SpaceId; 296167802Sjkim ThisRegister->StatusAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; 297167802Sjkim ThisRegister->EnableAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; 298193267Sjkim ThisRegister->StatusAddress.BitOffset = 0; 299193267Sjkim ThisRegister->EnableAddress.BitOffset = 0; 300114239Snjl 301114239Snjl /* Init the EventInfo for each GPE within this register */ 302114239Snjl 303114239Snjl for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 304114239Snjl { 305167802Sjkim ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j); 306114239Snjl ThisEvent->RegisterInfo = ThisRegister; 307114239Snjl ThisEvent++; 308114239Snjl } 309114239Snjl 310167802Sjkim /* Disable all GPEs within this register */ 311167802Sjkim 312197104Sjkim Status = AcpiHwWrite (0x00, &ThisRegister->EnableAddress); 313114239Snjl if (ACPI_FAILURE (Status)) 314114239Snjl { 315114239Snjl goto ErrorExit; 316114239Snjl } 317114239Snjl 318167802Sjkim /* Clear any pending GPE events within this register */ 319167802Sjkim 320197104Sjkim Status = AcpiHwWrite (0xFF, &ThisRegister->StatusAddress); 321114239Snjl if (ACPI_FAILURE (Status)) 322114239Snjl { 323114239Snjl goto ErrorExit; 324114239Snjl } 325114239Snjl 326114239Snjl ThisRegister++; 327114239Snjl } 328114239Snjl 329114239Snjl return_ACPI_STATUS (AE_OK); 330114239Snjl 331114239Snjl 332114239SnjlErrorExit: 333114239Snjl if (GpeRegisterInfo) 334114239Snjl { 335167802Sjkim ACPI_FREE (GpeRegisterInfo); 336114239Snjl } 337114239Snjl if (GpeEventInfo) 338114239Snjl { 339167802Sjkim ACPI_FREE (GpeEventInfo); 340114239Snjl } 341114239Snjl 342117521Snjl return_ACPI_STATUS (Status); 343114239Snjl} 344114239Snjl 345114239Snjl 346114239Snjl/******************************************************************************* 347114239Snjl * 348114239Snjl * FUNCTION: AcpiEvCreateGpeBlock 349114239Snjl * 350117521Snjl * PARAMETERS: GpeDevice - Handle to the parent GPE block 351117521Snjl * GpeBlockAddress - Address and SpaceID 352117521Snjl * RegisterCount - Number of GPE register pairs in the block 353117521Snjl * GpeBlockBaseNumber - Starting GPE number for the block 354151937Sjkim * InterruptNumber - H/W interrupt for the block 355117521Snjl * ReturnGpeBlock - Where the new block descriptor is returned 356114239Snjl * 357114239Snjl * RETURN: Status 358114239Snjl * 359167802Sjkim * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within 360167802Sjkim * the block are disabled at exit. 361167802Sjkim * Note: Assumes namespace is locked. 362114239Snjl * 363114239Snjl ******************************************************************************/ 364114239Snjl 365114239SnjlACPI_STATUS 366114239SnjlAcpiEvCreateGpeBlock ( 367117521Snjl ACPI_NAMESPACE_NODE *GpeDevice, 368281075Sdim UINT64 Address, 369281075Sdim UINT8 SpaceId, 370114239Snjl UINT32 RegisterCount, 371281075Sdim UINT16 GpeBlockBaseNumber, 372151937Sjkim UINT32 InterruptNumber, 373117521Snjl ACPI_GPE_BLOCK_INFO **ReturnGpeBlock) 374114239Snjl{ 375167802Sjkim ACPI_STATUS Status; 376114239Snjl ACPI_GPE_BLOCK_INFO *GpeBlock; 377207344Sjkim ACPI_GPE_WALK_INFO WalkInfo; 378114239Snjl 379129684Snjl 380167802Sjkim ACPI_FUNCTION_TRACE (EvCreateGpeBlock); 381114239Snjl 382114239Snjl 383114239Snjl if (!RegisterCount) 384114239Snjl { 385114239Snjl return_ACPI_STATUS (AE_OK); 386114239Snjl } 387114239Snjl 388114239Snjl /* Allocate a new GPE block */ 389114239Snjl 390167802Sjkim GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO)); 391114239Snjl if (!GpeBlock) 392114239Snjl { 393114239Snjl return_ACPI_STATUS (AE_NO_MEMORY); 394114239Snjl } 395114239Snjl 396114239Snjl /* Initialize the new GPE block */ 397114239Snjl 398281075Sdim GpeBlock->Address = Address; 399281075Sdim GpeBlock->SpaceId = SpaceId; 400167802Sjkim GpeBlock->Node = GpeDevice; 401206117Sjkim GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH); 402216471Sjkim GpeBlock->Initialized = FALSE; 403167802Sjkim GpeBlock->RegisterCount = RegisterCount; 404114239Snjl GpeBlock->BlockBaseNumber = GpeBlockBaseNumber; 405114239Snjl 406167802Sjkim /* 407167802Sjkim * Create the RegisterInfo and EventInfo sub-structures 408167802Sjkim * Note: disables and clears all GPEs in the block 409167802Sjkim */ 410114239Snjl Status = AcpiEvCreateGpeInfoBlocks (GpeBlock); 411114239Snjl if (ACPI_FAILURE (Status)) 412114239Snjl { 413167802Sjkim ACPI_FREE (GpeBlock); 414114239Snjl return_ACPI_STATUS (Status); 415114239Snjl } 416114239Snjl 417167802Sjkim /* Install the new block in the global lists */ 418114239Snjl 419151937Sjkim Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber); 420114239Snjl if (ACPI_FAILURE (Status)) 421114239Snjl { 422250838Sjkim ACPI_FREE (GpeBlock->RegisterInfo); 423250838Sjkim ACPI_FREE (GpeBlock->EventInfo); 424167802Sjkim ACPI_FREE (GpeBlock); 425114239Snjl return_ACPI_STATUS (Status); 426114239Snjl } 427114239Snjl 428216471Sjkim AcpiGbl_AllGpesInitialized = FALSE; 429216471Sjkim 430207344Sjkim /* Find all GPE methods (_Lxx or_Exx) for this block */ 431114239Snjl 432207344Sjkim WalkInfo.GpeBlock = GpeBlock; 433207344Sjkim WalkInfo.GpeDevice = GpeDevice; 434207344Sjkim WalkInfo.ExecuteByOwnerId = FALSE; 435207344Sjkim 436117521Snjl Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice, 437167802Sjkim ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, 438207344Sjkim AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL); 439114239Snjl 440167802Sjkim /* Return the new block */ 441167802Sjkim 442167802Sjkim if (ReturnGpeBlock) 443167802Sjkim { 444167802Sjkim (*ReturnGpeBlock) = GpeBlock; 445167802Sjkim } 446167802Sjkim 447245582Sjkim ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, 448281075Sdim " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n", 449167802Sjkim (UINT32) GpeBlock->BlockBaseNumber, 450206117Sjkim (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)), 451281075Sdim GpeDevice->Name.Ascii, GpeBlock->RegisterCount, InterruptNumber, 452281075Sdim InterruptNumber == AcpiGbl_FADT.SciInterrupt ? " (SCI)" : "")); 453167802Sjkim 454193267Sjkim /* Update global count of currently available GPEs */ 455193267Sjkim 456206117Sjkim AcpiCurrentGpeCount += GpeBlock->GpeCount; 457167802Sjkim return_ACPI_STATUS (AE_OK); 458167802Sjkim} 459167802Sjkim 460167802Sjkim 461167802Sjkim/******************************************************************************* 462167802Sjkim * 463167802Sjkim * FUNCTION: AcpiEvInitializeGpeBlock 464167802Sjkim * 465216471Sjkim * PARAMETERS: ACPI_GPE_CALLBACK 466167802Sjkim * 467167802Sjkim * RETURN: Status 468167802Sjkim * 469216471Sjkim * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have 470216471Sjkim * associated methods. 471167802Sjkim * Note: Assumes namespace is locked. 472167802Sjkim * 473167802Sjkim ******************************************************************************/ 474167802Sjkim 475167802SjkimACPI_STATUS 476167802SjkimAcpiEvInitializeGpeBlock ( 477216471Sjkim ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 478216471Sjkim ACPI_GPE_BLOCK_INFO *GpeBlock, 479216471Sjkim void *Ignored) 480167802Sjkim{ 481167802Sjkim ACPI_STATUS Status; 482167802Sjkim ACPI_GPE_EVENT_INFO *GpeEventInfo; 483167802Sjkim UINT32 GpeEnabledCount; 484206117Sjkim UINT32 GpeIndex; 485193267Sjkim UINT32 i; 486193267Sjkim UINT32 j; 487167802Sjkim 488167802Sjkim 489167802Sjkim ACPI_FUNCTION_TRACE (EvInitializeGpeBlock); 490167802Sjkim 491167802Sjkim 492128212Snjl /* 493216471Sjkim * Ignore a null GPE block (e.g., if no GPE block 1 exists), and 494216471Sjkim * any GPE blocks that have been initialized already. 495128212Snjl */ 496216471Sjkim if (!GpeBlock || GpeBlock->Initialized) 497128212Snjl { 498216471Sjkim return_ACPI_STATUS (AE_OK); 499128212Snjl } 500128212Snjl 501129684Snjl /* 502216471Sjkim * Enable all GPEs that have a corresponding method and have the 503216471Sjkim * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block 504216471Sjkim * must be enabled via the acpi_enable_gpe() interface. 505128212Snjl */ 506128212Snjl GpeEnabledCount = 0; 507128212Snjl 508128212Snjl for (i = 0; i < GpeBlock->RegisterCount; i++) 509128212Snjl { 510206117Sjkim for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 511128212Snjl { 512128212Snjl /* Get the info block for this particular GPE */ 513128212Snjl 514206117Sjkim GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j; 515206117Sjkim GpeEventInfo = &GpeBlock->EventInfo[GpeIndex]; 516129684Snjl 517209746Sjkim /* 518216471Sjkim * Ignore GPEs that have no corresponding _Lxx/_Exx method 519216471Sjkim * and GPEs that are used to wake the system 520209746Sjkim */ 521281075Sdim if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_NONE) || 522281075Sdim (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_HANDLER) || 523281075Sdim (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_RAW_HANDLER) || 524216471Sjkim (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 525209746Sjkim { 526206117Sjkim continue; 527128212Snjl } 528206117Sjkim 529216471Sjkim Status = AcpiEvAddGpeReference (GpeEventInfo); 530206117Sjkim if (ACPI_FAILURE (Status)) 531206117Sjkim { 532206117Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 533216471Sjkim "Could not enable GPE 0x%02X", 534216471Sjkim GpeIndex + GpeBlock->BlockBaseNumber)); 535206117Sjkim continue; 536206117Sjkim } 537206117Sjkim 538206117Sjkim GpeEnabledCount++; 539128212Snjl } 540128212Snjl } 541128212Snjl 542216471Sjkim if (GpeEnabledCount) 543117521Snjl { 544245582Sjkim ACPI_INFO ((AE_INFO, 545245582Sjkim "Enabled %u GPEs in block %02X to %02X", GpeEnabledCount, 546245582Sjkim (UINT32) GpeBlock->BlockBaseNumber, 547245582Sjkim (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)))); 548114239Snjl } 549114239Snjl 550216471Sjkim GpeBlock->Initialized = TRUE; 551114239Snjl return_ACPI_STATUS (AE_OK); 552114239Snjl} 553114239Snjl 554231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */ 555