Home | History | Annotate | Line # | Download | only in hardware
hwgpe.c revision 1.1.1.4
      1 /******************************************************************************
      2  *
      3  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2014, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "acpi.h"
     45 #include "accommon.h"
     46 #include "acevents.h"
     47 
     48 #define _COMPONENT          ACPI_HARDWARE
     49         ACPI_MODULE_NAME    ("hwgpe")
     50 
     51 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
     52 
     53 /* Local prototypes */
     54 
     55 static ACPI_STATUS
     56 AcpiHwEnableWakeupGpeBlock (
     57     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
     58     ACPI_GPE_BLOCK_INFO     *GpeBlock,
     59     void                    *Context);
     60 
     61 
     62 /******************************************************************************
     63  *
     64  * FUNCTION:    AcpiHwGetGpeRegisterBit
     65  *
     66  * PARAMETERS:  GpeEventInfo        - Info block for the GPE
     67  *
     68  * RETURN:      Register mask with a one in the GPE bit position
     69  *
     70  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
     71  *              correct position for the input GPE.
     72  *
     73  ******************************************************************************/
     74 
     75 UINT32
     76 AcpiHwGetGpeRegisterBit (
     77     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
     78 {
     79 
     80     return ((UINT32) 1 <<
     81         (GpeEventInfo->GpeNumber - GpeEventInfo->RegisterInfo->BaseGpeNumber));
     82 }
     83 
     84 
     85 /******************************************************************************
     86  *
     87  * FUNCTION:    AcpiHwLowSetGpe
     88  *
     89  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be disabled
     90  *              Action              - Enable or disable
     91  *
     92  * RETURN:      Status
     93  *
     94  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
     95  *
     96  ******************************************************************************/
     97 
     98 ACPI_STATUS
     99 AcpiHwLowSetGpe (
    100     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    101     UINT32                  Action)
    102 {
    103     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    104     ACPI_STATUS             Status;
    105     UINT32                  EnableMask;
    106     UINT32                  RegisterBit;
    107 
    108 
    109     ACPI_FUNCTION_ENTRY ();
    110 
    111 
    112     /* Get the info block for the entire GPE register */
    113 
    114     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    115     if (!GpeRegisterInfo)
    116     {
    117         return (AE_NOT_EXIST);
    118     }
    119 
    120     /* Get current value of the enable register that contains this GPE */
    121 
    122     Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress);
    123     if (ACPI_FAILURE (Status))
    124     {
    125         return (Status);
    126     }
    127 
    128     /* Set or clear just the bit that corresponds to this GPE */
    129 
    130     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    131     switch (Action)
    132     {
    133     case ACPI_GPE_CONDITIONAL_ENABLE:
    134 
    135         /* Only enable if the EnableForRun bit is set */
    136 
    137         if (!(RegisterBit & GpeRegisterInfo->EnableForRun))
    138         {
    139             return (AE_BAD_PARAMETER);
    140         }
    141 
    142         /*lint -fallthrough */
    143 
    144     case ACPI_GPE_ENABLE:
    145 
    146         ACPI_SET_BIT (EnableMask, RegisterBit);
    147         break;
    148 
    149     case ACPI_GPE_DISABLE:
    150 
    151         ACPI_CLEAR_BIT (EnableMask, RegisterBit);
    152         break;
    153 
    154     default:
    155 
    156         ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u", Action));
    157         return (AE_BAD_PARAMETER);
    158     }
    159 
    160     /* Write the updated enable mask */
    161 
    162     Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
    163     return (Status);
    164 }
    165 
    166 
    167 /******************************************************************************
    168  *
    169  * FUNCTION:    AcpiHwClearGpe
    170  *
    171  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be cleared
    172  *
    173  * RETURN:      Status
    174  *
    175  * DESCRIPTION: Clear the status bit for a single GPE.
    176  *
    177  ******************************************************************************/
    178 
    179 ACPI_STATUS
    180 AcpiHwClearGpe (
    181     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    182 {
    183     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    184     ACPI_STATUS             Status;
    185     UINT32                  RegisterBit;
    186 
    187 
    188     ACPI_FUNCTION_ENTRY ();
    189 
    190     /* Get the info block for the entire GPE register */
    191 
    192     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    193     if (!GpeRegisterInfo)
    194     {
    195         return (AE_NOT_EXIST);
    196     }
    197 
    198     /*
    199      * Write a one to the appropriate bit in the status register to
    200      * clear this GPE.
    201      */
    202     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    203 
    204     Status = AcpiHwWrite (RegisterBit,
    205                     &GpeRegisterInfo->StatusAddress);
    206 
    207     return (Status);
    208 }
    209 
    210 
    211 /******************************************************************************
    212  *
    213  * FUNCTION:    AcpiHwGetGpeStatus
    214  *
    215  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to queried
    216  *              EventStatus         - Where the GPE status is returned
    217  *
    218  * RETURN:      Status
    219  *
    220  * DESCRIPTION: Return the status of a single GPE.
    221  *
    222  ******************************************************************************/
    223 
    224 ACPI_STATUS
    225 AcpiHwGetGpeStatus (
    226     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    227     ACPI_EVENT_STATUS       *EventStatus)
    228 {
    229     UINT32                  InByte;
    230     UINT32                  RegisterBit;
    231     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    232     ACPI_EVENT_STATUS       LocalEventStatus = 0;
    233     ACPI_STATUS             Status;
    234 
    235 
    236     ACPI_FUNCTION_ENTRY ();
    237 
    238 
    239     if (!EventStatus)
    240     {
    241         return (AE_BAD_PARAMETER);
    242     }
    243 
    244     /* GPE currently handled? */
    245 
    246     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
    247             ACPI_GPE_DISPATCH_NONE)
    248     {
    249         LocalEventStatus |= ACPI_EVENT_FLAG_HAS_HANDLER;
    250     }
    251 
    252     /* Get the info block for the entire GPE register */
    253 
    254     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    255 
    256     /* Get the register bitmask for this GPE */
    257 
    258     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    259 
    260     /* GPE currently enabled? (enabled for runtime?) */
    261 
    262     if (RegisterBit & GpeRegisterInfo->EnableForRun)
    263     {
    264         LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
    265     }
    266 
    267     /* GPE enabled for wake? */
    268 
    269     if (RegisterBit & GpeRegisterInfo->EnableForWake)
    270     {
    271         LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
    272     }
    273 
    274     /* GPE currently active (status bit == 1)? */
    275 
    276     Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
    277     if (ACPI_FAILURE (Status))
    278     {
    279         return (Status);
    280     }
    281 
    282     if (RegisterBit & InByte)
    283     {
    284         LocalEventStatus |= ACPI_EVENT_FLAG_SET;
    285     }
    286 
    287     /* Set return value */
    288 
    289     (*EventStatus) = LocalEventStatus;
    290     return (AE_OK);
    291 }
    292 
    293 
    294 /******************************************************************************
    295  *
    296  * FUNCTION:    AcpiHwDisableGpeBlock
    297  *
    298  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    299  *              GpeBlock            - Gpe Block info
    300  *
    301  * RETURN:      Status
    302  *
    303  * DESCRIPTION: Disable all GPEs within a single GPE block
    304  *
    305  ******************************************************************************/
    306 
    307 ACPI_STATUS
    308 AcpiHwDisableGpeBlock (
    309     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    310     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    311     void                    *Context)
    312 {
    313     UINT32                  i;
    314     ACPI_STATUS             Status;
    315 
    316 
    317     /* Examine each GPE Register within the block */
    318 
    319     for (i = 0; i < GpeBlock->RegisterCount; i++)
    320     {
    321         /* Disable all GPEs in this register */
    322 
    323         Status = AcpiHwWrite (0x00, &GpeBlock->RegisterInfo[i].EnableAddress);
    324         if (ACPI_FAILURE (Status))
    325         {
    326             return (Status);
    327         }
    328     }
    329 
    330     return (AE_OK);
    331 }
    332 
    333 
    334 /******************************************************************************
    335  *
    336  * FUNCTION:    AcpiHwClearGpeBlock
    337  *
    338  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    339  *              GpeBlock            - Gpe Block info
    340  *
    341  * RETURN:      Status
    342  *
    343  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
    344  *
    345  ******************************************************************************/
    346 
    347 ACPI_STATUS
    348 AcpiHwClearGpeBlock (
    349     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    350     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    351     void                    *Context)
    352 {
    353     UINT32                  i;
    354     ACPI_STATUS             Status;
    355 
    356 
    357     /* Examine each GPE Register within the block */
    358 
    359     for (i = 0; i < GpeBlock->RegisterCount; i++)
    360     {
    361         /* Clear status on all GPEs in this register */
    362 
    363         Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
    364         if (ACPI_FAILURE (Status))
    365         {
    366             return (Status);
    367         }
    368     }
    369 
    370     return (AE_OK);
    371 }
    372 
    373 
    374 /******************************************************************************
    375  *
    376  * FUNCTION:    AcpiHwEnableRuntimeGpeBlock
    377  *
    378  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    379  *              GpeBlock            - Gpe Block info
    380  *
    381  * RETURN:      Status
    382  *
    383  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
    384  *              combination wake/run GPEs.
    385  *
    386  ******************************************************************************/
    387 
    388 ACPI_STATUS
    389 AcpiHwEnableRuntimeGpeBlock (
    390     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    391     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    392     void                    *Context)
    393 {
    394     UINT32                  i;
    395     ACPI_STATUS             Status;
    396 
    397 
    398     /* NOTE: assumes that all GPEs are currently disabled */
    399 
    400     /* Examine each GPE Register within the block */
    401 
    402     for (i = 0; i < GpeBlock->RegisterCount; i++)
    403     {
    404         if (!GpeBlock->RegisterInfo[i].EnableForRun)
    405         {
    406             continue;
    407         }
    408 
    409         /* Enable all "runtime" GPEs in this register */
    410 
    411         Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun,
    412                     &GpeBlock->RegisterInfo[i].EnableAddress);
    413         if (ACPI_FAILURE (Status))
    414         {
    415             return (Status);
    416         }
    417     }
    418 
    419     return (AE_OK);
    420 }
    421 
    422 
    423 /******************************************************************************
    424  *
    425  * FUNCTION:    AcpiHwEnableWakeupGpeBlock
    426  *
    427  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    428  *              GpeBlock            - Gpe Block info
    429  *
    430  * RETURN:      Status
    431  *
    432  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
    433  *              combination wake/run GPEs.
    434  *
    435  ******************************************************************************/
    436 
    437 static ACPI_STATUS
    438 AcpiHwEnableWakeupGpeBlock (
    439     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    440     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    441     void                    *Context)
    442 {
    443     UINT32                  i;
    444     ACPI_STATUS             Status;
    445 
    446 
    447     /* Examine each GPE Register within the block */
    448 
    449     for (i = 0; i < GpeBlock->RegisterCount; i++)
    450     {
    451         if (!GpeBlock->RegisterInfo[i].EnableForWake)
    452         {
    453             continue;
    454         }
    455 
    456         /* Enable all "wake" GPEs in this register */
    457 
    458         Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake,
    459                     &GpeBlock->RegisterInfo[i].EnableAddress);
    460         if (ACPI_FAILURE (Status))
    461         {
    462             return (Status);
    463         }
    464     }
    465 
    466     return (AE_OK);
    467 }
    468 
    469 
    470 /******************************************************************************
    471  *
    472  * FUNCTION:    AcpiHwDisableAllGpes
    473  *
    474  * PARAMETERS:  None
    475  *
    476  * RETURN:      Status
    477  *
    478  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
    479  *
    480  ******************************************************************************/
    481 
    482 ACPI_STATUS
    483 AcpiHwDisableAllGpes (
    484     void)
    485 {
    486     ACPI_STATUS             Status;
    487 
    488 
    489     ACPI_FUNCTION_TRACE (HwDisableAllGpes);
    490 
    491 
    492     Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
    493     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
    494     return_ACPI_STATUS (Status);
    495 }
    496 
    497 
    498 /******************************************************************************
    499  *
    500  * FUNCTION:    AcpiHwEnableAllRuntimeGpes
    501  *
    502  * PARAMETERS:  None
    503  *
    504  * RETURN:      Status
    505  *
    506  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
    507  *
    508  ******************************************************************************/
    509 
    510 ACPI_STATUS
    511 AcpiHwEnableAllRuntimeGpes (
    512     void)
    513 {
    514     ACPI_STATUS             Status;
    515 
    516 
    517     ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
    518 
    519 
    520     Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
    521     return_ACPI_STATUS (Status);
    522 }
    523 
    524 
    525 /******************************************************************************
    526  *
    527  * FUNCTION:    AcpiHwEnableAllWakeupGpes
    528  *
    529  * PARAMETERS:  None
    530  *
    531  * RETURN:      Status
    532  *
    533  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
    534  *
    535  ******************************************************************************/
    536 
    537 ACPI_STATUS
    538 AcpiHwEnableAllWakeupGpes (
    539     void)
    540 {
    541     ACPI_STATUS             Status;
    542 
    543 
    544     ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
    545 
    546 
    547     Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
    548     return_ACPI_STATUS (Status);
    549 }
    550 
    551 #endif /* !ACPI_REDUCED_HARDWARE */
    552