1114239Snjl/****************************************************************************** 2114239Snjl * 3114239Snjl * Module Name: evgpeblk - GPE block creation and initialization. 4114239Snjl * 5114239Snjl *****************************************************************************/ 6114239Snjl 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, 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 } 196306536Sjkim 197151937Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 198117521Snjl } 199117521Snjl 200206117Sjkim AcpiCurrentGpeCount -= GpeBlock->GpeCount; 201193267Sjkim 202117521Snjl /* Free the GpeBlock */ 203117521Snjl 204167802Sjkim ACPI_FREE (GpeBlock->RegisterInfo); 205167802Sjkim ACPI_FREE (GpeBlock->EventInfo); 206167802Sjkim ACPI_FREE (GpeBlock); 207117521Snjl 208117521SnjlUnlockAndExit: 209117521Snjl Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 210117521Snjl return_ACPI_STATUS (Status); 211117521Snjl} 212117521Snjl 213117521Snjl 214117521Snjl/******************************************************************************* 215117521Snjl * 216114239Snjl * FUNCTION: AcpiEvCreateGpeInfoBlocks 217114239Snjl * 218114239Snjl * PARAMETERS: GpeBlock - New GPE block 219114239Snjl * 220114239Snjl * RETURN: Status 221114239Snjl * 222114239Snjl * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block 223114239Snjl * 224114239Snjl ******************************************************************************/ 225114239Snjl 226117521Snjlstatic ACPI_STATUS 227114239SnjlAcpiEvCreateGpeInfoBlocks ( 228114239Snjl ACPI_GPE_BLOCK_INFO *GpeBlock) 229114239Snjl{ 230114239Snjl ACPI_GPE_REGISTER_INFO *GpeRegisterInfo = NULL; 231114239Snjl ACPI_GPE_EVENT_INFO *GpeEventInfo = NULL; 232114239Snjl ACPI_GPE_EVENT_INFO *ThisEvent; 233114239Snjl ACPI_GPE_REGISTER_INFO *ThisRegister; 234193267Sjkim UINT32 i; 235193267Sjkim UINT32 j; 236114239Snjl ACPI_STATUS Status; 237114239Snjl 238114239Snjl 239167802Sjkim ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks); 240114239Snjl 241114239Snjl 242114239Snjl /* Allocate the GPE register information block */ 243114239Snjl 244167802Sjkim GpeRegisterInfo = ACPI_ALLOCATE_ZEROED ( 245306536Sjkim (ACPI_SIZE) GpeBlock->RegisterCount * 246306536Sjkim sizeof (ACPI_GPE_REGISTER_INFO)); 247114239Snjl if (!GpeRegisterInfo) 248114239Snjl { 249167802Sjkim ACPI_ERROR ((AE_INFO, 250167802Sjkim "Could not allocate the GpeRegisterInfo table")); 251114239Snjl return_ACPI_STATUS (AE_NO_MEMORY); 252114239Snjl } 253114239Snjl 254114239Snjl /* 255167802Sjkim * Allocate the GPE EventInfo block. There are eight distinct GPEs 256167802Sjkim * per register. Initialization to zeros is sufficient. 257114239Snjl */ 258206117Sjkim GpeEventInfo = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) GpeBlock->GpeCount * 259306536Sjkim sizeof (ACPI_GPE_EVENT_INFO)); 260114239Snjl if (!GpeEventInfo) 261114239Snjl { 262167802Sjkim ACPI_ERROR ((AE_INFO, 263167802Sjkim "Could not allocate the GpeEventInfo table")); 264114239Snjl Status = AE_NO_MEMORY; 265114239Snjl goto ErrorExit; 266114239Snjl } 267114239Snjl 268117521Snjl /* Save the new Info arrays in the GPE block */ 269117521Snjl 270117521Snjl GpeBlock->RegisterInfo = GpeRegisterInfo; 271306536Sjkim GpeBlock->EventInfo = GpeEventInfo; 272117521Snjl 273114239Snjl /* 274167802Sjkim * Initialize the GPE Register and Event structures. A goal of these 275193267Sjkim * tables is to hide the fact that there are two separate GPE register 276193267Sjkim * sets in a given GPE hardware block, the status registers occupy the 277193267Sjkim * first half, and the enable registers occupy the second half. 278114239Snjl */ 279114239Snjl ThisRegister = GpeRegisterInfo; 280306536Sjkim ThisEvent = GpeEventInfo; 281114239Snjl 282114239Snjl for (i = 0; i < GpeBlock->RegisterCount; i++) 283114239Snjl { 284114239Snjl /* Init the RegisterInfo for this GPE register (8 GPEs) */ 285114239Snjl 286281075Sdim ThisRegister->BaseGpeNumber = (UINT16) 287281075Sdim (GpeBlock->BlockBaseNumber + (i * ACPI_GPE_REGISTER_WIDTH)); 288114239Snjl 289167802Sjkim ThisRegister->StatusAddress.Address = 290281075Sdim GpeBlock->Address + i; 291114239Snjl 292167802Sjkim ThisRegister->EnableAddress.Address = 293281075Sdim GpeBlock->Address + i + GpeBlock->RegisterCount; 294114239Snjl 295281075Sdim ThisRegister->StatusAddress.SpaceId = GpeBlock->SpaceId; 296281075Sdim ThisRegister->EnableAddress.SpaceId = GpeBlock->SpaceId; 297167802Sjkim ThisRegister->StatusAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; 298167802Sjkim ThisRegister->EnableAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; 299193267Sjkim ThisRegister->StatusAddress.BitOffset = 0; 300193267Sjkim ThisRegister->EnableAddress.BitOffset = 0; 301114239Snjl 302114239Snjl /* Init the EventInfo for each GPE within this register */ 303114239Snjl 304114239Snjl for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 305114239Snjl { 306167802Sjkim ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j); 307114239Snjl ThisEvent->RegisterInfo = ThisRegister; 308114239Snjl ThisEvent++; 309114239Snjl } 310114239Snjl 311167802Sjkim /* Disable all GPEs within this register */ 312167802Sjkim 313197104Sjkim Status = AcpiHwWrite (0x00, &ThisRegister->EnableAddress); 314114239Snjl if (ACPI_FAILURE (Status)) 315114239Snjl { 316114239Snjl goto ErrorExit; 317114239Snjl } 318114239Snjl 319167802Sjkim /* Clear any pending GPE events within this register */ 320167802Sjkim 321197104Sjkim Status = AcpiHwWrite (0xFF, &ThisRegister->StatusAddress); 322114239Snjl if (ACPI_FAILURE (Status)) 323114239Snjl { 324114239Snjl goto ErrorExit; 325114239Snjl } 326114239Snjl 327114239Snjl ThisRegister++; 328114239Snjl } 329114239Snjl 330114239Snjl return_ACPI_STATUS (AE_OK); 331114239Snjl 332114239Snjl 333114239SnjlErrorExit: 334114239Snjl if (GpeRegisterInfo) 335114239Snjl { 336167802Sjkim ACPI_FREE (GpeRegisterInfo); 337114239Snjl } 338114239Snjl if (GpeEventInfo) 339114239Snjl { 340167802Sjkim ACPI_FREE (GpeEventInfo); 341114239Snjl } 342114239Snjl 343117521Snjl return_ACPI_STATUS (Status); 344114239Snjl} 345114239Snjl 346114239Snjl 347114239Snjl/******************************************************************************* 348114239Snjl * 349114239Snjl * FUNCTION: AcpiEvCreateGpeBlock 350114239Snjl * 351117521Snjl * PARAMETERS: GpeDevice - Handle to the parent GPE block 352117521Snjl * GpeBlockAddress - Address and SpaceID 353117521Snjl * RegisterCount - Number of GPE register pairs in the block 354117521Snjl * GpeBlockBaseNumber - Starting GPE number for the block 355151937Sjkim * InterruptNumber - H/W interrupt for the block 356117521Snjl * ReturnGpeBlock - Where the new block descriptor is returned 357114239Snjl * 358114239Snjl * RETURN: Status 359114239Snjl * 360167802Sjkim * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within 361167802Sjkim * the block are disabled at exit. 362167802Sjkim * Note: Assumes namespace is locked. 363114239Snjl * 364114239Snjl ******************************************************************************/ 365114239Snjl 366114239SnjlACPI_STATUS 367114239SnjlAcpiEvCreateGpeBlock ( 368117521Snjl ACPI_NAMESPACE_NODE *GpeDevice, 369281075Sdim UINT64 Address, 370281075Sdim UINT8 SpaceId, 371114239Snjl UINT32 RegisterCount, 372281075Sdim UINT16 GpeBlockBaseNumber, 373151937Sjkim UINT32 InterruptNumber, 374117521Snjl ACPI_GPE_BLOCK_INFO **ReturnGpeBlock) 375114239Snjl{ 376167802Sjkim ACPI_STATUS Status; 377114239Snjl ACPI_GPE_BLOCK_INFO *GpeBlock; 378207344Sjkim ACPI_GPE_WALK_INFO WalkInfo; 379114239Snjl 380129684Snjl 381167802Sjkim ACPI_FUNCTION_TRACE (EvCreateGpeBlock); 382114239Snjl 383114239Snjl 384114239Snjl if (!RegisterCount) 385114239Snjl { 386114239Snjl return_ACPI_STATUS (AE_OK); 387114239Snjl } 388114239Snjl 389114239Snjl /* Allocate a new GPE block */ 390114239Snjl 391167802Sjkim GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO)); 392114239Snjl if (!GpeBlock) 393114239Snjl { 394114239Snjl return_ACPI_STATUS (AE_NO_MEMORY); 395114239Snjl } 396114239Snjl 397114239Snjl /* Initialize the new GPE block */ 398114239Snjl 399281075Sdim GpeBlock->Address = Address; 400281075Sdim GpeBlock->SpaceId = SpaceId; 401167802Sjkim GpeBlock->Node = GpeDevice; 402206117Sjkim GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH); 403216471Sjkim GpeBlock->Initialized = FALSE; 404167802Sjkim GpeBlock->RegisterCount = RegisterCount; 405114239Snjl GpeBlock->BlockBaseNumber = GpeBlockBaseNumber; 406114239Snjl 407167802Sjkim /* 408167802Sjkim * Create the RegisterInfo and EventInfo sub-structures 409167802Sjkim * Note: disables and clears all GPEs in the block 410167802Sjkim */ 411114239Snjl Status = AcpiEvCreateGpeInfoBlocks (GpeBlock); 412114239Snjl if (ACPI_FAILURE (Status)) 413114239Snjl { 414167802Sjkim ACPI_FREE (GpeBlock); 415114239Snjl return_ACPI_STATUS (Status); 416114239Snjl } 417114239Snjl 418167802Sjkim /* Install the new block in the global lists */ 419114239Snjl 420151937Sjkim Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber); 421114239Snjl if (ACPI_FAILURE (Status)) 422114239Snjl { 423250838Sjkim ACPI_FREE (GpeBlock->RegisterInfo); 424250838Sjkim ACPI_FREE (GpeBlock->EventInfo); 425167802Sjkim ACPI_FREE (GpeBlock); 426114239Snjl return_ACPI_STATUS (Status); 427114239Snjl } 428114239Snjl 429216471Sjkim AcpiGbl_AllGpesInitialized = FALSE; 430216471Sjkim 431207344Sjkim /* Find all GPE methods (_Lxx or_Exx) for this block */ 432114239Snjl 433207344Sjkim WalkInfo.GpeBlock = GpeBlock; 434207344Sjkim WalkInfo.GpeDevice = GpeDevice; 435207344Sjkim WalkInfo.ExecuteByOwnerId = FALSE; 436207344Sjkim 437117521Snjl Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice, 438306536Sjkim ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, 439306536Sjkim AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL); 440114239Snjl 441167802Sjkim /* Return the new block */ 442167802Sjkim 443167802Sjkim if (ReturnGpeBlock) 444167802Sjkim { 445167802Sjkim (*ReturnGpeBlock) = GpeBlock; 446167802Sjkim } 447167802Sjkim 448245582Sjkim ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, 449281075Sdim " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n", 450167802Sjkim (UINT32) GpeBlock->BlockBaseNumber, 451206117Sjkim (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)), 452281075Sdim GpeDevice->Name.Ascii, GpeBlock->RegisterCount, InterruptNumber, 453281075Sdim InterruptNumber == AcpiGbl_FADT.SciInterrupt ? " (SCI)" : "")); 454167802Sjkim 455193267Sjkim /* Update global count of currently available GPEs */ 456193267Sjkim 457206117Sjkim AcpiCurrentGpeCount += GpeBlock->GpeCount; 458167802Sjkim return_ACPI_STATUS (AE_OK); 459167802Sjkim} 460167802Sjkim 461167802Sjkim 462167802Sjkim/******************************************************************************* 463167802Sjkim * 464167802Sjkim * FUNCTION: AcpiEvInitializeGpeBlock 465167802Sjkim * 466216471Sjkim * PARAMETERS: ACPI_GPE_CALLBACK 467167802Sjkim * 468167802Sjkim * RETURN: Status 469167802Sjkim * 470216471Sjkim * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have 471216471Sjkim * associated methods. 472167802Sjkim * Note: Assumes namespace is locked. 473167802Sjkim * 474167802Sjkim ******************************************************************************/ 475167802Sjkim 476167802SjkimACPI_STATUS 477167802SjkimAcpiEvInitializeGpeBlock ( 478216471Sjkim ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 479216471Sjkim ACPI_GPE_BLOCK_INFO *GpeBlock, 480216471Sjkim void *Ignored) 481167802Sjkim{ 482167802Sjkim ACPI_STATUS Status; 483167802Sjkim ACPI_GPE_EVENT_INFO *GpeEventInfo; 484167802Sjkim UINT32 GpeEnabledCount; 485206117Sjkim UINT32 GpeIndex; 486193267Sjkim UINT32 i; 487193267Sjkim UINT32 j; 488167802Sjkim 489167802Sjkim 490167802Sjkim ACPI_FUNCTION_TRACE (EvInitializeGpeBlock); 491167802Sjkim 492167802Sjkim 493128212Snjl /* 494216471Sjkim * Ignore a null GPE block (e.g., if no GPE block 1 exists), and 495216471Sjkim * any GPE blocks that have been initialized already. 496128212Snjl */ 497216471Sjkim if (!GpeBlock || GpeBlock->Initialized) 498128212Snjl { 499216471Sjkim return_ACPI_STATUS (AE_OK); 500128212Snjl } 501128212Snjl 502129684Snjl /* 503216471Sjkim * Enable all GPEs that have a corresponding method and have the 504216471Sjkim * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block 505216471Sjkim * must be enabled via the acpi_enable_gpe() interface. 506128212Snjl */ 507128212Snjl GpeEnabledCount = 0; 508128212Snjl 509128212Snjl for (i = 0; i < GpeBlock->RegisterCount; i++) 510128212Snjl { 511206117Sjkim for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 512128212Snjl { 513128212Snjl /* Get the info block for this particular GPE */ 514128212Snjl 515206117Sjkim GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j; 516206117Sjkim GpeEventInfo = &GpeBlock->EventInfo[GpeIndex]; 517129684Snjl 518209746Sjkim /* 519216471Sjkim * Ignore GPEs that have no corresponding _Lxx/_Exx method 520216471Sjkim * and GPEs that are used to wake the system 521209746Sjkim */ 522281075Sdim if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_NONE) || 523281075Sdim (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_HANDLER) || 524281075Sdim (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_RAW_HANDLER) || 525216471Sjkim (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 526209746Sjkim { 527206117Sjkim continue; 528128212Snjl } 529206117Sjkim 530216471Sjkim Status = AcpiEvAddGpeReference (GpeEventInfo); 531206117Sjkim if (ACPI_FAILURE (Status)) 532206117Sjkim { 533206117Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 534216471Sjkim "Could not enable GPE 0x%02X", 535216471Sjkim GpeIndex + GpeBlock->BlockBaseNumber)); 536206117Sjkim continue; 537206117Sjkim } 538206117Sjkim 539206117Sjkim GpeEnabledCount++; 540128212Snjl } 541128212Snjl } 542128212Snjl 543216471Sjkim if (GpeEnabledCount) 544117521Snjl { 545306536Sjkim ACPI_INFO (( 546245582Sjkim "Enabled %u GPEs in block %02X to %02X", GpeEnabledCount, 547245582Sjkim (UINT32) GpeBlock->BlockBaseNumber, 548245582Sjkim (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)))); 549114239Snjl } 550114239Snjl 551216471Sjkim GpeBlock->Initialized = TRUE; 552114239Snjl return_ACPI_STATUS (AE_OK); 553114239Snjl} 554114239Snjl 555231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */ 556