126f3cdf0SGordon Ross /****************************************************************************** 226f3cdf0SGordon Ross * 326f3cdf0SGordon Ross * Module Name: evgpeinit - System GPE initialization and update 426f3cdf0SGordon Ross * 526f3cdf0SGordon Ross *****************************************************************************/ 626f3cdf0SGordon Ross 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 926f3cdf0SGordon Ross * All rights reserved. 1026f3cdf0SGordon Ross * 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. 2526f3cdf0SGordon Ross * 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. 2926f3cdf0SGordon Ross * 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 */ 4326f3cdf0SGordon Ross 4426f3cdf0SGordon Ross #include "acpi.h" 4526f3cdf0SGordon Ross #include "accommon.h" 4626f3cdf0SGordon Ross #include "acevents.h" 4726f3cdf0SGordon Ross #include "acnamesp.h" 4826f3cdf0SGordon Ross 4926f3cdf0SGordon Ross #define _COMPONENT ACPI_EVENTS 5026f3cdf0SGordon Ross ACPI_MODULE_NAME ("evgpeinit") 5126f3cdf0SGordon Ross 52*385cc6b4SJerry Jelinek #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 5326f3cdf0SGordon Ross 5426f3cdf0SGordon Ross /* 5526f3cdf0SGordon Ross * Note: History of _PRW support in ACPICA 5626f3cdf0SGordon Ross * 5726f3cdf0SGordon Ross * Originally (2000 - 2010), the GPE initialization code performed a walk of 5826f3cdf0SGordon Ross * the entire namespace to execute the _PRW methods and detect all GPEs 5926f3cdf0SGordon Ross * capable of waking the system. 6026f3cdf0SGordon Ross * 6126f3cdf0SGordon Ross * As of 10/2010, the _PRW method execution has been removed since it is 6226f3cdf0SGordon Ross * actually unnecessary. The host OS must in fact execute all _PRW methods 6326f3cdf0SGordon Ross * in order to identify the device/power-resource dependencies. We now put 6426f3cdf0SGordon Ross * the onus on the host OS to identify the wake GPEs as part of this process 6526f3cdf0SGordon Ross * and to inform ACPICA of these GPEs via the AcpiSetupGpeForWake interface. This 6626f3cdf0SGordon Ross * not only reduces the complexity of the ACPICA initialization code, but in 6726f3cdf0SGordon Ross * some cases (on systems with very large namespaces) it should reduce the 6826f3cdf0SGordon Ross * kernel boot time as well. 6926f3cdf0SGordon Ross */ 7026f3cdf0SGordon Ross 7126f3cdf0SGordon Ross /******************************************************************************* 7226f3cdf0SGordon Ross * 7326f3cdf0SGordon Ross * FUNCTION: AcpiEvGpeInitialize 7426f3cdf0SGordon Ross * 7526f3cdf0SGordon Ross * PARAMETERS: None 7626f3cdf0SGordon Ross * 7726f3cdf0SGordon Ross * RETURN: Status 7826f3cdf0SGordon Ross * 7926f3cdf0SGordon Ross * DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks 8026f3cdf0SGordon Ross * 8126f3cdf0SGordon Ross ******************************************************************************/ 8226f3cdf0SGordon Ross 8326f3cdf0SGordon Ross ACPI_STATUS 8426f3cdf0SGordon Ross AcpiEvGpeInitialize ( 8526f3cdf0SGordon Ross void) 8626f3cdf0SGordon Ross { 8726f3cdf0SGordon Ross UINT32 RegisterCount0 = 0; 8826f3cdf0SGordon Ross UINT32 RegisterCount1 = 0; 8926f3cdf0SGordon Ross UINT32 GpeNumberMax = 0; 9026f3cdf0SGordon Ross ACPI_STATUS Status; 9126f3cdf0SGordon Ross 9226f3cdf0SGordon Ross 9326f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (EvGpeInitialize); 9426f3cdf0SGordon Ross 9526f3cdf0SGordon Ross 96*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, 97*385cc6b4SJerry Jelinek "Initializing General Purpose Events (GPEs):\n")); 98*385cc6b4SJerry Jelinek 9926f3cdf0SGordon Ross Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 10026f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 10126f3cdf0SGordon Ross { 10226f3cdf0SGordon Ross return_ACPI_STATUS (Status); 10326f3cdf0SGordon Ross } 10426f3cdf0SGordon Ross 10526f3cdf0SGordon Ross /* 10626f3cdf0SGordon Ross * Initialize the GPE Block(s) defined in the FADT 10726f3cdf0SGordon Ross * 10826f3cdf0SGordon Ross * Why the GPE register block lengths are divided by 2: From the ACPI 10926f3cdf0SGordon Ross * Spec, section "General-Purpose Event Registers", we have: 11026f3cdf0SGordon Ross * 11126f3cdf0SGordon Ross * "Each register block contains two registers of equal length 11226f3cdf0SGordon Ross * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the 11326f3cdf0SGordon Ross * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN 11426f3cdf0SGordon Ross * The length of the GPE1_STS and GPE1_EN registers is equal to 11526f3cdf0SGordon Ross * half the GPE1_LEN. If a generic register block is not supported 11626f3cdf0SGordon Ross * then its respective block pointer and block length values in the 11726f3cdf0SGordon Ross * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need 11826f3cdf0SGordon Ross * to be the same size." 11926f3cdf0SGordon Ross */ 12026f3cdf0SGordon Ross 12126f3cdf0SGordon Ross /* 12226f3cdf0SGordon Ross * Determine the maximum GPE number for this machine. 12326f3cdf0SGordon Ross * 12426f3cdf0SGordon Ross * Note: both GPE0 and GPE1 are optional, and either can exist without 12526f3cdf0SGordon Ross * the other. 12626f3cdf0SGordon Ross * 12726f3cdf0SGordon Ross * If EITHER the register length OR the block address are zero, then that 12826f3cdf0SGordon Ross * particular block is not supported. 12926f3cdf0SGordon Ross */ 13026f3cdf0SGordon Ross if (AcpiGbl_FADT.Gpe0BlockLength && 13126f3cdf0SGordon Ross AcpiGbl_FADT.XGpe0Block.Address) 13226f3cdf0SGordon Ross { 13326f3cdf0SGordon Ross /* GPE block 0 exists (has both length and address > 0) */ 13426f3cdf0SGordon Ross 13526f3cdf0SGordon Ross RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2); 13626f3cdf0SGordon Ross GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1; 13726f3cdf0SGordon Ross 13826f3cdf0SGordon Ross /* Install GPE Block 0 */ 13926f3cdf0SGordon Ross 14026f3cdf0SGordon Ross Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, 141*385cc6b4SJerry Jelinek AcpiGbl_FADT.XGpe0Block.Address, 142*385cc6b4SJerry Jelinek AcpiGbl_FADT.XGpe0Block.SpaceId, 143*385cc6b4SJerry Jelinek RegisterCount0, 0, 14426f3cdf0SGordon Ross AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]); 14526f3cdf0SGordon Ross 14626f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 14726f3cdf0SGordon Ross { 14826f3cdf0SGordon Ross ACPI_EXCEPTION ((AE_INFO, Status, 14926f3cdf0SGordon Ross "Could not create GPE Block 0")); 15026f3cdf0SGordon Ross } 15126f3cdf0SGordon Ross } 15226f3cdf0SGordon Ross 15326f3cdf0SGordon Ross if (AcpiGbl_FADT.Gpe1BlockLength && 15426f3cdf0SGordon Ross AcpiGbl_FADT.XGpe1Block.Address) 15526f3cdf0SGordon Ross { 15626f3cdf0SGordon Ross /* GPE block 1 exists (has both length and address > 0) */ 15726f3cdf0SGordon Ross 15826f3cdf0SGordon Ross RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2); 15926f3cdf0SGordon Ross 16026f3cdf0SGordon Ross /* Check for GPE0/GPE1 overlap (if both banks exist) */ 16126f3cdf0SGordon Ross 16226f3cdf0SGordon Ross if ((RegisterCount0) && 16326f3cdf0SGordon Ross (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base)) 16426f3cdf0SGordon Ross { 16526f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, 16626f3cdf0SGordon Ross "GPE0 block (GPE 0 to %u) overlaps the GPE1 block " 16726f3cdf0SGordon Ross "(GPE %u to %u) - Ignoring GPE1", 16826f3cdf0SGordon Ross GpeNumberMax, AcpiGbl_FADT.Gpe1Base, 16926f3cdf0SGordon Ross AcpiGbl_FADT.Gpe1Base + 17026f3cdf0SGordon Ross ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1))); 17126f3cdf0SGordon Ross 17226f3cdf0SGordon Ross /* Ignore GPE1 block by setting the register count to zero */ 17326f3cdf0SGordon Ross 17426f3cdf0SGordon Ross RegisterCount1 = 0; 17526f3cdf0SGordon Ross } 17626f3cdf0SGordon Ross else 17726f3cdf0SGordon Ross { 17826f3cdf0SGordon Ross /* Install GPE Block 1 */ 17926f3cdf0SGordon Ross 18026f3cdf0SGordon Ross Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, 181*385cc6b4SJerry Jelinek AcpiGbl_FADT.XGpe1Block.Address, 182*385cc6b4SJerry Jelinek AcpiGbl_FADT.XGpe1Block.SpaceId, 183*385cc6b4SJerry Jelinek RegisterCount1, 18426f3cdf0SGordon Ross AcpiGbl_FADT.Gpe1Base, 18526f3cdf0SGordon Ross AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]); 18626f3cdf0SGordon Ross 18726f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 18826f3cdf0SGordon Ross { 18926f3cdf0SGordon Ross ACPI_EXCEPTION ((AE_INFO, Status, 19026f3cdf0SGordon Ross "Could not create GPE Block 1")); 19126f3cdf0SGordon Ross } 19226f3cdf0SGordon Ross 19326f3cdf0SGordon Ross /* 19426f3cdf0SGordon Ross * GPE0 and GPE1 do not have to be contiguous in the GPE number 19526f3cdf0SGordon Ross * space. However, GPE0 always starts at GPE number zero. 19626f3cdf0SGordon Ross */ 19726f3cdf0SGordon Ross GpeNumberMax = AcpiGbl_FADT.Gpe1Base + 19826f3cdf0SGordon Ross ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1); 19926f3cdf0SGordon Ross } 20026f3cdf0SGordon Ross } 20126f3cdf0SGordon Ross 20226f3cdf0SGordon Ross /* Exit if there are no GPE registers */ 20326f3cdf0SGordon Ross 20426f3cdf0SGordon Ross if ((RegisterCount0 + RegisterCount1) == 0) 20526f3cdf0SGordon Ross { 20626f3cdf0SGordon Ross /* GPEs are not required by ACPI, this is OK */ 20726f3cdf0SGordon Ross 20826f3cdf0SGordon Ross ACPI_DEBUG_PRINT ((ACPI_DB_INIT, 20926f3cdf0SGordon Ross "There are no GPE blocks defined in the FADT\n")); 21026f3cdf0SGordon Ross Status = AE_OK; 21126f3cdf0SGordon Ross goto Cleanup; 21226f3cdf0SGordon Ross } 21326f3cdf0SGordon Ross 21426f3cdf0SGordon Ross 21526f3cdf0SGordon Ross Cleanup: 21626f3cdf0SGordon Ross (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 21726f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 21826f3cdf0SGordon Ross } 21926f3cdf0SGordon Ross 22026f3cdf0SGordon Ross 22126f3cdf0SGordon Ross /******************************************************************************* 22226f3cdf0SGordon Ross * 22326f3cdf0SGordon Ross * FUNCTION: AcpiEvUpdateGpes 22426f3cdf0SGordon Ross * 22526f3cdf0SGordon Ross * PARAMETERS: TableOwnerId - ID of the newly-loaded ACPI table 22626f3cdf0SGordon Ross * 22726f3cdf0SGordon Ross * RETURN: None 22826f3cdf0SGordon Ross * 22926f3cdf0SGordon Ross * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a 23026f3cdf0SGordon Ross * result of a Load() or LoadTable() operation. If new GPE 23126f3cdf0SGordon Ross * methods have been installed, register the new methods. 23226f3cdf0SGordon Ross * 23326f3cdf0SGordon Ross ******************************************************************************/ 23426f3cdf0SGordon Ross 23526f3cdf0SGordon Ross void 23626f3cdf0SGordon Ross AcpiEvUpdateGpes ( 23726f3cdf0SGordon Ross ACPI_OWNER_ID TableOwnerId) 23826f3cdf0SGordon Ross { 23926f3cdf0SGordon Ross ACPI_GPE_XRUPT_INFO *GpeXruptInfo; 24026f3cdf0SGordon Ross ACPI_GPE_BLOCK_INFO *GpeBlock; 24126f3cdf0SGordon Ross ACPI_GPE_WALK_INFO WalkInfo; 24226f3cdf0SGordon Ross ACPI_STATUS Status = AE_OK; 24326f3cdf0SGordon Ross 24426f3cdf0SGordon Ross 24526f3cdf0SGordon Ross /* 24626f3cdf0SGordon Ross * Find any _Lxx/_Exx GPE methods that have just been loaded. 24726f3cdf0SGordon Ross * 24826f3cdf0SGordon Ross * Any GPEs that correspond to new _Lxx/_Exx methods are immediately 24926f3cdf0SGordon Ross * enabled. 25026f3cdf0SGordon Ross * 25126f3cdf0SGordon Ross * Examine the namespace underneath each GpeDevice within the 25226f3cdf0SGordon Ross * GpeBlock lists. 25326f3cdf0SGordon Ross */ 25426f3cdf0SGordon Ross Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 25526f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 25626f3cdf0SGordon Ross { 25726f3cdf0SGordon Ross return; 25826f3cdf0SGordon Ross } 25926f3cdf0SGordon Ross 26026f3cdf0SGordon Ross WalkInfo.Count = 0; 26126f3cdf0SGordon Ross WalkInfo.OwnerId = TableOwnerId; 26226f3cdf0SGordon Ross WalkInfo.ExecuteByOwnerId = TRUE; 26326f3cdf0SGordon Ross 26426f3cdf0SGordon Ross /* Walk the interrupt level descriptor list */ 26526f3cdf0SGordon Ross 26626f3cdf0SGordon Ross GpeXruptInfo = AcpiGbl_GpeXruptListHead; 26726f3cdf0SGordon Ross while (GpeXruptInfo) 26826f3cdf0SGordon Ross { 26926f3cdf0SGordon Ross /* Walk all Gpe Blocks attached to this interrupt level */ 27026f3cdf0SGordon Ross 27126f3cdf0SGordon Ross GpeBlock = GpeXruptInfo->GpeBlockListHead; 27226f3cdf0SGordon Ross while (GpeBlock) 27326f3cdf0SGordon Ross { 27426f3cdf0SGordon Ross WalkInfo.GpeBlock = GpeBlock; 27526f3cdf0SGordon Ross WalkInfo.GpeDevice = GpeBlock->Node; 27626f3cdf0SGordon Ross 27726f3cdf0SGordon Ross Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, 27826f3cdf0SGordon Ross WalkInfo.GpeDevice, ACPI_UINT32_MAX, 27926f3cdf0SGordon Ross ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod, 28026f3cdf0SGordon Ross NULL, &WalkInfo, NULL); 28126f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 28226f3cdf0SGordon Ross { 28326f3cdf0SGordon Ross ACPI_EXCEPTION ((AE_INFO, Status, 28426f3cdf0SGordon Ross "While decoding _Lxx/_Exx methods")); 28526f3cdf0SGordon Ross } 28626f3cdf0SGordon Ross 28726f3cdf0SGordon Ross GpeBlock = GpeBlock->Next; 28826f3cdf0SGordon Ross } 28926f3cdf0SGordon Ross 29026f3cdf0SGordon Ross GpeXruptInfo = GpeXruptInfo->Next; 29126f3cdf0SGordon Ross } 29226f3cdf0SGordon Ross 29326f3cdf0SGordon Ross if (WalkInfo.Count) 29426f3cdf0SGordon Ross { 295*385cc6b4SJerry Jelinek ACPI_INFO (("Enabled %u new GPEs", WalkInfo.Count)); 29626f3cdf0SGordon Ross } 29726f3cdf0SGordon Ross 29826f3cdf0SGordon Ross (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 29926f3cdf0SGordon Ross return; 30026f3cdf0SGordon Ross } 30126f3cdf0SGordon Ross 30226f3cdf0SGordon Ross 30326f3cdf0SGordon Ross /******************************************************************************* 30426f3cdf0SGordon Ross * 30526f3cdf0SGordon Ross * FUNCTION: AcpiEvMatchGpeMethod 30626f3cdf0SGordon Ross * 30726f3cdf0SGordon Ross * PARAMETERS: Callback from WalkNamespace 30826f3cdf0SGordon Ross * 30926f3cdf0SGordon Ross * RETURN: Status 31026f3cdf0SGordon Ross * 31126f3cdf0SGordon Ross * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a 31226f3cdf0SGordon Ross * control method under the _GPE portion of the namespace. 31326f3cdf0SGordon Ross * Extract the name and GPE type from the object, saving this 31426f3cdf0SGordon Ross * information for quick lookup during GPE dispatch. Allows a 31526f3cdf0SGordon Ross * per-OwnerId evaluation if ExecuteByOwnerId is TRUE in the 31626f3cdf0SGordon Ross * WalkInfo parameter block. 31726f3cdf0SGordon Ross * 31826f3cdf0SGordon Ross * The name of each GPE control method is of the form: 31926f3cdf0SGordon Ross * "_Lxx" or "_Exx", where: 32026f3cdf0SGordon Ross * L - means that the GPE is level triggered 32126f3cdf0SGordon Ross * E - means that the GPE is edge triggered 32226f3cdf0SGordon Ross * xx - is the GPE number [in HEX] 32326f3cdf0SGordon Ross * 32426f3cdf0SGordon Ross * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods 32526f3cdf0SGordon Ross * with that owner. 32626f3cdf0SGordon Ross * 32726f3cdf0SGordon Ross ******************************************************************************/ 32826f3cdf0SGordon Ross 32926f3cdf0SGordon Ross ACPI_STATUS 33026f3cdf0SGordon Ross AcpiEvMatchGpeMethod ( 33126f3cdf0SGordon Ross ACPI_HANDLE ObjHandle, 33226f3cdf0SGordon Ross UINT32 Level, 33326f3cdf0SGordon Ross void *Context, 33426f3cdf0SGordon Ross void **ReturnValue) 33526f3cdf0SGordon Ross { 33626f3cdf0SGordon Ross ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); 33726f3cdf0SGordon Ross ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); 33826f3cdf0SGordon Ross ACPI_GPE_EVENT_INFO *GpeEventInfo; 33926f3cdf0SGordon Ross UINT32 GpeNumber; 34026f3cdf0SGordon Ross char Name[ACPI_NAME_SIZE + 1]; 34126f3cdf0SGordon Ross UINT8 Type; 34226f3cdf0SGordon Ross 34326f3cdf0SGordon Ross 34426f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (EvMatchGpeMethod); 34526f3cdf0SGordon Ross 34626f3cdf0SGordon Ross 34726f3cdf0SGordon Ross /* Check if requested OwnerId matches this OwnerId */ 34826f3cdf0SGordon Ross 34926f3cdf0SGordon Ross if ((WalkInfo->ExecuteByOwnerId) && 35026f3cdf0SGordon Ross (MethodNode->OwnerId != WalkInfo->OwnerId)) 35126f3cdf0SGordon Ross { 35226f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 35326f3cdf0SGordon Ross } 35426f3cdf0SGordon Ross 35526f3cdf0SGordon Ross /* 35626f3cdf0SGordon Ross * Match and decode the _Lxx and _Exx GPE method names 35726f3cdf0SGordon Ross * 35826f3cdf0SGordon Ross * 1) Extract the method name and null terminate it 35926f3cdf0SGordon Ross */ 36026f3cdf0SGordon Ross ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer); 36126f3cdf0SGordon Ross Name[ACPI_NAME_SIZE] = 0; 36226f3cdf0SGordon Ross 36326f3cdf0SGordon Ross /* 2) Name must begin with an underscore */ 36426f3cdf0SGordon Ross 36526f3cdf0SGordon Ross if (Name[0] != '_') 36626f3cdf0SGordon Ross { 36726f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); /* Ignore this method */ 36826f3cdf0SGordon Ross } 36926f3cdf0SGordon Ross 37026f3cdf0SGordon Ross /* 37126f3cdf0SGordon Ross * 3) Edge/Level determination is based on the 2nd character 37226f3cdf0SGordon Ross * of the method name 37326f3cdf0SGordon Ross */ 37426f3cdf0SGordon Ross switch (Name[1]) 37526f3cdf0SGordon Ross { 37626f3cdf0SGordon Ross case 'L': 377*385cc6b4SJerry Jelinek 37826f3cdf0SGordon Ross Type = ACPI_GPE_LEVEL_TRIGGERED; 37926f3cdf0SGordon Ross break; 38026f3cdf0SGordon Ross 38126f3cdf0SGordon Ross case 'E': 382*385cc6b4SJerry Jelinek 38326f3cdf0SGordon Ross Type = ACPI_GPE_EDGE_TRIGGERED; 38426f3cdf0SGordon Ross break; 38526f3cdf0SGordon Ross 38626f3cdf0SGordon Ross default: 387*385cc6b4SJerry Jelinek 38826f3cdf0SGordon Ross /* Unknown method type, just ignore it */ 38926f3cdf0SGordon Ross 39026f3cdf0SGordon Ross ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, 39126f3cdf0SGordon Ross "Ignoring unknown GPE method type: %s " 39226f3cdf0SGordon Ross "(name not of form _Lxx or _Exx)", Name)); 39326f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 39426f3cdf0SGordon Ross } 39526f3cdf0SGordon Ross 39626f3cdf0SGordon Ross /* 4) The last two characters of the name are the hex GPE Number */ 39726f3cdf0SGordon Ross 398*385cc6b4SJerry Jelinek GpeNumber = strtoul (&Name[2], NULL, 16); 39926f3cdf0SGordon Ross if (GpeNumber == ACPI_UINT32_MAX) 40026f3cdf0SGordon Ross { 40126f3cdf0SGordon Ross /* Conversion failed; invalid method, just ignore it */ 40226f3cdf0SGordon Ross 40326f3cdf0SGordon Ross ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, 40426f3cdf0SGordon Ross "Could not extract GPE number from name: %s " 40526f3cdf0SGordon Ross "(name is not of form _Lxx or _Exx)", Name)); 40626f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 40726f3cdf0SGordon Ross } 40826f3cdf0SGordon Ross 40926f3cdf0SGordon Ross /* Ensure that we have a valid GPE number for this GPE block */ 41026f3cdf0SGordon Ross 41126f3cdf0SGordon Ross GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, WalkInfo->GpeBlock); 41226f3cdf0SGordon Ross if (!GpeEventInfo) 41326f3cdf0SGordon Ross { 41426f3cdf0SGordon Ross /* 41526f3cdf0SGordon Ross * This GpeNumber is not valid for this GPE block, just ignore it. 41626f3cdf0SGordon Ross * However, it may be valid for a different GPE block, since GPE0 41726f3cdf0SGordon Ross * and GPE1 methods both appear under \_GPE. 41826f3cdf0SGordon Ross */ 41926f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 42026f3cdf0SGordon Ross } 42126f3cdf0SGordon Ross 422*385cc6b4SJerry Jelinek if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 423*385cc6b4SJerry Jelinek ACPI_GPE_DISPATCH_HANDLER) || 424*385cc6b4SJerry Jelinek (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 425*385cc6b4SJerry Jelinek ACPI_GPE_DISPATCH_RAW_HANDLER)) 42626f3cdf0SGordon Ross { 42726f3cdf0SGordon Ross /* If there is already a handler, ignore this GPE method */ 42826f3cdf0SGordon Ross 42926f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 43026f3cdf0SGordon Ross } 43126f3cdf0SGordon Ross 432*385cc6b4SJerry Jelinek if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == 43326f3cdf0SGordon Ross ACPI_GPE_DISPATCH_METHOD) 43426f3cdf0SGordon Ross { 43526f3cdf0SGordon Ross /* 43626f3cdf0SGordon Ross * If there is already a method, ignore this method. But check 43726f3cdf0SGordon Ross * for a type mismatch (if both the _Lxx AND _Exx exist) 43826f3cdf0SGordon Ross */ 43926f3cdf0SGordon Ross if (Type != (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) 44026f3cdf0SGordon Ross { 44126f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, 44226f3cdf0SGordon Ross "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods", 44326f3cdf0SGordon Ross GpeNumber, GpeNumber, GpeNumber)); 44426f3cdf0SGordon Ross } 44526f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 44626f3cdf0SGordon Ross } 44726f3cdf0SGordon Ross 448*385cc6b4SJerry Jelinek /* Disable the GPE in case it's been enabled already. */ 449*385cc6b4SJerry Jelinek 450*385cc6b4SJerry Jelinek (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 451*385cc6b4SJerry Jelinek 45226f3cdf0SGordon Ross /* 45326f3cdf0SGordon Ross * Add the GPE information from above to the GpeEventInfo block for 45426f3cdf0SGordon Ross * use during dispatch of this GPE. 45526f3cdf0SGordon Ross */ 45626f3cdf0SGordon Ross GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK); 45726f3cdf0SGordon Ross GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); 45826f3cdf0SGordon Ross GpeEventInfo->Dispatch.MethodNode = MethodNode; 45926f3cdf0SGordon Ross 46026f3cdf0SGordon Ross ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, 46126f3cdf0SGordon Ross "Registered GPE method %s as GPE number 0x%.2X\n", 46226f3cdf0SGordon Ross Name, GpeNumber)); 46326f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 46426f3cdf0SGordon Ross } 465*385cc6b4SJerry Jelinek 466*385cc6b4SJerry Jelinek #endif /* !ACPI_REDUCED_HARDWARE */ 467