Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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/acpi.h>
  45. #include "accommon.h"
  46. #include "acevents.h"
  47.  
  48. #define _COMPONENT          ACPI_HARDWARE
  49. ACPI_MODULE_NAME("hwgpe")
  50. #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
  51. /* Local prototypes */
  52. static acpi_status
  53. acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  54.                                 struct acpi_gpe_block_info *gpe_block,
  55.                                 void *context);
  56.  
  57. static acpi_status
  58. acpi_hw_gpe_enable_write(u8 enable_mask,
  59.                          struct acpi_gpe_register_info *gpe_register_info);
  60.  
  61. /******************************************************************************
  62.  *
  63.  * FUNCTION:    acpi_hw_get_gpe_register_bit
  64.  *
  65.  * PARAMETERS:  gpe_event_info      - Info block for the GPE
  66.  *
  67.  * RETURN:      Register mask with a one in the GPE bit position
  68.  *
  69.  * DESCRIPTION: Compute the register mask for this GPE. One bit is set in the
  70.  *              correct position for the input GPE.
  71.  *
  72.  ******************************************************************************/
  73.  
  74. u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
  75. {
  76.  
  77.         return ((u32)1 <<
  78.                 (gpe_event_info->gpe_number -
  79.                  gpe_event_info->register_info->base_gpe_number));
  80. }
  81.  
  82. /******************************************************************************
  83.  *
  84.  * FUNCTION:    acpi_hw_low_set_gpe
  85.  *
  86.  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
  87.  *              action              - Enable or disable
  88.  *
  89.  * RETURN:      Status
  90.  *
  91.  * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
  92.  *              The enable_mask field of the involved GPE register must be
  93.  *              updated by the caller if necessary.
  94.  *
  95.  ******************************************************************************/
  96.  
  97. acpi_status
  98. acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
  99. {
  100.         struct acpi_gpe_register_info *gpe_register_info;
  101.         acpi_status status;
  102.         u32 enable_mask;
  103.         u32 register_bit;
  104.  
  105.         ACPI_FUNCTION_ENTRY();
  106.  
  107.         /* Get the info block for the entire GPE register */
  108.  
  109.         gpe_register_info = gpe_event_info->register_info;
  110.         if (!gpe_register_info) {
  111.                 return (AE_NOT_EXIST);
  112.         }
  113.  
  114.         /* Get current value of the enable register that contains this GPE */
  115.  
  116.         status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
  117.         if (ACPI_FAILURE(status)) {
  118.                 return (status);
  119.         }
  120.  
  121.         /* Set or clear just the bit that corresponds to this GPE */
  122.  
  123.         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
  124.         switch (action) {
  125.         case ACPI_GPE_CONDITIONAL_ENABLE:
  126.  
  127.                 /* Only enable if the corresponding enable_mask bit is set */
  128.  
  129.                 if (!(register_bit & gpe_register_info->enable_mask)) {
  130.                         return (AE_BAD_PARAMETER);
  131.                 }
  132.  
  133.                 /*lint -fallthrough */
  134.  
  135.         case ACPI_GPE_ENABLE:
  136.  
  137.                 ACPI_SET_BIT(enable_mask, register_bit);
  138.                 break;
  139.  
  140.         case ACPI_GPE_DISABLE:
  141.  
  142.                 ACPI_CLEAR_BIT(enable_mask, register_bit);
  143.                 break;
  144.  
  145.         default:
  146.  
  147.                 ACPI_ERROR((AE_INFO, "Invalid GPE Action, %u", action));
  148.                 return (AE_BAD_PARAMETER);
  149.         }
  150.  
  151.         /* Write the updated enable mask */
  152.  
  153.         status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
  154.         return (status);
  155. }
  156.  
  157. /******************************************************************************
  158.  *
  159.  * FUNCTION:    acpi_hw_clear_gpe
  160.  *
  161.  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
  162.  *
  163.  * RETURN:      Status
  164.  *
  165.  * DESCRIPTION: Clear the status bit for a single GPE.
  166.  *
  167.  ******************************************************************************/
  168.  
  169. acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
  170. {
  171.         struct acpi_gpe_register_info *gpe_register_info;
  172.         acpi_status status;
  173.         u32 register_bit;
  174.  
  175.         ACPI_FUNCTION_ENTRY();
  176.  
  177.         /* Get the info block for the entire GPE register */
  178.  
  179.         gpe_register_info = gpe_event_info->register_info;
  180.         if (!gpe_register_info) {
  181.                 return (AE_NOT_EXIST);
  182.         }
  183.  
  184.         /*
  185.          * Write a one to the appropriate bit in the status register to
  186.          * clear this GPE.
  187.          */
  188.         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
  189.  
  190.         status = acpi_hw_write(register_bit,
  191.                                &gpe_register_info->status_address);
  192.  
  193.         return (status);
  194. }
  195.  
  196. /******************************************************************************
  197.  *
  198.  * FUNCTION:    acpi_hw_get_gpe_status
  199.  *
  200.  * PARAMETERS:  gpe_event_info      - Info block for the GPE to queried
  201.  *              event_status        - Where the GPE status is returned
  202.  *
  203.  * RETURN:      Status
  204.  *
  205.  * DESCRIPTION: Return the status of a single GPE.
  206.  *
  207.  ******************************************************************************/
  208.  
  209. acpi_status
  210. acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
  211.                        acpi_event_status *event_status)
  212. {
  213.         u32 in_byte;
  214.         u32 register_bit;
  215.         struct acpi_gpe_register_info *gpe_register_info;
  216.         acpi_event_status local_event_status = 0;
  217.         acpi_status status;
  218.  
  219.         ACPI_FUNCTION_ENTRY();
  220.  
  221.         if (!event_status) {
  222.                 return (AE_BAD_PARAMETER);
  223.         }
  224.  
  225.         /* GPE currently handled? */
  226.  
  227.         if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
  228.             ACPI_GPE_DISPATCH_NONE) {
  229.                 local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
  230.         }
  231.  
  232.         /* Get the info block for the entire GPE register */
  233.  
  234.         gpe_register_info = gpe_event_info->register_info;
  235.  
  236.         /* Get the register bitmask for this GPE */
  237.  
  238.         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
  239.  
  240.         /* GPE currently enabled? (enabled for runtime?) */
  241.  
  242.         if (register_bit & gpe_register_info->enable_for_run) {
  243.                 local_event_status |= ACPI_EVENT_FLAG_ENABLED;
  244.         }
  245.  
  246.         /* GPE enabled for wake? */
  247.  
  248.         if (register_bit & gpe_register_info->enable_for_wake) {
  249.                 local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
  250.         }
  251.  
  252.         /* GPE currently enabled (enable bit == 1)? */
  253.  
  254.         status = acpi_hw_read(&in_byte, &gpe_register_info->enable_address);
  255.         if (ACPI_FAILURE(status)) {
  256.                 return (status);
  257.         }
  258.  
  259.         if (register_bit & in_byte) {
  260.                 local_event_status |= ACPI_EVENT_FLAG_ENABLE_SET;
  261.         }
  262.  
  263.         /* GPE currently active (status bit == 1)? */
  264.  
  265.         status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
  266.         if (ACPI_FAILURE(status)) {
  267.                 return (status);
  268.         }
  269.  
  270.         if (register_bit & in_byte) {
  271.                 local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
  272.         }
  273.  
  274.         /* Set return value */
  275.  
  276.         (*event_status) = local_event_status;
  277.         return (AE_OK);
  278. }
  279.  
  280. /******************************************************************************
  281.  *
  282.  * FUNCTION:    acpi_hw_gpe_enable_write
  283.  *
  284.  * PARAMETERS:  enable_mask         - Bit mask to write to the GPE register
  285.  *              gpe_register_info   - Gpe Register info
  286.  *
  287.  * RETURN:      Status
  288.  *
  289.  * DESCRIPTION: Write the enable mask byte to the given GPE register.
  290.  *
  291.  ******************************************************************************/
  292.  
  293. static acpi_status
  294. acpi_hw_gpe_enable_write(u8 enable_mask,
  295.                          struct acpi_gpe_register_info *gpe_register_info)
  296. {
  297.         acpi_status status;
  298.  
  299.         gpe_register_info->enable_mask = enable_mask;
  300.         status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
  301.         return (status);
  302. }
  303.  
  304. /******************************************************************************
  305.  *
  306.  * FUNCTION:    acpi_hw_disable_gpe_block
  307.  *
  308.  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  309.  *              gpe_block           - Gpe Block info
  310.  *
  311.  * RETURN:      Status
  312.  *
  313.  * DESCRIPTION: Disable all GPEs within a single GPE block
  314.  *
  315.  ******************************************************************************/
  316.  
  317. acpi_status
  318. acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  319.                           struct acpi_gpe_block_info *gpe_block, void *context)
  320. {
  321.         u32 i;
  322.         acpi_status status;
  323.  
  324.         /* Examine each GPE Register within the block */
  325.  
  326.         for (i = 0; i < gpe_block->register_count; i++) {
  327.  
  328.                 /* Disable all GPEs in this register */
  329.  
  330.                 status =
  331.                     acpi_hw_gpe_enable_write(0x00,
  332.                                              &gpe_block->register_info[i]);
  333.                 if (ACPI_FAILURE(status)) {
  334.                         return (status);
  335.                 }
  336.         }
  337.  
  338.         return (AE_OK);
  339. }
  340.  
  341. /******************************************************************************
  342.  *
  343.  * FUNCTION:    acpi_hw_clear_gpe_block
  344.  *
  345.  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  346.  *              gpe_block           - Gpe Block info
  347.  *
  348.  * RETURN:      Status
  349.  *
  350.  * DESCRIPTION: Clear status bits for all GPEs within a single GPE block
  351.  *
  352.  ******************************************************************************/
  353.  
  354. acpi_status
  355. acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  356.                         struct acpi_gpe_block_info *gpe_block, void *context)
  357. {
  358.         u32 i;
  359.         acpi_status status;
  360.  
  361.         /* Examine each GPE Register within the block */
  362.  
  363.         for (i = 0; i < gpe_block->register_count; i++) {
  364.  
  365.                 /* Clear status on all GPEs in this register */
  366.  
  367.                 status =
  368.                     acpi_hw_write(0xFF,
  369.                                   &gpe_block->register_info[i].status_address);
  370.                 if (ACPI_FAILURE(status)) {
  371.                         return (status);
  372.                 }
  373.         }
  374.  
  375.         return (AE_OK);
  376. }
  377.  
  378. /******************************************************************************
  379.  *
  380.  * FUNCTION:    acpi_hw_enable_runtime_gpe_block
  381.  *
  382.  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  383.  *              gpe_block           - Gpe Block info
  384.  *
  385.  * RETURN:      Status
  386.  *
  387.  * DESCRIPTION: Enable all "runtime" GPEs within a single GPE block. Includes
  388.  *              combination wake/run GPEs.
  389.  *
  390.  ******************************************************************************/
  391.  
  392. acpi_status
  393. acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  394.                                  struct acpi_gpe_block_info * gpe_block,
  395.                                  void *context)
  396. {
  397.         u32 i;
  398.         acpi_status status;
  399.         struct acpi_gpe_register_info *gpe_register_info;
  400.  
  401.         /* NOTE: assumes that all GPEs are currently disabled */
  402.  
  403.         /* Examine each GPE Register within the block */
  404.  
  405.         for (i = 0; i < gpe_block->register_count; i++) {
  406.                 gpe_register_info = &gpe_block->register_info[i];
  407.                 if (!gpe_register_info->enable_for_run) {
  408.                         continue;
  409.                 }
  410.  
  411.                 /* Enable all "runtime" GPEs in this register */
  412.  
  413.                 status =
  414.                     acpi_hw_gpe_enable_write(gpe_register_info->enable_for_run,
  415.                                              gpe_register_info);
  416.                 if (ACPI_FAILURE(status)) {
  417.                         return (status);
  418.                 }
  419.         }
  420.  
  421.         return (AE_OK);
  422. }
  423.  
  424. /******************************************************************************
  425.  *
  426.  * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
  427.  *
  428.  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  429.  *              gpe_block           - Gpe Block info
  430.  *
  431.  * RETURN:      Status
  432.  *
  433.  * DESCRIPTION: Enable all "wake" GPEs within a single GPE block. Includes
  434.  *              combination wake/run GPEs.
  435.  *
  436.  ******************************************************************************/
  437.  
  438. static acpi_status
  439. acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  440.                                 struct acpi_gpe_block_info *gpe_block,
  441.                                 void *context)
  442. {
  443.         u32 i;
  444.         acpi_status status;
  445.         struct acpi_gpe_register_info *gpe_register_info;
  446.  
  447.         /* Examine each GPE Register within the block */
  448.  
  449.         for (i = 0; i < gpe_block->register_count; i++) {
  450.                 gpe_register_info = &gpe_block->register_info[i];
  451.  
  452.                 /*
  453.                  * Enable all "wake" GPEs in this register and disable the
  454.                  * remaining ones.
  455.                  */
  456.  
  457.                 status =
  458.                     acpi_hw_gpe_enable_write(gpe_register_info->enable_for_wake,
  459.                                              gpe_register_info);
  460.                 if (ACPI_FAILURE(status)) {
  461.                         return (status);
  462.                 }
  463.         }
  464.  
  465.         return (AE_OK);
  466. }
  467.  
  468. /******************************************************************************
  469.  *
  470.  * FUNCTION:    acpi_hw_disable_all_gpes
  471.  *
  472.  * PARAMETERS:  None
  473.  *
  474.  * RETURN:      Status
  475.  *
  476.  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
  477.  *
  478.  ******************************************************************************/
  479.  
  480. acpi_status acpi_hw_disable_all_gpes(void)
  481. {
  482.         acpi_status status;
  483.  
  484.         ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
  485.  
  486.         status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
  487.         status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
  488.         return_ACPI_STATUS(status);
  489. }
  490.  
  491. /******************************************************************************
  492.  *
  493.  * FUNCTION:    acpi_hw_enable_all_runtime_gpes
  494.  *
  495.  * PARAMETERS:  None
  496.  *
  497.  * RETURN:      Status
  498.  *
  499.  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
  500.  *
  501.  ******************************************************************************/
  502.  
  503. acpi_status acpi_hw_enable_all_runtime_gpes(void)
  504. {
  505.         acpi_status status;
  506.  
  507.         ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
  508.  
  509.         status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
  510.         return_ACPI_STATUS(status);
  511. }
  512.  
  513. /******************************************************************************
  514.  *
  515.  * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
  516.  *
  517.  * PARAMETERS:  None
  518.  *
  519.  * RETURN:      Status
  520.  *
  521.  * DESCRIPTION: Enable all "wakeup" GPEs, in all GPE blocks
  522.  *
  523.  ******************************************************************************/
  524.  
  525. acpi_status acpi_hw_enable_all_wakeup_gpes(void)
  526. {
  527.         acpi_status status;
  528.  
  529.         ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
  530.  
  531.         status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
  532.         return_ACPI_STATUS(status);
  533. }
  534.  
  535. #endif                          /* !ACPI_REDUCED_HARDWARE */
  536.