1207340Sjkim/******************************************************************************
2207340Sjkim *
3207340Sjkim * Module Name: evgpeinit - System GPE initialization and update
4207340Sjkim *
5207340Sjkim *****************************************************************************/
6207340Sjkim
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9207340Sjkim * All rights reserved.
10207340Sjkim *
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.
25207340Sjkim *
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.
29207340Sjkim *
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 */
43207340Sjkim
44207344Sjkim#include <contrib/dev/acpica/include/acpi.h>
45207344Sjkim#include <contrib/dev/acpica/include/accommon.h>
46207344Sjkim#include <contrib/dev/acpica/include/acevents.h>
47207344Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
48207340Sjkim
49207340Sjkim#define _COMPONENT          ACPI_EVENTS
50207340Sjkim        ACPI_MODULE_NAME    ("evgpeinit")
51207340Sjkim
52231844Sjkim#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
53207340Sjkim
54216471Sjkim/*
55216471Sjkim * Note: History of _PRW support in ACPICA
56216471Sjkim *
57216471Sjkim * Originally (2000 - 2010), the GPE initialization code performed a walk of
58216471Sjkim * the entire namespace to execute the _PRW methods and detect all GPEs
59216471Sjkim * capable of waking the system.
60216471Sjkim *
61216471Sjkim * As of 10/2010, the _PRW method execution has been removed since it is
62216471Sjkim * actually unnecessary. The host OS must in fact execute all _PRW methods
63216471Sjkim * in order to identify the device/power-resource dependencies. We now put
64216471Sjkim * the onus on the host OS to identify the wake GPEs as part of this process
65216471Sjkim * and to inform ACPICA of these GPEs via the AcpiSetupGpeForWake interface. This
66216471Sjkim * not only reduces the complexity of the ACPICA initialization code, but in
67216471Sjkim * some cases (on systems with very large namespaces) it should reduce the
68216471Sjkim * kernel boot time as well.
69216471Sjkim */
70216471Sjkim
71207340Sjkim/*******************************************************************************
72207340Sjkim *
73207340Sjkim * FUNCTION:    AcpiEvGpeInitialize
74207340Sjkim *
75207340Sjkim * PARAMETERS:  None
76207340Sjkim *
77207340Sjkim * RETURN:      Status
78207340Sjkim *
79207340Sjkim * DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks
80207340Sjkim *
81207340Sjkim ******************************************************************************/
82207340Sjkim
83207340SjkimACPI_STATUS
84207340SjkimAcpiEvGpeInitialize (
85207340Sjkim    void)
86207340Sjkim{
87207340Sjkim    UINT32                  RegisterCount0 = 0;
88207340Sjkim    UINT32                  RegisterCount1 = 0;
89207340Sjkim    UINT32                  GpeNumberMax = 0;
90207340Sjkim    ACPI_STATUS             Status;
91207340Sjkim
92207340Sjkim
93207340Sjkim    ACPI_FUNCTION_TRACE (EvGpeInitialize);
94207340Sjkim
95207340Sjkim
96245582Sjkim    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
97245582Sjkim        "Initializing General Purpose Events (GPEs):\n"));
98245582Sjkim
99207340Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
100207340Sjkim    if (ACPI_FAILURE (Status))
101207340Sjkim    {
102207340Sjkim        return_ACPI_STATUS (Status);
103207340Sjkim    }
104207340Sjkim
105207340Sjkim    /*
106207340Sjkim     * Initialize the GPE Block(s) defined in the FADT
107207340Sjkim     *
108207340Sjkim     * Why the GPE register block lengths are divided by 2:  From the ACPI
109207340Sjkim     * Spec, section "General-Purpose Event Registers", we have:
110207340Sjkim     *
111207340Sjkim     * "Each register block contains two registers of equal length
112207340Sjkim     *  GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
113207340Sjkim     *  GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
114207340Sjkim     *  The length of the GPE1_STS and GPE1_EN registers is equal to
115207340Sjkim     *  half the GPE1_LEN. If a generic register block is not supported
116207340Sjkim     *  then its respective block pointer and block length values in the
117207340Sjkim     *  FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
118207340Sjkim     *  to be the same size."
119207340Sjkim     */
120207340Sjkim
121207340Sjkim    /*
122207340Sjkim     * Determine the maximum GPE number for this machine.
123207340Sjkim     *
124207340Sjkim     * Note: both GPE0 and GPE1 are optional, and either can exist without
125207340Sjkim     * the other.
126207340Sjkim     *
127207340Sjkim     * If EITHER the register length OR the block address are zero, then that
128207340Sjkim     * particular block is not supported.
129207340Sjkim     */
130207340Sjkim    if (AcpiGbl_FADT.Gpe0BlockLength &&
131207340Sjkim        AcpiGbl_FADT.XGpe0Block.Address)
132207340Sjkim    {
133207340Sjkim        /* GPE block 0 exists (has both length and address > 0) */
134207340Sjkim
135207340Sjkim        RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2);
136207340Sjkim        GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1;
137207340Sjkim
138207340Sjkim        /* Install GPE Block 0 */
139207340Sjkim
140207340Sjkim        Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
141306536Sjkim            AcpiGbl_FADT.XGpe0Block.Address,
142306536Sjkim            AcpiGbl_FADT.XGpe0Block.SpaceId,
143306536Sjkim            RegisterCount0, 0,
144306536Sjkim            AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]);
145207340Sjkim
146207340Sjkim        if (ACPI_FAILURE (Status))
147207340Sjkim        {
148207340Sjkim            ACPI_EXCEPTION ((AE_INFO, Status,
149207340Sjkim                "Could not create GPE Block 0"));
150207340Sjkim        }
151207340Sjkim    }
152207340Sjkim
153207340Sjkim    if (AcpiGbl_FADT.Gpe1BlockLength &&
154207340Sjkim        AcpiGbl_FADT.XGpe1Block.Address)
155207340Sjkim    {
156207340Sjkim        /* GPE block 1 exists (has both length and address > 0) */
157207340Sjkim
158207340Sjkim        RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2);
159207340Sjkim
160207340Sjkim        /* Check for GPE0/GPE1 overlap (if both banks exist) */
161207340Sjkim
162207340Sjkim        if ((RegisterCount0) &&
163207340Sjkim            (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base))
164207340Sjkim        {
165207340Sjkim            ACPI_ERROR ((AE_INFO,
166207340Sjkim                "GPE0 block (GPE 0 to %u) overlaps the GPE1 block "
167207340Sjkim                "(GPE %u to %u) - Ignoring GPE1",
168207340Sjkim                GpeNumberMax, AcpiGbl_FADT.Gpe1Base,
169207340Sjkim                AcpiGbl_FADT.Gpe1Base +
170207340Sjkim                ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
171207340Sjkim
172207340Sjkim            /* Ignore GPE1 block by setting the register count to zero */
173207340Sjkim
174207340Sjkim            RegisterCount1 = 0;
175207340Sjkim        }
176207340Sjkim        else
177207340Sjkim        {
178207340Sjkim            /* Install GPE Block 1 */
179207340Sjkim
180207340Sjkim            Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
181306536Sjkim                AcpiGbl_FADT.XGpe1Block.Address,
182306536Sjkim                AcpiGbl_FADT.XGpe1Block.SpaceId,
183306536Sjkim                RegisterCount1,
184306536Sjkim                AcpiGbl_FADT.Gpe1Base,
185306536Sjkim                AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]);
186207340Sjkim
187207340Sjkim            if (ACPI_FAILURE (Status))
188207340Sjkim            {
189207340Sjkim                ACPI_EXCEPTION ((AE_INFO, Status,
190207340Sjkim                    "Could not create GPE Block 1"));
191207340Sjkim            }
192207340Sjkim
193207340Sjkim            /*
194207340Sjkim             * GPE0 and GPE1 do not have to be contiguous in the GPE number
195207340Sjkim             * space. However, GPE0 always starts at GPE number zero.
196207340Sjkim             */
197207340Sjkim            GpeNumberMax = AcpiGbl_FADT.Gpe1Base +
198306536Sjkim                ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1);
199207340Sjkim        }
200207340Sjkim    }
201207340Sjkim
202207340Sjkim    /* Exit if there are no GPE registers */
203207340Sjkim
204207340Sjkim    if ((RegisterCount0 + RegisterCount1) == 0)
205207340Sjkim    {
206207340Sjkim        /* GPEs are not required by ACPI, this is OK */
207207340Sjkim
208207340Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
209207340Sjkim            "There are no GPE blocks defined in the FADT\n"));
210207340Sjkim        Status = AE_OK;
211207340Sjkim        goto Cleanup;
212207340Sjkim    }
213207340Sjkim
214207340Sjkim
215207340SjkimCleanup:
216207340Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
217207340Sjkim    return_ACPI_STATUS (AE_OK);
218207340Sjkim}
219207340Sjkim
220207340Sjkim
221207340Sjkim/*******************************************************************************
222207340Sjkim *
223207340Sjkim * FUNCTION:    AcpiEvUpdateGpes
224207340Sjkim *
225207340Sjkim * PARAMETERS:  TableOwnerId        - ID of the newly-loaded ACPI table
226207340Sjkim *
227207340Sjkim * RETURN:      None
228207340Sjkim *
229207340Sjkim * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
230207340Sjkim *              result of a Load() or LoadTable() operation. If new GPE
231216471Sjkim *              methods have been installed, register the new methods.
232207340Sjkim *
233207340Sjkim ******************************************************************************/
234207340Sjkim
235207340Sjkimvoid
236207340SjkimAcpiEvUpdateGpes (
237207340Sjkim    ACPI_OWNER_ID           TableOwnerId)
238207340Sjkim{
239207340Sjkim    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo;
240207340Sjkim    ACPI_GPE_BLOCK_INFO     *GpeBlock;
241207340Sjkim    ACPI_GPE_WALK_INFO      WalkInfo;
242207340Sjkim    ACPI_STATUS             Status = AE_OK;
243207340Sjkim
244207340Sjkim
245207340Sjkim    /*
246216471Sjkim     * Find any _Lxx/_Exx GPE methods that have just been loaded.
247207340Sjkim     *
248216471Sjkim     * Any GPEs that correspond to new _Lxx/_Exx methods are immediately
249216471Sjkim     * enabled.
250207340Sjkim     *
251207340Sjkim     * Examine the namespace underneath each GpeDevice within the
252207340Sjkim     * GpeBlock lists.
253207340Sjkim     */
254207340Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
255207340Sjkim    if (ACPI_FAILURE (Status))
256207340Sjkim    {
257207340Sjkim        return;
258207340Sjkim    }
259207340Sjkim
260207340Sjkim    WalkInfo.Count = 0;
261216471Sjkim    WalkInfo.OwnerId = TableOwnerId;
262216471Sjkim    WalkInfo.ExecuteByOwnerId = TRUE;
263207340Sjkim
264207340Sjkim    /* Walk the interrupt level descriptor list */
265207340Sjkim
266207340Sjkim    GpeXruptInfo = AcpiGbl_GpeXruptListHead;
267207340Sjkim    while (GpeXruptInfo)
268207340Sjkim    {
269207340Sjkim        /* Walk all Gpe Blocks attached to this interrupt level */
270207340Sjkim
271207340Sjkim        GpeBlock = GpeXruptInfo->GpeBlockListHead;
272207340Sjkim        while (GpeBlock)
273207340Sjkim        {
274207340Sjkim            WalkInfo.GpeBlock = GpeBlock;
275207340Sjkim            WalkInfo.GpeDevice = GpeBlock->Node;
276207340Sjkim
277207340Sjkim            Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD,
278306536Sjkim                WalkInfo.GpeDevice, ACPI_UINT32_MAX,
279306536Sjkim                ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod,
280306536Sjkim                NULL, &WalkInfo, NULL);
281207340Sjkim            if (ACPI_FAILURE (Status))
282207340Sjkim            {
283207340Sjkim                ACPI_EXCEPTION ((AE_INFO, Status,
284207340Sjkim                    "While decoding _Lxx/_Exx methods"));
285207340Sjkim            }
286207340Sjkim
287207340Sjkim            GpeBlock = GpeBlock->Next;
288207340Sjkim        }
289207340Sjkim
290207340Sjkim        GpeXruptInfo = GpeXruptInfo->Next;
291207340Sjkim    }
292207340Sjkim
293216471Sjkim    if (WalkInfo.Count)
294207340Sjkim    {
295306536Sjkim        ACPI_INFO (("Enabled %u new GPEs", WalkInfo.Count));
296207340Sjkim    }
297207340Sjkim
298207340Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
299207340Sjkim    return;
300207340Sjkim}
301207340Sjkim
302207340Sjkim
303207340Sjkim/*******************************************************************************
304207340Sjkim *
305207340Sjkim * FUNCTION:    AcpiEvMatchGpeMethod
306207340Sjkim *
307207340Sjkim * PARAMETERS:  Callback from WalkNamespace
308207340Sjkim *
309207340Sjkim * RETURN:      Status
310207340Sjkim *
311207340Sjkim * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
312207340Sjkim *              control method under the _GPE portion of the namespace.
313207340Sjkim *              Extract the name and GPE type from the object, saving this
314207340Sjkim *              information for quick lookup during GPE dispatch. Allows a
315207340Sjkim *              per-OwnerId evaluation if ExecuteByOwnerId is TRUE in the
316207340Sjkim *              WalkInfo parameter block.
317207340Sjkim *
318207340Sjkim *              The name of each GPE control method is of the form:
319207340Sjkim *              "_Lxx" or "_Exx", where:
320207340Sjkim *                  L      - means that the GPE is level triggered
321207340Sjkim *                  E      - means that the GPE is edge triggered
322207340Sjkim *                  xx     - is the GPE number [in HEX]
323207340Sjkim *
324207340Sjkim * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods
325216471Sjkim * with that owner.
326207340Sjkim *
327207340Sjkim ******************************************************************************/
328207340Sjkim
329207340SjkimACPI_STATUS
330207340SjkimAcpiEvMatchGpeMethod (
331207340Sjkim    ACPI_HANDLE             ObjHandle,
332207340Sjkim    UINT32                  Level,
333207340Sjkim    void                    *Context,
334207340Sjkim    void                    **ReturnValue)
335207340Sjkim{
336207340Sjkim    ACPI_NAMESPACE_NODE     *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
337207340Sjkim    ACPI_GPE_WALK_INFO      *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context);
338207340Sjkim    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
339207340Sjkim    UINT32                  GpeNumber;
340207340Sjkim    char                    Name[ACPI_NAME_SIZE + 1];
341207340Sjkim    UINT8                   Type;
342207340Sjkim
343207340Sjkim
344207340Sjkim    ACPI_FUNCTION_TRACE (EvMatchGpeMethod);
345207340Sjkim
346207340Sjkim
347207340Sjkim    /* Check if requested OwnerId matches this OwnerId */
348207340Sjkim
349207340Sjkim    if ((WalkInfo->ExecuteByOwnerId) &&
350207340Sjkim        (MethodNode->OwnerId != WalkInfo->OwnerId))
351207340Sjkim    {
352207340Sjkim        return_ACPI_STATUS (AE_OK);
353207340Sjkim    }
354207340Sjkim
355207340Sjkim    /*
356207340Sjkim     * Match and decode the _Lxx and _Exx GPE method names
357207340Sjkim     *
358207340Sjkim     * 1) Extract the method name and null terminate it
359207340Sjkim     */
360207340Sjkim    ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer);
361207340Sjkim    Name[ACPI_NAME_SIZE] = 0;
362207340Sjkim
363207340Sjkim    /* 2) Name must begin with an underscore */
364207340Sjkim
365207340Sjkim    if (Name[0] != '_')
366207340Sjkim    {
367207340Sjkim        return_ACPI_STATUS (AE_OK); /* Ignore this method */
368207340Sjkim    }
369207340Sjkim
370207340Sjkim    /*
371207340Sjkim     * 3) Edge/Level determination is based on the 2nd character
372207340Sjkim     *    of the method name
373207340Sjkim     */
374207340Sjkim    switch (Name[1])
375207340Sjkim    {
376207340Sjkim    case 'L':
377250838Sjkim
378207340Sjkim        Type = ACPI_GPE_LEVEL_TRIGGERED;
379207340Sjkim        break;
380207340Sjkim
381207340Sjkim    case 'E':
382250838Sjkim
383207340Sjkim        Type = ACPI_GPE_EDGE_TRIGGERED;
384207340Sjkim        break;
385207340Sjkim
386207340Sjkim    default:
387250838Sjkim
388207340Sjkim        /* Unknown method type, just ignore it */
389207340Sjkim
390207340Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
391207340Sjkim            "Ignoring unknown GPE method type: %s "
392207340Sjkim            "(name not of form _Lxx or _Exx)", Name));
393207340Sjkim        return_ACPI_STATUS (AE_OK);
394207340Sjkim    }
395207340Sjkim
396207340Sjkim    /* 4) The last two characters of the name are the hex GPE Number */
397207340Sjkim
398306536Sjkim    GpeNumber = strtoul (&Name[2], NULL, 16);
399207340Sjkim    if (GpeNumber == ACPI_UINT32_MAX)
400207340Sjkim    {
401207340Sjkim        /* Conversion failed; invalid method, just ignore it */
402207340Sjkim
403207340Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
404207340Sjkim            "Could not extract GPE number from name: %s "
405207340Sjkim            "(name is not of form _Lxx or _Exx)", Name));
406207340Sjkim        return_ACPI_STATUS (AE_OK);
407207340Sjkim    }
408207340Sjkim
409207340Sjkim    /* Ensure that we have a valid GPE number for this GPE block */
410207340Sjkim
411207340Sjkim    GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, WalkInfo->GpeBlock);
412207340Sjkim    if (!GpeEventInfo)
413207340Sjkim    {
414207340Sjkim        /*
415207340Sjkim         * This GpeNumber is not valid for this GPE block, just ignore it.
416207340Sjkim         * However, it may be valid for a different GPE block, since GPE0
417207340Sjkim         * and GPE1 methods both appear under \_GPE.
418207340Sjkim         */
419207340Sjkim        return_ACPI_STATUS (AE_OK);
420207340Sjkim    }
421207340Sjkim
422281075Sdim    if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
423281075Sdim            ACPI_GPE_DISPATCH_HANDLER) ||
424281075Sdim        (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
425281075Sdim            ACPI_GPE_DISPATCH_RAW_HANDLER))
426207340Sjkim    {
427207340Sjkim        /* If there is already a handler, ignore this GPE method */
428207340Sjkim
429207340Sjkim        return_ACPI_STATUS (AE_OK);
430207340Sjkim    }
431207340Sjkim
432281075Sdim    if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
433306536Sjkim        ACPI_GPE_DISPATCH_METHOD)
434207340Sjkim    {
435207340Sjkim        /*
436207340Sjkim         * If there is already a method, ignore this method. But check
437207340Sjkim         * for a type mismatch (if both the _Lxx AND _Exx exist)
438207340Sjkim         */
439207340Sjkim        if (Type != (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
440207340Sjkim        {
441207340Sjkim            ACPI_ERROR ((AE_INFO,
442207340Sjkim                "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods",
443207340Sjkim                GpeNumber, GpeNumber, GpeNumber));
444207340Sjkim        }
445207340Sjkim        return_ACPI_STATUS (AE_OK);
446207340Sjkim    }
447207340Sjkim
448281075Sdim    /* Disable the GPE in case it's been enabled already. */
449281075Sdim
450281075Sdim    (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
451281075Sdim
452207340Sjkim    /*
453207340Sjkim     * Add the GPE information from above to the GpeEventInfo block for
454207340Sjkim     * use during dispatch of this GPE.
455207340Sjkim     */
456216471Sjkim    GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK);
457207340Sjkim    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD);
458207340Sjkim    GpeEventInfo->Dispatch.MethodNode = MethodNode;
459207340Sjkim
460207340Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
461207340Sjkim        "Registered GPE method %s as GPE number 0x%.2X\n",
462207340Sjkim        Name, GpeNumber));
463207340Sjkim    return_ACPI_STATUS (AE_OK);
464207340Sjkim}
465231844Sjkim
466231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */
467