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