Home | History | Annotate | Line # | Download | only in hardware
hwgpe.c revision 1.1.1.6
      1 /******************************************************************************
      2  *
      3  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2015, 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 static ACPI_STATUS
     62 AcpiHwGpeEnableWrite (
     63     UINT8                   EnableMask,
     64     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo);
     65 
     66 
     67 /******************************************************************************
     68  *
     69  * FUNCTION:    AcpiHwGetGpeRegisterBit
     70  *
     71  * PARAMETERS:  GpeEventInfo        - Info block for the GPE
     72  *
     73  * RETURN:      Register mask with a one in the GPE bit position
     74  *
     75  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
     76  *              correct position for the input GPE.
     77  *
     78  ******************************************************************************/
     79 
     80 UINT32
     81 AcpiHwGetGpeRegisterBit (
     82     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
     83 {
     84 
     85     return ((UINT32) 1 <<
     86         (GpeEventInfo->GpeNumber - GpeEventInfo->RegisterInfo->BaseGpeNumber));
     87 }
     88 
     89 
     90 /******************************************************************************
     91  *
     92  * FUNCTION:    AcpiHwLowSetGpe
     93  *
     94  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be disabled
     95  *              Action              - Enable or disable
     96  *
     97  * RETURN:      Status
     98  *
     99  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
    100  *              The EnableMask field of the involved GPE register must be
    101  *              updated by the caller if necessary.
    102  *
    103  ******************************************************************************/
    104 
    105 ACPI_STATUS
    106 AcpiHwLowSetGpe (
    107     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    108     UINT32                  Action)
    109 {
    110     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    111     ACPI_STATUS             Status;
    112     UINT32                  EnableMask;
    113     UINT32                  RegisterBit;
    114 
    115 
    116     ACPI_FUNCTION_ENTRY ();
    117 
    118 
    119     /* Get the info block for the entire GPE register */
    120 
    121     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    122     if (!GpeRegisterInfo)
    123     {
    124         return (AE_NOT_EXIST);
    125     }
    126 
    127     /* Get current value of the enable register that contains this GPE */
    128 
    129     Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress);
    130     if (ACPI_FAILURE (Status))
    131     {
    132         return (Status);
    133     }
    134 
    135     /* Set or clear just the bit that corresponds to this GPE */
    136 
    137     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    138     switch (Action)
    139     {
    140     case ACPI_GPE_CONDITIONAL_ENABLE:
    141 
    142         /* Only enable if the corresponding EnableMask bit is set */
    143 
    144         if (!(RegisterBit & GpeRegisterInfo->EnableMask))
    145         {
    146             return (AE_BAD_PARAMETER);
    147         }
    148 
    149         /*lint -fallthrough */
    150 
    151     case ACPI_GPE_ENABLE:
    152 
    153         ACPI_SET_BIT (EnableMask, RegisterBit);
    154         break;
    155 
    156     case ACPI_GPE_DISABLE:
    157 
    158         ACPI_CLEAR_BIT (EnableMask, RegisterBit);
    159         break;
    160 
    161     default:
    162 
    163         ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u", Action));
    164         return (AE_BAD_PARAMETER);
    165     }
    166 
    167     /* Write the updated enable mask */
    168 
    169     Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
    170     return (Status);
    171 }
    172 
    173 
    174 /******************************************************************************
    175  *
    176  * FUNCTION:    AcpiHwClearGpe
    177  *
    178  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to be cleared
    179  *
    180  * RETURN:      Status
    181  *
    182  * DESCRIPTION: Clear the status bit for a single GPE.
    183  *
    184  ******************************************************************************/
    185 
    186 ACPI_STATUS
    187 AcpiHwClearGpe (
    188     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    189 {
    190     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    191     ACPI_STATUS             Status;
    192     UINT32                  RegisterBit;
    193 
    194 
    195     ACPI_FUNCTION_ENTRY ();
    196 
    197     /* Get the info block for the entire GPE register */
    198 
    199     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    200     if (!GpeRegisterInfo)
    201     {
    202         return (AE_NOT_EXIST);
    203     }
    204 
    205     /*
    206      * Write a one to the appropriate bit in the status register to
    207      * clear this GPE.
    208      */
    209     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    210 
    211     Status = AcpiHwWrite (RegisterBit,
    212                     &GpeRegisterInfo->StatusAddress);
    213 
    214     return (Status);
    215 }
    216 
    217 
    218 /******************************************************************************
    219  *
    220  * FUNCTION:    AcpiHwGetGpeStatus
    221  *
    222  * PARAMETERS:  GpeEventInfo        - Info block for the GPE to queried
    223  *              EventStatus         - Where the GPE status is returned
    224  *
    225  * RETURN:      Status
    226  *
    227  * DESCRIPTION: Return the status of a single GPE.
    228  *
    229  ******************************************************************************/
    230 
    231 ACPI_STATUS
    232 AcpiHwGetGpeStatus (
    233     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    234     ACPI_EVENT_STATUS       *EventStatus)
    235 {
    236     UINT32                  InByte;
    237     UINT32                  RegisterBit;
    238     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    239     ACPI_EVENT_STATUS       LocalEventStatus = 0;
    240     ACPI_STATUS             Status;
    241 
    242 
    243     ACPI_FUNCTION_ENTRY ();
    244 
    245 
    246     if (!EventStatus)
    247     {
    248         return (AE_BAD_PARAMETER);
    249     }
    250 
    251     /* GPE currently handled? */
    252 
    253     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
    254             ACPI_GPE_DISPATCH_NONE)
    255     {
    256         LocalEventStatus |= ACPI_EVENT_FLAG_HAS_HANDLER;
    257     }
    258 
    259     /* Get the info block for the entire GPE register */
    260 
    261     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    262 
    263     /* Get the register bitmask for this GPE */
    264 
    265     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    266 
    267     /* GPE currently enabled? (enabled for runtime?) */
    268 
    269     if (RegisterBit & GpeRegisterInfo->EnableForRun)
    270     {
    271         LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
    272     }
    273 
    274     /* GPE enabled for wake? */
    275 
    276     if (RegisterBit & GpeRegisterInfo->EnableForWake)
    277     {
    278         LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
    279     }
    280 
    281     /* GPE currently enabled (enable bit == 1)? */
    282 
    283     Status = AcpiHwRead (&InByte, &GpeRegisterInfo->EnableAddress);
    284     if (ACPI_FAILURE (Status))
    285     {
    286         return (Status);
    287     }
    288 
    289     if (RegisterBit & InByte)
    290     {
    291         LocalEventStatus |= ACPI_EVENT_FLAG_ENABLE_SET;
    292     }
    293 
    294     /* GPE currently active (status bit == 1)? */
    295 
    296     Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
    297     if (ACPI_FAILURE (Status))
    298     {
    299         return (Status);
    300     }
    301 
    302     if (RegisterBit & InByte)
    303     {
    304         LocalEventStatus |= ACPI_EVENT_FLAG_STATUS_SET;
    305     }
    306 
    307     /* Set return value */
    308 
    309     (*EventStatus) = LocalEventStatus;
    310     return (AE_OK);
    311 }
    312 
    313 
    314 /******************************************************************************
    315  *
    316  * FUNCTION:    AcpiHwGpeEnableWrite
    317  *
    318  * PARAMETERS:  EnableMask          - Bit mask to write to the GPE register
    319  *              GpeRegisterInfo     - Gpe Register info
    320  *
    321  * RETURN:      Status
    322  *
    323  * DESCRIPTION: Write the enable mask byte to the given GPE register.
    324  *
    325  ******************************************************************************/
    326 
    327 static ACPI_STATUS
    328 AcpiHwGpeEnableWrite (
    329     UINT8                   EnableMask,
    330     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo)
    331 {
    332     ACPI_STATUS             Status;
    333 
    334 
    335     GpeRegisterInfo->EnableMask = EnableMask;
    336     Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress);
    337 
    338     return (Status);
    339 }
    340 
    341 
    342 /******************************************************************************
    343  *
    344  * FUNCTION:    AcpiHwDisableGpeBlock
    345  *
    346  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    347  *              GpeBlock            - Gpe Block info
    348  *
    349  * RETURN:      Status
    350  *
    351  * DESCRIPTION: Disable all GPEs within a single GPE block
    352  *
    353  ******************************************************************************/
    354 
    355 ACPI_STATUS
    356 AcpiHwDisableGpeBlock (
    357     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    358     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    359     void                    *Context)
    360 {
    361     UINT32                  i;
    362     ACPI_STATUS             Status;
    363 
    364 
    365     /* Examine each GPE Register within the block */
    366 
    367     for (i = 0; i < GpeBlock->RegisterCount; i++)
    368     {
    369         /* Disable all GPEs in this register */
    370 
    371         Status = AcpiHwGpeEnableWrite (0x00, &GpeBlock->RegisterInfo[i]);
    372         if (ACPI_FAILURE (Status))
    373         {
    374             return (Status);
    375         }
    376     }
    377 
    378     return (AE_OK);
    379 }
    380 
    381 
    382 /******************************************************************************
    383  *
    384  * FUNCTION:    AcpiHwClearGpeBlock
    385  *
    386  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    387  *              GpeBlock            - Gpe Block info
    388  *
    389  * RETURN:      Status
    390  *
    391  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
    392  *
    393  ******************************************************************************/
    394 
    395 ACPI_STATUS
    396 AcpiHwClearGpeBlock (
    397     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    398     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    399     void                    *Context)
    400 {
    401     UINT32                  i;
    402     ACPI_STATUS             Status;
    403 
    404 
    405     /* Examine each GPE Register within the block */
    406 
    407     for (i = 0; i < GpeBlock->RegisterCount; i++)
    408     {
    409         /* Clear status on all GPEs in this register */
    410 
    411         Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
    412         if (ACPI_FAILURE (Status))
    413         {
    414             return (Status);
    415         }
    416     }
    417 
    418     return (AE_OK);
    419 }
    420 
    421 
    422 /******************************************************************************
    423  *
    424  * FUNCTION:    AcpiHwEnableRuntimeGpeBlock
    425  *
    426  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    427  *              GpeBlock            - Gpe Block info
    428  *
    429  * RETURN:      Status
    430  *
    431  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
    432  *              combination wake/run GPEs.
    433  *
    434  ******************************************************************************/
    435 
    436 ACPI_STATUS
    437 AcpiHwEnableRuntimeGpeBlock (
    438     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    439     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    440     void                    *Context)
    441 {
    442     UINT32                  i;
    443     ACPI_STATUS             Status;
    444     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    445 
    446 
    447     /* NOTE: assumes that all GPEs are currently disabled */
    448 
    449     /* Examine each GPE Register within the block */
    450 
    451     for (i = 0; i < GpeBlock->RegisterCount; i++)
    452     {
    453         GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
    454         if (!GpeRegisterInfo->EnableForRun)
    455         {
    456             continue;
    457         }
    458 
    459         /* Enable all "runtime" GPEs in this register */
    460 
    461         Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForRun,
    462                     GpeRegisterInfo);
    463         if (ACPI_FAILURE (Status))
    464         {
    465             return (Status);
    466         }
    467     }
    468 
    469     return (AE_OK);
    470 }
    471 
    472 
    473 /******************************************************************************
    474  *
    475  * FUNCTION:    AcpiHwEnableWakeupGpeBlock
    476  *
    477  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    478  *              GpeBlock            - Gpe Block info
    479  *
    480  * RETURN:      Status
    481  *
    482  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
    483  *              combination wake/run GPEs.
    484  *
    485  ******************************************************************************/
    486 
    487 static ACPI_STATUS
    488 AcpiHwEnableWakeupGpeBlock (
    489     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    490     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    491     void                    *Context)
    492 {
    493     UINT32                  i;
    494     ACPI_STATUS             Status;
    495     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    496 
    497 
    498     /* Examine each GPE Register within the block */
    499 
    500     for (i = 0; i < GpeBlock->RegisterCount; i++)
    501     {
    502         GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
    503 
    504         /*
    505          * Enable all "wake" GPEs in this register and disable the
    506          * remaining ones.
    507          */
    508         Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForWake,
    509                     GpeRegisterInfo);
    510         if (ACPI_FAILURE (Status))
    511         {
    512             return (Status);
    513         }
    514     }
    515 
    516     return (AE_OK);
    517 }
    518 
    519 
    520 /******************************************************************************
    521  *
    522  * FUNCTION:    AcpiHwDisableAllGpes
    523  *
    524  * PARAMETERS:  None
    525  *
    526  * RETURN:      Status
    527  *
    528  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
    529  *
    530  ******************************************************************************/
    531 
    532 ACPI_STATUS
    533 AcpiHwDisableAllGpes (
    534     void)
    535 {
    536     ACPI_STATUS             Status;
    537 
    538 
    539     ACPI_FUNCTION_TRACE (HwDisableAllGpes);
    540 
    541 
    542     Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
    543     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
    544     return_ACPI_STATUS (Status);
    545 }
    546 
    547 
    548 /******************************************************************************
    549  *
    550  * FUNCTION:    AcpiHwEnableAllRuntimeGpes
    551  *
    552  * PARAMETERS:  None
    553  *
    554  * RETURN:      Status
    555  *
    556  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
    557  *
    558  ******************************************************************************/
    559 
    560 ACPI_STATUS
    561 AcpiHwEnableAllRuntimeGpes (
    562     void)
    563 {
    564     ACPI_STATUS             Status;
    565 
    566 
    567     ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
    568 
    569 
    570     Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
    571     return_ACPI_STATUS (Status);
    572 }
    573 
    574 
    575 /******************************************************************************
    576  *
    577  * FUNCTION:    AcpiHwEnableAllWakeupGpes
    578  *
    579  * PARAMETERS:  None
    580  *
    581  * RETURN:      Status
    582  *
    583  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
    584  *
    585  ******************************************************************************/
    586 
    587 ACPI_STATUS
    588 AcpiHwEnableAllWakeupGpes (
    589     void)
    590 {
    591     ACPI_STATUS             Status;
    592 
    593 
    594     ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
    595 
    596 
    597     Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
    598     return_ACPI_STATUS (Status);
    599 }
    600 
    601 #endif /* !ACPI_REDUCED_HARDWARE */
    602