1*a159c266SJung-uk Kim /****************************************************************************** 2*a159c266SJung-uk Kim * 3*a159c266SJung-uk Kim * Module Name: evgpeblk - GPE block creation and initialization. 4*a159c266SJung-uk Kim * 5*a159c266SJung-uk Kim *****************************************************************************/ 6*a159c266SJung-uk Kim 7*a159c266SJung-uk Kim /* 8*a159c266SJung-uk Kim * Copyright (C) 2000 - 2012, Intel Corp. 9*a159c266SJung-uk Kim * All rights reserved. 10*a159c266SJung-uk Kim * 11*a159c266SJung-uk Kim * Redistribution and use in source and binary forms, with or without 12*a159c266SJung-uk Kim * modification, are permitted provided that the following conditions 13*a159c266SJung-uk Kim * are met: 14*a159c266SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 15*a159c266SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 16*a159c266SJung-uk Kim * without modification. 17*a159c266SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18*a159c266SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 19*a159c266SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 20*a159c266SJung-uk Kim * including a substantially similar Disclaimer requirement for further 21*a159c266SJung-uk Kim * binary redistribution. 22*a159c266SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 23*a159c266SJung-uk Kim * of any contributors may be used to endorse or promote products derived 24*a159c266SJung-uk Kim * from this software without specific prior written permission. 25*a159c266SJung-uk Kim * 26*a159c266SJung-uk Kim * Alternatively, this software may be distributed under the terms of the 27*a159c266SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 28*a159c266SJung-uk Kim * Software Foundation. 29*a159c266SJung-uk Kim * 30*a159c266SJung-uk Kim * NO WARRANTY 31*a159c266SJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32*a159c266SJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33*a159c266SJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34*a159c266SJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35*a159c266SJung-uk Kim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36*a159c266SJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37*a159c266SJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38*a159c266SJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39*a159c266SJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40*a159c266SJung-uk Kim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41*a159c266SJung-uk Kim * POSSIBILITY OF SUCH DAMAGES. 42*a159c266SJung-uk Kim */ 43*a159c266SJung-uk Kim 44*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 45*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 46*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acevents.h> 47*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h> 48*a159c266SJung-uk Kim 49*a159c266SJung-uk Kim #define _COMPONENT ACPI_EVENTS 50*a159c266SJung-uk Kim ACPI_MODULE_NAME ("evgpeblk") 51*a159c266SJung-uk Kim 52*a159c266SJung-uk Kim #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 53*a159c266SJung-uk Kim 54*a159c266SJung-uk Kim /* Local prototypes */ 55*a159c266SJung-uk Kim 56*a159c266SJung-uk Kim static ACPI_STATUS 57*a159c266SJung-uk Kim AcpiEvInstallGpeBlock ( 58*a159c266SJung-uk Kim ACPI_GPE_BLOCK_INFO *GpeBlock, 59*a159c266SJung-uk Kim UINT32 InterruptNumber); 60*a159c266SJung-uk Kim 61*a159c266SJung-uk Kim static ACPI_STATUS 62*a159c266SJung-uk Kim AcpiEvCreateGpeInfoBlocks ( 63*a159c266SJung-uk Kim ACPI_GPE_BLOCK_INFO *GpeBlock); 64*a159c266SJung-uk Kim 65*a159c266SJung-uk Kim 66*a159c266SJung-uk Kim /******************************************************************************* 67*a159c266SJung-uk Kim * 68*a159c266SJung-uk Kim * FUNCTION: AcpiEvInstallGpeBlock 69*a159c266SJung-uk Kim * 70*a159c266SJung-uk Kim * PARAMETERS: GpeBlock - New GPE block 71*a159c266SJung-uk Kim * InterruptNumber - Xrupt to be associated with this 72*a159c266SJung-uk Kim * GPE block 73*a159c266SJung-uk Kim * 74*a159c266SJung-uk Kim * RETURN: Status 75*a159c266SJung-uk Kim * 76*a159c266SJung-uk Kim * DESCRIPTION: Install new GPE block with mutex support 77*a159c266SJung-uk Kim * 78*a159c266SJung-uk Kim ******************************************************************************/ 79*a159c266SJung-uk Kim 80*a159c266SJung-uk Kim static ACPI_STATUS 81*a159c266SJung-uk Kim AcpiEvInstallGpeBlock ( 82*a159c266SJung-uk Kim ACPI_GPE_BLOCK_INFO *GpeBlock, 83*a159c266SJung-uk Kim UINT32 InterruptNumber) 84*a159c266SJung-uk Kim { 85*a159c266SJung-uk Kim ACPI_GPE_BLOCK_INFO *NextGpeBlock; 86*a159c266SJung-uk Kim ACPI_GPE_XRUPT_INFO *GpeXruptBlock; 87*a159c266SJung-uk Kim ACPI_STATUS Status; 88*a159c266SJung-uk Kim ACPI_CPU_FLAGS Flags; 89*a159c266SJung-uk Kim 90*a159c266SJung-uk Kim 91*a159c266SJung-uk Kim ACPI_FUNCTION_TRACE (EvInstallGpeBlock); 92*a159c266SJung-uk Kim 93*a159c266SJung-uk Kim 94*a159c266SJung-uk Kim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 95*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 96*a159c266SJung-uk Kim { 97*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 98*a159c266SJung-uk Kim } 99*a159c266SJung-uk Kim 100*a159c266SJung-uk Kim GpeXruptBlock = AcpiEvGetGpeXruptBlock (InterruptNumber); 101*a159c266SJung-uk Kim if (!GpeXruptBlock) 102*a159c266SJung-uk Kim { 103*a159c266SJung-uk Kim Status = AE_NO_MEMORY; 104*a159c266SJung-uk Kim goto UnlockAndExit; 105*a159c266SJung-uk Kim } 106*a159c266SJung-uk Kim 107*a159c266SJung-uk Kim /* Install the new block at the end of the list with lock */ 108*a159c266SJung-uk Kim 109*a159c266SJung-uk Kim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 110*a159c266SJung-uk Kim if (GpeXruptBlock->GpeBlockListHead) 111*a159c266SJung-uk Kim { 112*a159c266SJung-uk Kim NextGpeBlock = GpeXruptBlock->GpeBlockListHead; 113*a159c266SJung-uk Kim while (NextGpeBlock->Next) 114*a159c266SJung-uk Kim { 115*a159c266SJung-uk Kim NextGpeBlock = NextGpeBlock->Next; 116*a159c266SJung-uk Kim } 117*a159c266SJung-uk Kim 118*a159c266SJung-uk Kim NextGpeBlock->Next = GpeBlock; 119*a159c266SJung-uk Kim GpeBlock->Previous = NextGpeBlock; 120*a159c266SJung-uk Kim } 121*a159c266SJung-uk Kim else 122*a159c266SJung-uk Kim { 123*a159c266SJung-uk Kim GpeXruptBlock->GpeBlockListHead = GpeBlock; 124*a159c266SJung-uk Kim } 125*a159c266SJung-uk Kim 126*a159c266SJung-uk Kim GpeBlock->XruptBlock = GpeXruptBlock; 127*a159c266SJung-uk Kim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 128*a159c266SJung-uk Kim 129*a159c266SJung-uk Kim 130*a159c266SJung-uk Kim UnlockAndExit: 131*a159c266SJung-uk Kim Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 132*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 133*a159c266SJung-uk Kim } 134*a159c266SJung-uk Kim 135*a159c266SJung-uk Kim 136*a159c266SJung-uk Kim /******************************************************************************* 137*a159c266SJung-uk Kim * 138*a159c266SJung-uk Kim * FUNCTION: AcpiEvDeleteGpeBlock 139*a159c266SJung-uk Kim * 140*a159c266SJung-uk Kim * PARAMETERS: GpeBlock - Existing GPE block 141*a159c266SJung-uk Kim * 142*a159c266SJung-uk Kim * RETURN: Status 143*a159c266SJung-uk Kim * 144*a159c266SJung-uk Kim * DESCRIPTION: Remove a GPE block 145*a159c266SJung-uk Kim * 146*a159c266SJung-uk Kim ******************************************************************************/ 147*a159c266SJung-uk Kim 148*a159c266SJung-uk Kim ACPI_STATUS 149*a159c266SJung-uk Kim AcpiEvDeleteGpeBlock ( 150*a159c266SJung-uk Kim ACPI_GPE_BLOCK_INFO *GpeBlock) 151*a159c266SJung-uk Kim { 152*a159c266SJung-uk Kim ACPI_STATUS Status; 153*a159c266SJung-uk Kim ACPI_CPU_FLAGS Flags; 154*a159c266SJung-uk Kim 155*a159c266SJung-uk Kim 156*a159c266SJung-uk Kim ACPI_FUNCTION_TRACE (EvInstallGpeBlock); 157*a159c266SJung-uk Kim 158*a159c266SJung-uk Kim 159*a159c266SJung-uk Kim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 160*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 161*a159c266SJung-uk Kim { 162*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 163*a159c266SJung-uk Kim } 164*a159c266SJung-uk Kim 165*a159c266SJung-uk Kim /* Disable all GPEs in this block */ 166*a159c266SJung-uk Kim 167*a159c266SJung-uk Kim Status = AcpiHwDisableGpeBlock (GpeBlock->XruptBlock, GpeBlock, NULL); 168*a159c266SJung-uk Kim 169*a159c266SJung-uk Kim if (!GpeBlock->Previous && !GpeBlock->Next) 170*a159c266SJung-uk Kim { 171*a159c266SJung-uk Kim /* This is the last GpeBlock on this interrupt */ 172*a159c266SJung-uk Kim 173*a159c266SJung-uk Kim Status = AcpiEvDeleteGpeXrupt (GpeBlock->XruptBlock); 174*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 175*a159c266SJung-uk Kim { 176*a159c266SJung-uk Kim goto UnlockAndExit; 177*a159c266SJung-uk Kim } 178*a159c266SJung-uk Kim } 179*a159c266SJung-uk Kim else 180*a159c266SJung-uk Kim { 181*a159c266SJung-uk Kim /* Remove the block on this interrupt with lock */ 182*a159c266SJung-uk Kim 183*a159c266SJung-uk Kim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 184*a159c266SJung-uk Kim if (GpeBlock->Previous) 185*a159c266SJung-uk Kim { 186*a159c266SJung-uk Kim GpeBlock->Previous->Next = GpeBlock->Next; 187*a159c266SJung-uk Kim } 188*a159c266SJung-uk Kim else 189*a159c266SJung-uk Kim { 190*a159c266SJung-uk Kim GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next; 191*a159c266SJung-uk Kim } 192*a159c266SJung-uk Kim 193*a159c266SJung-uk Kim if (GpeBlock->Next) 194*a159c266SJung-uk Kim { 195*a159c266SJung-uk Kim GpeBlock->Next->Previous = GpeBlock->Previous; 196*a159c266SJung-uk Kim } 197*a159c266SJung-uk Kim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 198*a159c266SJung-uk Kim } 199*a159c266SJung-uk Kim 200*a159c266SJung-uk Kim AcpiCurrentGpeCount -= GpeBlock->GpeCount; 201*a159c266SJung-uk Kim 202*a159c266SJung-uk Kim /* Free the GpeBlock */ 203*a159c266SJung-uk Kim 204*a159c266SJung-uk Kim ACPI_FREE (GpeBlock->RegisterInfo); 205*a159c266SJung-uk Kim ACPI_FREE (GpeBlock->EventInfo); 206*a159c266SJung-uk Kim ACPI_FREE (GpeBlock); 207*a159c266SJung-uk Kim 208*a159c266SJung-uk Kim UnlockAndExit: 209*a159c266SJung-uk Kim Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 210*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 211*a159c266SJung-uk Kim } 212*a159c266SJung-uk Kim 213*a159c266SJung-uk Kim 214*a159c266SJung-uk Kim /******************************************************************************* 215*a159c266SJung-uk Kim * 216*a159c266SJung-uk Kim * FUNCTION: AcpiEvCreateGpeInfoBlocks 217*a159c266SJung-uk Kim * 218*a159c266SJung-uk Kim * PARAMETERS: GpeBlock - New GPE block 219*a159c266SJung-uk Kim * 220*a159c266SJung-uk Kim * RETURN: Status 221*a159c266SJung-uk Kim * 222*a159c266SJung-uk Kim * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block 223*a159c266SJung-uk Kim * 224*a159c266SJung-uk Kim ******************************************************************************/ 225*a159c266SJung-uk Kim 226*a159c266SJung-uk Kim static ACPI_STATUS 227*a159c266SJung-uk Kim AcpiEvCreateGpeInfoBlocks ( 228*a159c266SJung-uk Kim ACPI_GPE_BLOCK_INFO *GpeBlock) 229*a159c266SJung-uk Kim { 230*a159c266SJung-uk Kim ACPI_GPE_REGISTER_INFO *GpeRegisterInfo = NULL; 231*a159c266SJung-uk Kim ACPI_GPE_EVENT_INFO *GpeEventInfo = NULL; 232*a159c266SJung-uk Kim ACPI_GPE_EVENT_INFO *ThisEvent; 233*a159c266SJung-uk Kim ACPI_GPE_REGISTER_INFO *ThisRegister; 234*a159c266SJung-uk Kim UINT32 i; 235*a159c266SJung-uk Kim UINT32 j; 236*a159c266SJung-uk Kim ACPI_STATUS Status; 237*a159c266SJung-uk Kim 238*a159c266SJung-uk Kim 239*a159c266SJung-uk Kim ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks); 240*a159c266SJung-uk Kim 241*a159c266SJung-uk Kim 242*a159c266SJung-uk Kim /* Allocate the GPE register information block */ 243*a159c266SJung-uk Kim 244*a159c266SJung-uk Kim GpeRegisterInfo = ACPI_ALLOCATE_ZEROED ( 245*a159c266SJung-uk Kim (ACPI_SIZE) GpeBlock->RegisterCount * 246*a159c266SJung-uk Kim sizeof (ACPI_GPE_REGISTER_INFO)); 247*a159c266SJung-uk Kim if (!GpeRegisterInfo) 248*a159c266SJung-uk Kim { 249*a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 250*a159c266SJung-uk Kim "Could not allocate the GpeRegisterInfo table")); 251*a159c266SJung-uk Kim return_ACPI_STATUS (AE_NO_MEMORY); 252*a159c266SJung-uk Kim } 253*a159c266SJung-uk Kim 254*a159c266SJung-uk Kim /* 255*a159c266SJung-uk Kim * Allocate the GPE EventInfo block. There are eight distinct GPEs 256*a159c266SJung-uk Kim * per register. Initialization to zeros is sufficient. 257*a159c266SJung-uk Kim */ 258*a159c266SJung-uk Kim GpeEventInfo = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) GpeBlock->GpeCount * 259*a159c266SJung-uk Kim sizeof (ACPI_GPE_EVENT_INFO)); 260*a159c266SJung-uk Kim if (!GpeEventInfo) 261*a159c266SJung-uk Kim { 262*a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 263*a159c266SJung-uk Kim "Could not allocate the GpeEventInfo table")); 264*a159c266SJung-uk Kim Status = AE_NO_MEMORY; 265*a159c266SJung-uk Kim goto ErrorExit; 266*a159c266SJung-uk Kim } 267*a159c266SJung-uk Kim 268*a159c266SJung-uk Kim /* Save the new Info arrays in the GPE block */ 269*a159c266SJung-uk Kim 270*a159c266SJung-uk Kim GpeBlock->RegisterInfo = GpeRegisterInfo; 271*a159c266SJung-uk Kim GpeBlock->EventInfo = GpeEventInfo; 272*a159c266SJung-uk Kim 273*a159c266SJung-uk Kim /* 274*a159c266SJung-uk Kim * Initialize the GPE Register and Event structures. A goal of these 275*a159c266SJung-uk Kim * tables is to hide the fact that there are two separate GPE register 276*a159c266SJung-uk Kim * sets in a given GPE hardware block, the status registers occupy the 277*a159c266SJung-uk Kim * first half, and the enable registers occupy the second half. 278*a159c266SJung-uk Kim */ 279*a159c266SJung-uk Kim ThisRegister = GpeRegisterInfo; 280*a159c266SJung-uk Kim ThisEvent = GpeEventInfo; 281*a159c266SJung-uk Kim 282*a159c266SJung-uk Kim for (i = 0; i < GpeBlock->RegisterCount; i++) 283*a159c266SJung-uk Kim { 284*a159c266SJung-uk Kim /* Init the RegisterInfo for this GPE register (8 GPEs) */ 285*a159c266SJung-uk Kim 286*a159c266SJung-uk Kim ThisRegister->BaseGpeNumber = (UINT8) (GpeBlock->BlockBaseNumber + 287*a159c266SJung-uk Kim (i * ACPI_GPE_REGISTER_WIDTH)); 288*a159c266SJung-uk Kim 289*a159c266SJung-uk Kim ThisRegister->StatusAddress.Address = 290*a159c266SJung-uk Kim GpeBlock->BlockAddress.Address + i; 291*a159c266SJung-uk Kim 292*a159c266SJung-uk Kim ThisRegister->EnableAddress.Address = 293*a159c266SJung-uk Kim GpeBlock->BlockAddress.Address + i + GpeBlock->RegisterCount; 294*a159c266SJung-uk Kim 295*a159c266SJung-uk Kim ThisRegister->StatusAddress.SpaceId = GpeBlock->BlockAddress.SpaceId; 296*a159c266SJung-uk Kim ThisRegister->EnableAddress.SpaceId = GpeBlock->BlockAddress.SpaceId; 297*a159c266SJung-uk Kim ThisRegister->StatusAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; 298*a159c266SJung-uk Kim ThisRegister->EnableAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; 299*a159c266SJung-uk Kim ThisRegister->StatusAddress.BitOffset = 0; 300*a159c266SJung-uk Kim ThisRegister->EnableAddress.BitOffset = 0; 301*a159c266SJung-uk Kim 302*a159c266SJung-uk Kim /* Init the EventInfo for each GPE within this register */ 303*a159c266SJung-uk Kim 304*a159c266SJung-uk Kim for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 305*a159c266SJung-uk Kim { 306*a159c266SJung-uk Kim ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j); 307*a159c266SJung-uk Kim ThisEvent->RegisterInfo = ThisRegister; 308*a159c266SJung-uk Kim ThisEvent++; 309*a159c266SJung-uk Kim } 310*a159c266SJung-uk Kim 311*a159c266SJung-uk Kim /* Disable all GPEs within this register */ 312*a159c266SJung-uk Kim 313*a159c266SJung-uk Kim Status = AcpiHwWrite (0x00, &ThisRegister->EnableAddress); 314*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 315*a159c266SJung-uk Kim { 316*a159c266SJung-uk Kim goto ErrorExit; 317*a159c266SJung-uk Kim } 318*a159c266SJung-uk Kim 319*a159c266SJung-uk Kim /* Clear any pending GPE events within this register */ 320*a159c266SJung-uk Kim 321*a159c266SJung-uk Kim Status = AcpiHwWrite (0xFF, &ThisRegister->StatusAddress); 322*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 323*a159c266SJung-uk Kim { 324*a159c266SJung-uk Kim goto ErrorExit; 325*a159c266SJung-uk Kim } 326*a159c266SJung-uk Kim 327*a159c266SJung-uk Kim ThisRegister++; 328*a159c266SJung-uk Kim } 329*a159c266SJung-uk Kim 330*a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 331*a159c266SJung-uk Kim 332*a159c266SJung-uk Kim 333*a159c266SJung-uk Kim ErrorExit: 334*a159c266SJung-uk Kim if (GpeRegisterInfo) 335*a159c266SJung-uk Kim { 336*a159c266SJung-uk Kim ACPI_FREE (GpeRegisterInfo); 337*a159c266SJung-uk Kim } 338*a159c266SJung-uk Kim if (GpeEventInfo) 339*a159c266SJung-uk Kim { 340*a159c266SJung-uk Kim ACPI_FREE (GpeEventInfo); 341*a159c266SJung-uk Kim } 342*a159c266SJung-uk Kim 343*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 344*a159c266SJung-uk Kim } 345*a159c266SJung-uk Kim 346*a159c266SJung-uk Kim 347*a159c266SJung-uk Kim /******************************************************************************* 348*a159c266SJung-uk Kim * 349*a159c266SJung-uk Kim * FUNCTION: AcpiEvCreateGpeBlock 350*a159c266SJung-uk Kim * 351*a159c266SJung-uk Kim * PARAMETERS: GpeDevice - Handle to the parent GPE block 352*a159c266SJung-uk Kim * GpeBlockAddress - Address and SpaceID 353*a159c266SJung-uk Kim * RegisterCount - Number of GPE register pairs in the block 354*a159c266SJung-uk Kim * GpeBlockBaseNumber - Starting GPE number for the block 355*a159c266SJung-uk Kim * InterruptNumber - H/W interrupt for the block 356*a159c266SJung-uk Kim * ReturnGpeBlock - Where the new block descriptor is returned 357*a159c266SJung-uk Kim * 358*a159c266SJung-uk Kim * RETURN: Status 359*a159c266SJung-uk Kim * 360*a159c266SJung-uk Kim * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within 361*a159c266SJung-uk Kim * the block are disabled at exit. 362*a159c266SJung-uk Kim * Note: Assumes namespace is locked. 363*a159c266SJung-uk Kim * 364*a159c266SJung-uk Kim ******************************************************************************/ 365*a159c266SJung-uk Kim 366*a159c266SJung-uk Kim ACPI_STATUS 367*a159c266SJung-uk Kim AcpiEvCreateGpeBlock ( 368*a159c266SJung-uk Kim ACPI_NAMESPACE_NODE *GpeDevice, 369*a159c266SJung-uk Kim ACPI_GENERIC_ADDRESS *GpeBlockAddress, 370*a159c266SJung-uk Kim UINT32 RegisterCount, 371*a159c266SJung-uk Kim UINT8 GpeBlockBaseNumber, 372*a159c266SJung-uk Kim UINT32 InterruptNumber, 373*a159c266SJung-uk Kim ACPI_GPE_BLOCK_INFO **ReturnGpeBlock) 374*a159c266SJung-uk Kim { 375*a159c266SJung-uk Kim ACPI_STATUS Status; 376*a159c266SJung-uk Kim ACPI_GPE_BLOCK_INFO *GpeBlock; 377*a159c266SJung-uk Kim ACPI_GPE_WALK_INFO WalkInfo; 378*a159c266SJung-uk Kim 379*a159c266SJung-uk Kim 380*a159c266SJung-uk Kim ACPI_FUNCTION_TRACE (EvCreateGpeBlock); 381*a159c266SJung-uk Kim 382*a159c266SJung-uk Kim 383*a159c266SJung-uk Kim if (!RegisterCount) 384*a159c266SJung-uk Kim { 385*a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 386*a159c266SJung-uk Kim } 387*a159c266SJung-uk Kim 388*a159c266SJung-uk Kim /* Allocate a new GPE block */ 389*a159c266SJung-uk Kim 390*a159c266SJung-uk Kim GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO)); 391*a159c266SJung-uk Kim if (!GpeBlock) 392*a159c266SJung-uk Kim { 393*a159c266SJung-uk Kim return_ACPI_STATUS (AE_NO_MEMORY); 394*a159c266SJung-uk Kim } 395*a159c266SJung-uk Kim 396*a159c266SJung-uk Kim /* Initialize the new GPE block */ 397*a159c266SJung-uk Kim 398*a159c266SJung-uk Kim GpeBlock->Node = GpeDevice; 399*a159c266SJung-uk Kim GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH); 400*a159c266SJung-uk Kim GpeBlock->Initialized = FALSE; 401*a159c266SJung-uk Kim GpeBlock->RegisterCount = RegisterCount; 402*a159c266SJung-uk Kim GpeBlock->BlockBaseNumber = GpeBlockBaseNumber; 403*a159c266SJung-uk Kim 404*a159c266SJung-uk Kim ACPI_MEMCPY (&GpeBlock->BlockAddress, GpeBlockAddress, 405*a159c266SJung-uk Kim sizeof (ACPI_GENERIC_ADDRESS)); 406*a159c266SJung-uk Kim 407*a159c266SJung-uk Kim /* 408*a159c266SJung-uk Kim * Create the RegisterInfo and EventInfo sub-structures 409*a159c266SJung-uk Kim * Note: disables and clears all GPEs in the block 410*a159c266SJung-uk Kim */ 411*a159c266SJung-uk Kim Status = AcpiEvCreateGpeInfoBlocks (GpeBlock); 412*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 413*a159c266SJung-uk Kim { 414*a159c266SJung-uk Kim ACPI_FREE (GpeBlock); 415*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 416*a159c266SJung-uk Kim } 417*a159c266SJung-uk Kim 418*a159c266SJung-uk Kim /* Install the new block in the global lists */ 419*a159c266SJung-uk Kim 420*a159c266SJung-uk Kim Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber); 421*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 422*a159c266SJung-uk Kim { 423*a159c266SJung-uk Kim ACPI_FREE (GpeBlock); 424*a159c266SJung-uk Kim return_ACPI_STATUS (Status); 425*a159c266SJung-uk Kim } 426*a159c266SJung-uk Kim 427*a159c266SJung-uk Kim AcpiGbl_AllGpesInitialized = FALSE; 428*a159c266SJung-uk Kim 429*a159c266SJung-uk Kim /* Find all GPE methods (_Lxx or_Exx) for this block */ 430*a159c266SJung-uk Kim 431*a159c266SJung-uk Kim WalkInfo.GpeBlock = GpeBlock; 432*a159c266SJung-uk Kim WalkInfo.GpeDevice = GpeDevice; 433*a159c266SJung-uk Kim WalkInfo.ExecuteByOwnerId = FALSE; 434*a159c266SJung-uk Kim 435*a159c266SJung-uk Kim Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice, 436*a159c266SJung-uk Kim ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, 437*a159c266SJung-uk Kim AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL); 438*a159c266SJung-uk Kim 439*a159c266SJung-uk Kim /* Return the new block */ 440*a159c266SJung-uk Kim 441*a159c266SJung-uk Kim if (ReturnGpeBlock) 442*a159c266SJung-uk Kim { 443*a159c266SJung-uk Kim (*ReturnGpeBlock) = GpeBlock; 444*a159c266SJung-uk Kim } 445*a159c266SJung-uk Kim 446*a159c266SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_INIT, 447*a159c266SJung-uk Kim "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", 448*a159c266SJung-uk Kim (UINT32) GpeBlock->BlockBaseNumber, 449*a159c266SJung-uk Kim (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)), 450*a159c266SJung-uk Kim GpeDevice->Name.Ascii, GpeBlock->RegisterCount, 451*a159c266SJung-uk Kim InterruptNumber)); 452*a159c266SJung-uk Kim 453*a159c266SJung-uk Kim /* Update global count of currently available GPEs */ 454*a159c266SJung-uk Kim 455*a159c266SJung-uk Kim AcpiCurrentGpeCount += GpeBlock->GpeCount; 456*a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 457*a159c266SJung-uk Kim } 458*a159c266SJung-uk Kim 459*a159c266SJung-uk Kim 460*a159c266SJung-uk Kim /******************************************************************************* 461*a159c266SJung-uk Kim * 462*a159c266SJung-uk Kim * FUNCTION: AcpiEvInitializeGpeBlock 463*a159c266SJung-uk Kim * 464*a159c266SJung-uk Kim * PARAMETERS: ACPI_GPE_CALLBACK 465*a159c266SJung-uk Kim * 466*a159c266SJung-uk Kim * RETURN: Status 467*a159c266SJung-uk Kim * 468*a159c266SJung-uk Kim * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have 469*a159c266SJung-uk Kim * associated methods. 470*a159c266SJung-uk Kim * Note: Assumes namespace is locked. 471*a159c266SJung-uk Kim * 472*a159c266SJung-uk Kim ******************************************************************************/ 473*a159c266SJung-uk Kim 474*a159c266SJung-uk Kim ACPI_STATUS 475*a159c266SJung-uk Kim AcpiEvInitializeGpeBlock ( 476*a159c266SJung-uk Kim ACPI_GPE_XRUPT_INFO *GpeXruptInfo, 477*a159c266SJung-uk Kim ACPI_GPE_BLOCK_INFO *GpeBlock, 478*a159c266SJung-uk Kim void *Ignored) 479*a159c266SJung-uk Kim { 480*a159c266SJung-uk Kim ACPI_STATUS Status; 481*a159c266SJung-uk Kim ACPI_GPE_EVENT_INFO *GpeEventInfo; 482*a159c266SJung-uk Kim UINT32 GpeEnabledCount; 483*a159c266SJung-uk Kim UINT32 GpeIndex; 484*a159c266SJung-uk Kim UINT32 i; 485*a159c266SJung-uk Kim UINT32 j; 486*a159c266SJung-uk Kim 487*a159c266SJung-uk Kim 488*a159c266SJung-uk Kim ACPI_FUNCTION_TRACE (EvInitializeGpeBlock); 489*a159c266SJung-uk Kim 490*a159c266SJung-uk Kim 491*a159c266SJung-uk Kim /* 492*a159c266SJung-uk Kim * Ignore a null GPE block (e.g., if no GPE block 1 exists), and 493*a159c266SJung-uk Kim * any GPE blocks that have been initialized already. 494*a159c266SJung-uk Kim */ 495*a159c266SJung-uk Kim if (!GpeBlock || GpeBlock->Initialized) 496*a159c266SJung-uk Kim { 497*a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 498*a159c266SJung-uk Kim } 499*a159c266SJung-uk Kim 500*a159c266SJung-uk Kim /* 501*a159c266SJung-uk Kim * Enable all GPEs that have a corresponding method and have the 502*a159c266SJung-uk Kim * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block 503*a159c266SJung-uk Kim * must be enabled via the acpi_enable_gpe() interface. 504*a159c266SJung-uk Kim */ 505*a159c266SJung-uk Kim GpeEnabledCount = 0; 506*a159c266SJung-uk Kim 507*a159c266SJung-uk Kim for (i = 0; i < GpeBlock->RegisterCount; i++) 508*a159c266SJung-uk Kim { 509*a159c266SJung-uk Kim for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 510*a159c266SJung-uk Kim { 511*a159c266SJung-uk Kim /* Get the info block for this particular GPE */ 512*a159c266SJung-uk Kim 513*a159c266SJung-uk Kim GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j; 514*a159c266SJung-uk Kim GpeEventInfo = &GpeBlock->EventInfo[GpeIndex]; 515*a159c266SJung-uk Kim 516*a159c266SJung-uk Kim /* 517*a159c266SJung-uk Kim * Ignore GPEs that have no corresponding _Lxx/_Exx method 518*a159c266SJung-uk Kim * and GPEs that are used to wake the system 519*a159c266SJung-uk Kim */ 520*a159c266SJung-uk Kim if (((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_NONE) || 521*a159c266SJung-uk Kim ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) || 522*a159c266SJung-uk Kim (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 523*a159c266SJung-uk Kim { 524*a159c266SJung-uk Kim continue; 525*a159c266SJung-uk Kim } 526*a159c266SJung-uk Kim 527*a159c266SJung-uk Kim Status = AcpiEvAddGpeReference (GpeEventInfo); 528*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 529*a159c266SJung-uk Kim { 530*a159c266SJung-uk Kim ACPI_EXCEPTION ((AE_INFO, Status, 531*a159c266SJung-uk Kim "Could not enable GPE 0x%02X", 532*a159c266SJung-uk Kim GpeIndex + GpeBlock->BlockBaseNumber)); 533*a159c266SJung-uk Kim continue; 534*a159c266SJung-uk Kim } 535*a159c266SJung-uk Kim 536*a159c266SJung-uk Kim GpeEnabledCount++; 537*a159c266SJung-uk Kim } 538*a159c266SJung-uk Kim } 539*a159c266SJung-uk Kim 540*a159c266SJung-uk Kim if (GpeEnabledCount) 541*a159c266SJung-uk Kim { 542*a159c266SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_INIT, 543*a159c266SJung-uk Kim "Enabled %u GPEs in this block\n", GpeEnabledCount)); 544*a159c266SJung-uk Kim } 545*a159c266SJung-uk Kim 546*a159c266SJung-uk Kim GpeBlock->Initialized = TRUE; 547*a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 548*a159c266SJung-uk Kim } 549*a159c266SJung-uk Kim 550*a159c266SJung-uk Kim #endif /* !ACPI_REDUCED_HARDWARE */ 551