hwgpe.c revision 217365
167754Smsmith
267754Smsmith/******************************************************************************
367754Smsmith *
470243Smsmith * Module Name: hwgpe - Low level GPE enable/disable/clear functions
567754Smsmith *
667754Smsmith *****************************************************************************/
767754Smsmith
867754Smsmith/*
967754Smsmith * Copyright (C) 2000 - 2011, Intel Corp.
1067754Smsmith * All rights reserved.
1167754Smsmith *
1271867Smsmith * Redistribution and use in source and binary forms, with or without
1370243Smsmith * modification, are permitted provided that the following conditions
1467754Smsmith * are met:
1567754Smsmith * 1. Redistributions of source code must retain the above copyright
1667754Smsmith *    notice, this list of conditions, and the following disclaimer,
1767754Smsmith *    without modification.
1867754Smsmith * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1967754Smsmith *    substantially similar to the "NO WARRANTY" disclaimer below
2067754Smsmith *    ("Disclaimer") and any redistribution must be conditioned upon
2167754Smsmith *    including a substantially similar Disclaimer requirement for further
2267754Smsmith *    binary redistribution.
2367754Smsmith * 3. Neither the names of the above-listed copyright holders nor the names
2467754Smsmith *    of any contributors may be used to endorse or promote products derived
2567754Smsmith *    from this software without specific prior written permission.
2667754Smsmith *
2767754Smsmith * Alternatively, this software may be distributed under the terms of the
2867754Smsmith * GNU General Public License ("GPL") version 2 as published by the Free
2967754Smsmith * Software Foundation.
3067754Smsmith *
3167754Smsmith * NO WARRANTY
3267754Smsmith * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3367754Smsmith * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3467754Smsmith * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3567754Smsmith * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3667754Smsmith * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3767754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3867754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3967754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4067754Smsmith * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4167754Smsmith * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4267754Smsmith * POSSIBILITY OF SUCH DAMAGES.
4367754Smsmith */
4467754Smsmith
4567754Smsmith#include <contrib/dev/acpica/include/acpi.h>
4667754Smsmith#include <contrib/dev/acpica/include/accommon.h>
4767754Smsmith#include <contrib/dev/acpica/include/acevents.h>
4867754Smsmith
4967754Smsmith#define _COMPONENT          ACPI_HARDWARE
5067754Smsmith        ACPI_MODULE_NAME    ("hwgpe")
5167754Smsmith
5267754Smsmith/* Local prototypes */
5367754Smsmith
5467754Smsmithstatic ACPI_STATUS
5567754SmsmithAcpiHwEnableWakeupGpeBlock (
5667754Smsmith    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
5767754Smsmith    ACPI_GPE_BLOCK_INFO     *GpeBlock,
5867754Smsmith    void                    *Context);
5967754Smsmith
6067754Smsmith
6167754Smsmith/******************************************************************************
6267754Smsmith *
6367754Smsmith * FUNCTION:    AcpiHwGetGpeRegisterBit
6467754Smsmith *
6567754Smsmith * PARAMETERS:  GpeEventInfo        - Info block for the GPE
6667754Smsmith *              GpeRegisterInfo     - Info block for the GPE register
6767754Smsmith *
6867754Smsmith * RETURN:      Register mask with a one in the GPE bit position
6967754Smsmith *
7067754Smsmith * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
7167754Smsmith *              correct position for the input GPE.
7267754Smsmith *
7367754Smsmith ******************************************************************************/
7467754Smsmith
7567754SmsmithUINT32
7667754SmsmithAcpiHwGetGpeRegisterBit (
7767754Smsmith    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
7867754Smsmith    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo)
7967754Smsmith{
8067754Smsmith
8167754Smsmith    return ((UINT32) 1 <<
8267754Smsmith        (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
8367754Smsmith}
8467754Smsmith
8567754Smsmith
8667754Smsmith/******************************************************************************
8767754Smsmith *
8867754Smsmith * FUNCTION:    AcpiHwLowSetGpe
8967754Smsmith *
9067754Smsmith * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be disabled
9167754Smsmith *              Action              - Enable or disable
9267754Smsmith *
9367754Smsmith * RETURN:      Status
9467754Smsmith *
9567754Smsmith * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
9667754Smsmith *
9767754Smsmith ******************************************************************************/
9867754Smsmith
9967754SmsmithACPI_STATUS
10067754SmsmithAcpiHwLowSetGpe (
10167754Smsmith    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
10267754Smsmith    UINT32                  Action)
10367754Smsmith{
10467754Smsmith    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
10567754Smsmith    ACPI_STATUS             Status;
10667754Smsmith    UINT32                  EnableMask;
10767754Smsmith    UINT32                  RegisterBit;
10867754Smsmith
10967754Smsmith
11067754Smsmith    ACPI_FUNCTION_ENTRY ();
11167754Smsmith
11267754Smsmith
11367754Smsmith    /* Get the info block for the entire GPE register */
11467754Smsmith
11567754Smsmith    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
11667754Smsmith    if (!GpeRegisterInfo)
11767754Smsmith    {
11867754Smsmith        return (AE_NOT_EXIST);
11967754Smsmith    }
12067754Smsmith
12167754Smsmith    /* Get current value of the enable register that contains this GPE */
12267754Smsmith
12367754Smsmith    Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress);
12477424Smsmith    if (ACPI_FAILURE (Status))
12580062Smsmith    {
12667754Smsmith        return (Status);
12767754Smsmith    }
12867754Smsmith
12967754Smsmith    /* Set or clear just the bit that corresponds to this GPE */
13067754Smsmith
13167754Smsmith    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
13267754Smsmith    switch (Action)
13367754Smsmith    {
13467754Smsmith    case ACPI_GPE_CONDITIONAL_ENABLE:
13567754Smsmith
13667754Smsmith        /* Only enable if the EnableForRun bit is set */
13767754Smsmith
13867754Smsmith        if (!(RegisterBit & GpeRegisterInfo->EnableForRun))
13967754Smsmith        {
14067754Smsmith            return (AE_BAD_PARAMETER);
14167754Smsmith        }
14280062Smsmith
14380062Smsmith        /*lint -fallthrough */
14480062Smsmith
14580062Smsmith    case ACPI_GPE_ENABLE:
14667754Smsmith        ACPI_SET_BIT (EnableMask, RegisterBit);
14767754Smsmith        break;
14867754Smsmith
14967754Smsmith    case ACPI_GPE_DISABLE:
15067754Smsmith        ACPI_CLEAR_BIT (EnableMask, RegisterBit);
15167754Smsmith        break;
15267754Smsmith
15367754Smsmith    default:
15480062Smsmith        ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u\n", Action));
15567754Smsmith        return (AE_BAD_PARAMETER);
15667754Smsmith    }
15780062Smsmith
15867754Smsmith    /* Write the updated enable mask */
15980062Smsmith
16067754Smsmith    Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
16167754Smsmith    return (Status);
16267754Smsmith}
16377424Smsmith
16477424Smsmith
16577424Smsmith/******************************************************************************
16677424Smsmith *
16777424Smsmith * FUNCTION:    AcpiHwClearGpe
16877424Smsmith *
16977424Smsmith * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be cleared
17077424Smsmith *
17177424Smsmith * RETURN:      Status
17277424Smsmith *
17377424Smsmith * DESCRIPTION: Clear the status bit for a single GPE.
17477424Smsmith *
17577424Smsmith ******************************************************************************/
17677424Smsmith
17777424SmsmithACPI_STATUS
17877424SmsmithAcpiHwClearGpe (
17977424Smsmith    ACPI_GPE_EVENT_INFO     *GpeEventInfo)
18067754Smsmith{
18167754Smsmith    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
18267754Smsmith    ACPI_STATUS             Status;
18367754Smsmith    UINT32                  RegisterBit;
18467754Smsmith
18580062Smsmith
18669450Smsmith    ACPI_FUNCTION_ENTRY ();
18767754Smsmith
18867754Smsmith    /* Get the info block for the entire GPE register */
18967754Smsmith
19080062Smsmith    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
19167754Smsmith    if (!GpeRegisterInfo)
19267754Smsmith    {
19367754Smsmith        return (AE_NOT_EXIST);
19467754Smsmith    }
19567754Smsmith
19667754Smsmith    /*
19767754Smsmith     * Write a one to the appropriate bit in the status register to
19867754Smsmith     * clear this GPE.
19967754Smsmith     */
20067754Smsmith    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
20167754Smsmith
20267754Smsmith    Status = AcpiHwWrite (RegisterBit,
20367754Smsmith                    &GpeRegisterInfo->StatusAddress);
20467754Smsmith
20567754Smsmith    return (Status);
20667754Smsmith}
20767754Smsmith
20867754Smsmith
20967754Smsmith/******************************************************************************
21067754Smsmith *
21167754Smsmith * FUNCTION:    AcpiHwGetGpeStatus
21278986Smsmith *
21378986Smsmith * PARAMETERS:  GpeEventInfo        - Info block for the GPE to queried
21478986Smsmith *              EventStatus         - Where the GPE status is returned
21578986Smsmith *
21678986Smsmith * RETURN:      Status
21778986Smsmith *
21867754Smsmith * DESCRIPTION: Return the status of a single GPE.
21978986Smsmith *
22067754Smsmith ******************************************************************************/
22167754Smsmith
22267754SmsmithACPI_STATUS
22367754SmsmithAcpiHwGetGpeStatus (
22467754Smsmith    ACPI_GPE_EVENT_INFO     *GpeEventInfo,
22567754Smsmith    ACPI_EVENT_STATUS       *EventStatus)
22667754Smsmith{
22767754Smsmith    UINT32                  InByte;
22867754Smsmith    UINT32                  RegisterBit;
22977424Smsmith    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
23067754Smsmith    ACPI_EVENT_STATUS       LocalEventStatus = 0;
23167754Smsmith    ACPI_STATUS             Status;
23267754Smsmith
23367754Smsmith
23467754Smsmith    ACPI_FUNCTION_ENTRY ();
23567754Smsmith
23677424Smsmith
23767754Smsmith    if (!EventStatus)
23867754Smsmith    {
23967754Smsmith        return (AE_BAD_PARAMETER);
24067754Smsmith    }
24167754Smsmith
24267754Smsmith    /* Get the info block for the entire GPE register */
24367754Smsmith
24467754Smsmith    GpeRegisterInfo = GpeEventInfo->RegisterInfo;
24567754Smsmith
24667754Smsmith    /* Get the register bitmask for this GPE */
24767754Smsmith
24867754Smsmith    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
24967754Smsmith
25067754Smsmith    /* GPE currently enabled? (enabled for runtime?) */
25167754Smsmith
25267754Smsmith    if (RegisterBit & GpeRegisterInfo->EnableForRun)
25367754Smsmith    {
25467754Smsmith        LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
25567754Smsmith    }
25667754Smsmith
25767754Smsmith    /* GPE enabled for wake? */
25867754Smsmith
25967754Smsmith    if (RegisterBit & GpeRegisterInfo->EnableForWake)
26067754Smsmith    {
26167754Smsmith        LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
26267754Smsmith    }
26367754Smsmith
26467754Smsmith    /* GPE currently active (status bit == 1)? */
26567754Smsmith
26667754Smsmith    Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
26767754Smsmith    if (ACPI_FAILURE (Status))
26867754Smsmith    {
26967754Smsmith        return (Status);
27067754Smsmith    }
27167754Smsmith
27267754Smsmith    if (RegisterBit & InByte)
27367754Smsmith    {
27467754Smsmith        LocalEventStatus |= ACPI_EVENT_FLAG_SET;
27567754Smsmith    }
27667754Smsmith
27767754Smsmith    /* Set return value */
27867754Smsmith
27967754Smsmith    (*EventStatus) = LocalEventStatus;
28067754Smsmith    return (AE_OK);
28167754Smsmith}
28267754Smsmith
28367754Smsmith
28467754Smsmith/******************************************************************************
28567754Smsmith *
28667754Smsmith * FUNCTION:    AcpiHwDisableGpeBlock
28767754Smsmith *
28877424Smsmith * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
28967754Smsmith *              GpeBlock            - Gpe Block info
29067754Smsmith *
29167754Smsmith * RETURN:      Status
29267754Smsmith *
29367754Smsmith * DESCRIPTION: Disable all GPEs within a single GPE block
29477424Smsmith *
29567754Smsmith ******************************************************************************/
29667754Smsmith
29767754SmsmithACPI_STATUS
29867754SmsmithAcpiHwDisableGpeBlock (
29967754Smsmith    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
30077424Smsmith    ACPI_GPE_BLOCK_INFO     *GpeBlock,
30167754Smsmith    void                    *Context)
30267754Smsmith{
30367754Smsmith    UINT32                  i;
30467754Smsmith    ACPI_STATUS             Status;
30567754Smsmith
30677424Smsmith
30767754Smsmith    /* Examine each GPE Register within the block */
30867754Smsmith
30967754Smsmith    for (i = 0; i < GpeBlock->RegisterCount; i++)
31067754Smsmith    {
31167754Smsmith        /* Disable all GPEs in this register */
31267754Smsmith
31377424Smsmith        Status = AcpiHwWrite (0x00, &GpeBlock->RegisterInfo[i].EnableAddress);
31467754Smsmith        if (ACPI_FAILURE (Status))
31567754Smsmith        {
31667754Smsmith            return (Status);
31767754Smsmith        }
31877424Smsmith    }
31977424Smsmith
32077424Smsmith    return (AE_OK);
32167754Smsmith}
32267754Smsmith
32367754Smsmith
32467754Smsmith/******************************************************************************
32567754Smsmith *
32677424Smsmith * FUNCTION:    AcpiHwClearGpeBlock
32777424Smsmith *
32867754Smsmith * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
32967754Smsmith *              GpeBlock            - Gpe Block info
33067754Smsmith *
33167754Smsmith * RETURN:      Status
33267754Smsmith *
33377424Smsmith * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
33467754Smsmith *
33567754Smsmith ******************************************************************************/
33667754Smsmith
33767754SmsmithACPI_STATUS
33867754SmsmithAcpiHwClearGpeBlock (
33967754Smsmith    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
34067754Smsmith    ACPI_GPE_BLOCK_INFO     *GpeBlock,
34167754Smsmith    void                    *Context)
34267754Smsmith{
34367754Smsmith    UINT32                  i;
34467754Smsmith    ACPI_STATUS             Status;
34567754Smsmith
34667754Smsmith
34777424Smsmith    /* Examine each GPE Register within the block */
34867754Smsmith
34967754Smsmith    for (i = 0; i < GpeBlock->RegisterCount; i++)
35067754Smsmith    {
35167754Smsmith        /* Clear status on all GPEs in this register */
35267754Smsmith
35367754Smsmith        Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
35467754Smsmith        if (ACPI_FAILURE (Status))
35567754Smsmith        {
35667754Smsmith            return (Status);
35767754Smsmith        }
35867754Smsmith    }
35967754Smsmith
36067754Smsmith    return (AE_OK);
36167754Smsmith}
36267754Smsmith
36367754Smsmith
36467754Smsmith/******************************************************************************
36567754Smsmith *
36667754Smsmith * FUNCTION:    AcpiHwEnableRuntimeGpeBlock
36767754Smsmith *
36867754Smsmith * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
36967754Smsmith *              GpeBlock            - Gpe Block info
37067754Smsmith *
37167754Smsmith * RETURN:      Status
37267754Smsmith *
37367754Smsmith * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
37467754Smsmith *              combination wake/run GPEs.
37567754Smsmith *
37667754Smsmith ******************************************************************************/
37767754Smsmith
37867754SmsmithACPI_STATUS
37967754SmsmithAcpiHwEnableRuntimeGpeBlock (
38067754Smsmith    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
38167754Smsmith    ACPI_GPE_BLOCK_INFO     *GpeBlock,
38267754Smsmith    void                    *Context)
38367754Smsmith{
38467754Smsmith    UINT32                  i;
38567754Smsmith    ACPI_STATUS             Status;
38667754Smsmith
38767754Smsmith
38867754Smsmith    /* NOTE: assumes that all GPEs are currently disabled */
38967754Smsmith
39067754Smsmith    /* Examine each GPE Register within the block */
39167754Smsmith
39267754Smsmith    for (i = 0; i < GpeBlock->RegisterCount; i++)
39367754Smsmith    {
39467754Smsmith        if (!GpeBlock->RegisterInfo[i].EnableForRun)
39567754Smsmith        {
39667754Smsmith            continue;
39767754Smsmith        }
39867754Smsmith
39967754Smsmith        /* Enable all "runtime" GPEs in this register */
40067754Smsmith
40169450Smsmith        Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun,
40267754Smsmith                    &GpeBlock->RegisterInfo[i].EnableAddress);
40367754Smsmith        if (ACPI_FAILURE (Status))
40467754Smsmith        {
40569450Smsmith            return (Status);
40667754Smsmith        }
40767754Smsmith    }
40871867Smsmith
40971867Smsmith    return (AE_OK);
41071867Smsmith}
41171867Smsmith
41267754Smsmith
41367754Smsmith/******************************************************************************
41467754Smsmith *
41567754Smsmith * FUNCTION:    AcpiHwEnableWakeupGpeBlock
41667754Smsmith *
41767754Smsmith * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
41867754Smsmith *              GpeBlock            - Gpe Block info
41967754Smsmith *
42067754Smsmith * RETURN:      Status
42167754Smsmith *
42267754Smsmith * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
42367754Smsmith *              combination wake/run GPEs.
42467754Smsmith *
42567754Smsmith ******************************************************************************/
42667754Smsmith
42767754Smsmithstatic ACPI_STATUS
42867754SmsmithAcpiHwEnableWakeupGpeBlock (
42967754Smsmith    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
43067754Smsmith    ACPI_GPE_BLOCK_INFO     *GpeBlock,
43167754Smsmith    void                    *Context)
43267754Smsmith{
43367754Smsmith    UINT32                  i;
43467754Smsmith    ACPI_STATUS             Status;
43567754Smsmith
43667754Smsmith
43767754Smsmith    /* Examine each GPE Register within the block */
43867754Smsmith
43967754Smsmith    for (i = 0; i < GpeBlock->RegisterCount; i++)
44067754Smsmith    {
44167754Smsmith        if (!GpeBlock->RegisterInfo[i].EnableForWake)
44267754Smsmith        {
443            continue;
444        }
445
446        /* Enable all "wake" GPEs in this register */
447
448        Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake,
449                    &GpeBlock->RegisterInfo[i].EnableAddress);
450        if (ACPI_FAILURE (Status))
451        {
452            return (Status);
453        }
454    }
455
456    return (AE_OK);
457}
458
459
460/******************************************************************************
461 *
462 * FUNCTION:    AcpiHwDisableAllGpes
463 *
464 * PARAMETERS:  None
465 *
466 * RETURN:      Status
467 *
468 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
469 *
470 ******************************************************************************/
471
472ACPI_STATUS
473AcpiHwDisableAllGpes (
474    void)
475{
476    ACPI_STATUS             Status;
477
478
479    ACPI_FUNCTION_TRACE (HwDisableAllGpes);
480
481
482    Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
483    Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
484    return_ACPI_STATUS (Status);
485}
486
487
488/******************************************************************************
489 *
490 * FUNCTION:    AcpiHwEnableAllRuntimeGpes
491 *
492 * PARAMETERS:  None
493 *
494 * RETURN:      Status
495 *
496 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
497 *
498 ******************************************************************************/
499
500ACPI_STATUS
501AcpiHwEnableAllRuntimeGpes (
502    void)
503{
504    ACPI_STATUS             Status;
505
506
507    ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
508
509
510    Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
511    return_ACPI_STATUS (Status);
512}
513
514
515/******************************************************************************
516 *
517 * FUNCTION:    AcpiHwEnableAllWakeupGpes
518 *
519 * PARAMETERS:  None
520 *
521 * RETURN:      Status
522 *
523 * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
524 *
525 ******************************************************************************/
526
527ACPI_STATUS
528AcpiHwEnableAllWakeupGpes (
529    void)
530{
531    ACPI_STATUS             Status;
532
533
534    ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
535
536
537    Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
538    return_ACPI_STATUS (Status);
539}
540
541