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