Home | History | Annotate | Line # | Download | only in hardware
hwgpe.c revision 1.1.1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2013, 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     /* Get the info block for the entire GPE register */
    245 
    246     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    247 
    248     /* Get the register bitmask for this GPE */
    249 
    250     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    251 
    252     /* GPE currently enabled? (enabled for runtime?) */
    253 
    254     if (RegisterBit & GpeRegisterInfo->EnableForRun)
    255     {
    256         LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED;
    257     }
    258 
    259     /* GPE enabled for wake? */
    260 
    261     if (RegisterBit & GpeRegisterInfo->EnableForWake)
    262     {
    263         LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED;
    264     }
    265 
    266     /* GPE currently active (status bit == 1)? */
    267 
    268     Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress);
    269     if (ACPI_FAILURE (Status))
    270     {
    271         return (Status);
    272     }
    273 
    274     if (RegisterBit & InByte)
    275     {
    276         LocalEventStatus |= ACPI_EVENT_FLAG_SET;
    277     }
    278 
    279     /* Set return value */
    280 
    281     (*EventStatus) = LocalEventStatus;
    282     return (AE_OK);
    283 }
    284 
    285 
    286 /******************************************************************************
    287  *
    288  * FUNCTION:    AcpiHwDisableGpeBlock
    289  *
    290  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    291  *              GpeBlock            - Gpe Block info
    292  *
    293  * RETURN:      Status
    294  *
    295  * DESCRIPTION: Disable all GPEs within a single GPE block
    296  *
    297  ******************************************************************************/
    298 
    299 ACPI_STATUS
    300 AcpiHwDisableGpeBlock (
    301     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    302     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    303     void                    *Context)
    304 {
    305     UINT32                  i;
    306     ACPI_STATUS             Status;
    307 
    308 
    309     /* Examine each GPE Register within the block */
    310 
    311     for (i = 0; i < GpeBlock->RegisterCount; i++)
    312     {
    313         /* Disable all GPEs in this register */
    314 
    315         Status = AcpiHwWrite (0x00, &GpeBlock->RegisterInfo[i].EnableAddress);
    316         if (ACPI_FAILURE (Status))
    317         {
    318             return (Status);
    319         }
    320     }
    321 
    322     return (AE_OK);
    323 }
    324 
    325 
    326 /******************************************************************************
    327  *
    328  * FUNCTION:    AcpiHwClearGpeBlock
    329  *
    330  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    331  *              GpeBlock            - Gpe Block info
    332  *
    333  * RETURN:      Status
    334  *
    335  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
    336  *
    337  ******************************************************************************/
    338 
    339 ACPI_STATUS
    340 AcpiHwClearGpeBlock (
    341     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    342     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    343     void                    *Context)
    344 {
    345     UINT32                  i;
    346     ACPI_STATUS             Status;
    347 
    348 
    349     /* Examine each GPE Register within the block */
    350 
    351     for (i = 0; i < GpeBlock->RegisterCount; i++)
    352     {
    353         /* Clear status on all GPEs in this register */
    354 
    355         Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress);
    356         if (ACPI_FAILURE (Status))
    357         {
    358             return (Status);
    359         }
    360     }
    361 
    362     return (AE_OK);
    363 }
    364 
    365 
    366 /******************************************************************************
    367  *
    368  * FUNCTION:    AcpiHwEnableRuntimeGpeBlock
    369  *
    370  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    371  *              GpeBlock            - Gpe Block info
    372  *
    373  * RETURN:      Status
    374  *
    375  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
    376  *              combination wake/run GPEs.
    377  *
    378  ******************************************************************************/
    379 
    380 ACPI_STATUS
    381 AcpiHwEnableRuntimeGpeBlock (
    382     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    383     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    384     void                    *Context)
    385 {
    386     UINT32                  i;
    387     ACPI_STATUS             Status;
    388 
    389 
    390     /* NOTE: assumes that all GPEs are currently disabled */
    391 
    392     /* Examine each GPE Register within the block */
    393 
    394     for (i = 0; i < GpeBlock->RegisterCount; i++)
    395     {
    396         if (!GpeBlock->RegisterInfo[i].EnableForRun)
    397         {
    398             continue;
    399         }
    400 
    401         /* Enable all "runtime" GPEs in this register */
    402 
    403         Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun,
    404                     &GpeBlock->RegisterInfo[i].EnableAddress);
    405         if (ACPI_FAILURE (Status))
    406         {
    407             return (Status);
    408         }
    409     }
    410 
    411     return (AE_OK);
    412 }
    413 
    414 
    415 /******************************************************************************
    416  *
    417  * FUNCTION:    AcpiHwEnableWakeupGpeBlock
    418  *
    419  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    420  *              GpeBlock            - Gpe Block info
    421  *
    422  * RETURN:      Status
    423  *
    424  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
    425  *              combination wake/run GPEs.
    426  *
    427  ******************************************************************************/
    428 
    429 static ACPI_STATUS
    430 AcpiHwEnableWakeupGpeBlock (
    431     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    432     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    433     void                    *Context)
    434 {
    435     UINT32                  i;
    436     ACPI_STATUS             Status;
    437 
    438 
    439     /* Examine each GPE Register within the block */
    440 
    441     for (i = 0; i < GpeBlock->RegisterCount; i++)
    442     {
    443         if (!GpeBlock->RegisterInfo[i].EnableForWake)
    444         {
    445             continue;
    446         }
    447 
    448         /* Enable all "wake" GPEs in this register */
    449 
    450         Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake,
    451                     &GpeBlock->RegisterInfo[i].EnableAddress);
    452         if (ACPI_FAILURE (Status))
    453         {
    454             return (Status);
    455         }
    456     }
    457 
    458     return (AE_OK);
    459 }
    460 
    461 
    462 /******************************************************************************
    463  *
    464  * FUNCTION:    AcpiHwDisableAllGpes
    465  *
    466  * PARAMETERS:  None
    467  *
    468  * RETURN:      Status
    469  *
    470  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
    471  *
    472  ******************************************************************************/
    473 
    474 ACPI_STATUS
    475 AcpiHwDisableAllGpes (
    476     void)
    477 {
    478     ACPI_STATUS             Status;
    479 
    480 
    481     ACPI_FUNCTION_TRACE (HwDisableAllGpes);
    482 
    483 
    484     Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
    485     Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL);
    486     return_ACPI_STATUS (Status);
    487 }
    488 
    489 
    490 /******************************************************************************
    491  *
    492  * FUNCTION:    AcpiHwEnableAllRuntimeGpes
    493  *
    494  * PARAMETERS:  None
    495  *
    496  * RETURN:      Status
    497  *
    498  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
    499  *
    500  ******************************************************************************/
    501 
    502 ACPI_STATUS
    503 AcpiHwEnableAllRuntimeGpes (
    504     void)
    505 {
    506     ACPI_STATUS             Status;
    507 
    508 
    509     ACPI_FUNCTION_TRACE (HwEnableAllRuntimeGpes);
    510 
    511 
    512     Status = AcpiEvWalkGpeList (AcpiHwEnableRuntimeGpeBlock, NULL);
    513     return_ACPI_STATUS (Status);
    514 }
    515 
    516 
    517 /******************************************************************************
    518  *
    519  * FUNCTION:    AcpiHwEnableAllWakeupGpes
    520  *
    521  * PARAMETERS:  None
    522  *
    523  * RETURN:      Status
    524  *
    525  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
    526  *
    527  ******************************************************************************/
    528 
    529 ACPI_STATUS
    530 AcpiHwEnableAllWakeupGpes (
    531     void)
    532 {
    533     ACPI_STATUS             Status;
    534 
    535 
    536     ACPI_FUNCTION_TRACE (HwEnableAllWakeupGpes);
    537 
    538 
    539     Status = AcpiEvWalkGpeList (AcpiHwEnableWakeupGpeBlock, NULL);
    540     return_ACPI_STATUS (Status);
    541 }
    542 
    543 #endif /* !ACPI_REDUCED_HARDWARE */
    544