Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: evgpeinit - System GPE initialization and update
  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. #include "acnamesp.h"
  48.  
  49. #define _COMPONENT          ACPI_EVENTS
  50. ACPI_MODULE_NAME("evgpeinit")
  51. #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
  52. /*
  53.  * Note: History of _PRW support in ACPICA
  54.  *
  55.  * Originally (2000 - 2010), the GPE initialization code performed a walk of
  56.  * the entire namespace to execute the _PRW methods and detect all GPEs
  57.  * capable of waking the system.
  58.  *
  59.  * As of 10/2010, the _PRW method execution has been removed since it is
  60.  * actually unnecessary. The host OS must in fact execute all _PRW methods
  61.  * in order to identify the device/power-resource dependencies. We now put
  62.  * the onus on the host OS to identify the wake GPEs as part of this process
  63.  * and to inform ACPICA of these GPEs via the acpi_setup_gpe_for_wake interface. This
  64.  * not only reduces the complexity of the ACPICA initialization code, but in
  65.  * some cases (on systems with very large namespaces) it should reduce the
  66.  * kernel boot time as well.
  67.  */
  68.  
  69. /*******************************************************************************
  70.  *
  71.  * FUNCTION:    acpi_ev_gpe_initialize
  72.  *
  73.  * PARAMETERS:  None
  74.  *
  75.  * RETURN:      Status
  76.  *
  77.  * DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks
  78.  *
  79.  ******************************************************************************/
  80. acpi_status acpi_ev_gpe_initialize(void)
  81. {
  82.         u32 register_count0 = 0;
  83.         u32 register_count1 = 0;
  84.         u32 gpe_number_max = 0;
  85.         acpi_status status;
  86.  
  87.         ACPI_FUNCTION_TRACE(ev_gpe_initialize);
  88.  
  89.         ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
  90.                               "Initializing General Purpose Events (GPEs):\n"));
  91.  
  92.         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  93.         if (ACPI_FAILURE(status)) {
  94.                 return_ACPI_STATUS(status);
  95.         }
  96.  
  97.         /*
  98.          * Initialize the GPE Block(s) defined in the FADT
  99.          *
  100.          * Why the GPE register block lengths are divided by 2:  From the ACPI
  101.          * Spec, section "General-Purpose Event Registers", we have:
  102.          *
  103.          * "Each register block contains two registers of equal length
  104.          *  GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
  105.          *  GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
  106.          *  The length of the GPE1_STS and GPE1_EN registers is equal to
  107.          *  half the GPE1_LEN. If a generic register block is not supported
  108.          *  then its respective block pointer and block length values in the
  109.          *  FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
  110.          *  to be the same size."
  111.          */
  112.  
  113.         /*
  114.          * Determine the maximum GPE number for this machine.
  115.          *
  116.          * Note: both GPE0 and GPE1 are optional, and either can exist without
  117.          * the other.
  118.          *
  119.          * If EITHER the register length OR the block address are zero, then that
  120.          * particular block is not supported.
  121.          */
  122.         if (acpi_gbl_FADT.gpe0_block_length &&
  123.             acpi_gbl_FADT.xgpe0_block.address) {
  124.  
  125.                 /* GPE block 0 exists (has both length and address > 0) */
  126.  
  127.                 register_count0 = (u16)(acpi_gbl_FADT.gpe0_block_length / 2);
  128.                 gpe_number_max =
  129.                     (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
  130.  
  131.                 /* Install GPE Block 0 */
  132.  
  133.                 status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
  134.                                                   acpi_gbl_FADT.xgpe0_block.
  135.                                                   address,
  136.                                                   acpi_gbl_FADT.xgpe0_block.
  137.                                                   space_id, register_count0, 0,
  138.                                                   acpi_gbl_FADT.sci_interrupt,
  139.                                                   &acpi_gbl_gpe_fadt_blocks[0]);
  140.  
  141.                 if (ACPI_FAILURE(status)) {
  142.                         ACPI_EXCEPTION((AE_INFO, status,
  143.                                         "Could not create GPE Block 0"));
  144.                 }
  145.         }
  146.  
  147.         if (acpi_gbl_FADT.gpe1_block_length &&
  148.             acpi_gbl_FADT.xgpe1_block.address) {
  149.  
  150.                 /* GPE block 1 exists (has both length and address > 0) */
  151.  
  152.                 register_count1 = (u16)(acpi_gbl_FADT.gpe1_block_length / 2);
  153.  
  154.                 /* Check for GPE0/GPE1 overlap (if both banks exist) */
  155.  
  156.                 if ((register_count0) &&
  157.                     (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) {
  158.                         ACPI_ERROR((AE_INFO,
  159.                                     "GPE0 block (GPE 0 to %u) overlaps the GPE1 block "
  160.                                     "(GPE %u to %u) - Ignoring GPE1",
  161.                                     gpe_number_max, acpi_gbl_FADT.gpe1_base,
  162.                                     acpi_gbl_FADT.gpe1_base +
  163.                                     ((register_count1 *
  164.                                       ACPI_GPE_REGISTER_WIDTH) - 1)));
  165.  
  166.                         /* Ignore GPE1 block by setting the register count to zero */
  167.  
  168.                         register_count1 = 0;
  169.                 } else {
  170.                         /* Install GPE Block 1 */
  171.  
  172.                         status =
  173.                             acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
  174.                                                      acpi_gbl_FADT.xgpe1_block.
  175.                                                      address,
  176.                                                      acpi_gbl_FADT.xgpe1_block.
  177.                                                      space_id, register_count1,
  178.                                                      acpi_gbl_FADT.gpe1_base,
  179.                                                      acpi_gbl_FADT.
  180.                                                      sci_interrupt,
  181.                                                      &acpi_gbl_gpe_fadt_blocks
  182.                                                      [1]);
  183.  
  184.                         if (ACPI_FAILURE(status)) {
  185.                                 ACPI_EXCEPTION((AE_INFO, status,
  186.                                                 "Could not create GPE Block 1"));
  187.                         }
  188.  
  189.                         /*
  190.                          * GPE0 and GPE1 do not have to be contiguous in the GPE number
  191.                          * space. However, GPE0 always starts at GPE number zero.
  192.                          */
  193.                         gpe_number_max = acpi_gbl_FADT.gpe1_base +
  194.                             ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1);
  195.                 }
  196.         }
  197.  
  198.         /* Exit if there are no GPE registers */
  199.  
  200.         if ((register_count0 + register_count1) == 0) {
  201.  
  202.                 /* GPEs are not required by ACPI, this is OK */
  203.  
  204.                 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
  205.                                   "There are no GPE blocks defined in the FADT\n"));
  206.                 status = AE_OK;
  207.                 goto cleanup;
  208.         }
  209.  
  210. cleanup:
  211.         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  212.         return_ACPI_STATUS(AE_OK);
  213. }
  214.  
  215. /*******************************************************************************
  216.  *
  217.  * FUNCTION:    acpi_ev_update_gpes
  218.  *
  219.  * PARAMETERS:  table_owner_id      - ID of the newly-loaded ACPI table
  220.  *
  221.  * RETURN:      None
  222.  *
  223.  * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
  224.  *              result of a Load() or load_table() operation. If new GPE
  225.  *              methods have been installed, register the new methods.
  226.  *
  227.  ******************************************************************************/
  228.  
  229. void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
  230. {
  231.         struct acpi_gpe_xrupt_info *gpe_xrupt_info;
  232.         struct acpi_gpe_block_info *gpe_block;
  233.         struct acpi_gpe_walk_info walk_info;
  234.         acpi_status status = AE_OK;
  235.  
  236.         /*
  237.          * Find any _Lxx/_Exx GPE methods that have just been loaded.
  238.          *
  239.          * Any GPEs that correspond to new _Lxx/_Exx methods are immediately
  240.          * enabled.
  241.          *
  242.          * Examine the namespace underneath each gpe_device within the
  243.          * gpe_block lists.
  244.          */
  245.         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  246.         if (ACPI_FAILURE(status)) {
  247.                 return;
  248.         }
  249.  
  250.         walk_info.count = 0;
  251.         walk_info.owner_id = table_owner_id;
  252.         walk_info.execute_by_owner_id = TRUE;
  253.  
  254.         /* Walk the interrupt level descriptor list */
  255.  
  256.         gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
  257.         while (gpe_xrupt_info) {
  258.  
  259.                 /* Walk all Gpe Blocks attached to this interrupt level */
  260.  
  261.                 gpe_block = gpe_xrupt_info->gpe_block_list_head;
  262.                 while (gpe_block) {
  263.                         walk_info.gpe_block = gpe_block;
  264.                         walk_info.gpe_device = gpe_block->node;
  265.  
  266.                         status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD,
  267.                                                         walk_info.gpe_device,
  268.                                                         ACPI_UINT32_MAX,
  269.                                                         ACPI_NS_WALK_NO_UNLOCK,
  270.                                                         acpi_ev_match_gpe_method,
  271.                                                         NULL, &walk_info, NULL);
  272.                         if (ACPI_FAILURE(status)) {
  273.                                 ACPI_EXCEPTION((AE_INFO, status,
  274.                                                 "While decoding _Lxx/_Exx methods"));
  275.                         }
  276.  
  277.                         gpe_block = gpe_block->next;
  278.                 }
  279.  
  280.                 gpe_xrupt_info = gpe_xrupt_info->next;
  281.         }
  282.  
  283.         if (walk_info.count) {
  284.                 ACPI_INFO((AE_INFO, "Enabled %u new GPEs", walk_info.count));
  285.         }
  286.  
  287.         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  288.         return;
  289. }
  290.  
  291. /*******************************************************************************
  292.  *
  293.  * FUNCTION:    acpi_ev_match_gpe_method
  294.  *
  295.  * PARAMETERS:  Callback from walk_namespace
  296.  *
  297.  * RETURN:      Status
  298.  *
  299.  * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
  300.  *              control method under the _GPE portion of the namespace.
  301.  *              Extract the name and GPE type from the object, saving this
  302.  *              information for quick lookup during GPE dispatch. Allows a
  303.  *              per-owner_id evaluation if execute_by_owner_id is TRUE in the
  304.  *              walk_info parameter block.
  305.  *
  306.  *              The name of each GPE control method is of the form:
  307.  *              "_Lxx" or "_Exx", where:
  308.  *                  L      - means that the GPE is level triggered
  309.  *                  E      - means that the GPE is edge triggered
  310.  *                  xx     - is the GPE number [in HEX]
  311.  *
  312.  * If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods
  313.  * with that owner.
  314.  *
  315.  ******************************************************************************/
  316.  
  317. acpi_status
  318. acpi_ev_match_gpe_method(acpi_handle obj_handle,
  319.                          u32 level, void *context, void **return_value)
  320. {
  321.         struct acpi_namespace_node *method_node =
  322.             ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
  323.         struct acpi_gpe_walk_info *walk_info =
  324.             ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
  325.         struct acpi_gpe_event_info *gpe_event_info;
  326.         u32 gpe_number;
  327.         char name[ACPI_NAME_SIZE + 1];
  328.         u8 type;
  329.  
  330.         ACPI_FUNCTION_TRACE(ev_match_gpe_method);
  331.  
  332.         /* Check if requested owner_id matches this owner_id */
  333.  
  334.         if ((walk_info->execute_by_owner_id) &&
  335.             (method_node->owner_id != walk_info->owner_id)) {
  336.                 return_ACPI_STATUS(AE_OK);
  337.         }
  338.  
  339.         /*
  340.          * Match and decode the _Lxx and _Exx GPE method names
  341.          *
  342.          * 1) Extract the method name and null terminate it
  343.          */
  344.         ACPI_MOVE_32_TO_32(name, &method_node->name.integer);
  345.         name[ACPI_NAME_SIZE] = 0;
  346.  
  347.         /* 2) Name must begin with an underscore */
  348.  
  349.         if (name[0] != '_') {
  350.                 return_ACPI_STATUS(AE_OK);      /* Ignore this method */
  351.         }
  352.  
  353.         /*
  354.          * 3) Edge/Level determination is based on the 2nd character
  355.          *    of the method name
  356.          */
  357.         switch (name[1]) {
  358.         case 'L':
  359.  
  360.                 type = ACPI_GPE_LEVEL_TRIGGERED;
  361.                 break;
  362.  
  363.         case 'E':
  364.  
  365.                 type = ACPI_GPE_EDGE_TRIGGERED;
  366.                 break;
  367.  
  368.         default:
  369.  
  370.                 /* Unknown method type, just ignore it */
  371.  
  372.                 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
  373.                                   "Ignoring unknown GPE method type: %s "
  374.                                   "(name not of form _Lxx or _Exx)", name));
  375.                 return_ACPI_STATUS(AE_OK);
  376.         }
  377.  
  378.         /* 4) The last two characters of the name are the hex GPE Number */
  379.  
  380.         gpe_number = strtoul(&name[2], NULL, 16);
  381.         if (gpe_number == ACPI_UINT32_MAX) {
  382.  
  383.                 /* Conversion failed; invalid method, just ignore it */
  384.  
  385.                 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
  386.                                   "Could not extract GPE number from name: %s "
  387.                                   "(name is not of form _Lxx or _Exx)", name));
  388.                 return_ACPI_STATUS(AE_OK);
  389.         }
  390.  
  391.         /* Ensure that we have a valid GPE number for this GPE block */
  392.  
  393.         gpe_event_info =
  394.             acpi_ev_low_get_gpe_info(gpe_number, walk_info->gpe_block);
  395.         if (!gpe_event_info) {
  396.                 /*
  397.                  * This gpe_number is not valid for this GPE block, just ignore it.
  398.                  * However, it may be valid for a different GPE block, since GPE0
  399.                  * and GPE1 methods both appear under \_GPE.
  400.                  */
  401.                 return_ACPI_STATUS(AE_OK);
  402.         }
  403.  
  404.         if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
  405.              ACPI_GPE_DISPATCH_HANDLER) ||
  406.             (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
  407.              ACPI_GPE_DISPATCH_RAW_HANDLER)) {
  408.  
  409.                 /* If there is already a handler, ignore this GPE method */
  410.  
  411.                 return_ACPI_STATUS(AE_OK);
  412.         }
  413.  
  414.         if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
  415.             ACPI_GPE_DISPATCH_METHOD) {
  416.                 /*
  417.                  * If there is already a method, ignore this method. But check
  418.                  * for a type mismatch (if both the _Lxx AND _Exx exist)
  419.                  */
  420.                 if (type != (gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) {
  421.                         ACPI_ERROR((AE_INFO,
  422.                                     "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods",
  423.                                     gpe_number, gpe_number, gpe_number));
  424.                 }
  425.                 return_ACPI_STATUS(AE_OK);
  426.         }
  427.  
  428.         /* Disable the GPE in case it's been enabled already. */
  429.  
  430.         (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
  431.  
  432.         /*
  433.          * Add the GPE information from above to the gpe_event_info block for
  434.          * use during dispatch of this GPE.
  435.          */
  436.         gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK);
  437.         gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
  438.         gpe_event_info->dispatch.method_node = method_node;
  439.  
  440.         ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
  441.                           "Registered GPE method %s as GPE number 0x%.2X\n",
  442.                           name, gpe_number));
  443.         return_ACPI_STATUS(AE_OK);
  444. }
  445.  
  446. #endif                          /* !ACPI_REDUCED_HARDWARE */
  447.