linux/drivers/acpi/acpica/evevent.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: evevent - Fixed Event handling and dispatch
   5 *
   6 * Copyright (C) 2000 - 2018, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "acevents.h"
  13
  14#define _COMPONENT          ACPI_EVENTS
  15ACPI_MODULE_NAME("evevent")
  16#if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
  17/* Local prototypes */
  18static acpi_status acpi_ev_fixed_event_initialize(void);
  19
  20static u32 acpi_ev_fixed_event_dispatch(u32 event);
  21
  22/*******************************************************************************
  23 *
  24 * FUNCTION:    acpi_ev_initialize_events
  25 *
  26 * PARAMETERS:  None
  27 *
  28 * RETURN:      Status
  29 *
  30 * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE)
  31 *
  32 ******************************************************************************/
  33
  34acpi_status acpi_ev_initialize_events(void)
  35{
  36        acpi_status status;
  37
  38        ACPI_FUNCTION_TRACE(ev_initialize_events);
  39
  40        /* If Hardware Reduced flag is set, there are no fixed events */
  41
  42        if (acpi_gbl_reduced_hardware) {
  43                return_ACPI_STATUS(AE_OK);
  44        }
  45
  46        /*
  47         * Initialize the Fixed and General Purpose Events. This is done prior to
  48         * enabling SCIs to prevent interrupts from occurring before the handlers
  49         * are installed.
  50         */
  51        status = acpi_ev_fixed_event_initialize();
  52        if (ACPI_FAILURE(status)) {
  53                ACPI_EXCEPTION((AE_INFO, status,
  54                                "Unable to initialize fixed events"));
  55                return_ACPI_STATUS(status);
  56        }
  57
  58        status = acpi_ev_gpe_initialize();
  59        if (ACPI_FAILURE(status)) {
  60                ACPI_EXCEPTION((AE_INFO, status,
  61                                "Unable to initialize general purpose events"));
  62                return_ACPI_STATUS(status);
  63        }
  64
  65        return_ACPI_STATUS(status);
  66}
  67
  68/*******************************************************************************
  69 *
  70 * FUNCTION:    acpi_ev_install_xrupt_handlers
  71 *
  72 * PARAMETERS:  None
  73 *
  74 * RETURN:      Status
  75 *
  76 * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
  77 *
  78 ******************************************************************************/
  79
  80acpi_status acpi_ev_install_xrupt_handlers(void)
  81{
  82        acpi_status status;
  83
  84        ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers);
  85
  86        /* If Hardware Reduced flag is set, there is no ACPI h/w */
  87
  88        if (acpi_gbl_reduced_hardware) {
  89                return_ACPI_STATUS(AE_OK);
  90        }
  91
  92        /* Install the SCI handler */
  93
  94        status = acpi_ev_install_sci_handler();
  95        if (ACPI_FAILURE(status)) {
  96                ACPI_EXCEPTION((AE_INFO, status,
  97                                "Unable to install System Control Interrupt handler"));
  98                return_ACPI_STATUS(status);
  99        }
 100
 101        /* Install the handler for the Global Lock */
 102
 103        status = acpi_ev_init_global_lock_handler();
 104        if (ACPI_FAILURE(status)) {
 105                ACPI_EXCEPTION((AE_INFO, status,
 106                                "Unable to initialize Global Lock handler"));
 107                return_ACPI_STATUS(status);
 108        }
 109
 110        acpi_gbl_events_initialized = TRUE;
 111        return_ACPI_STATUS(status);
 112}
 113
 114/*******************************************************************************
 115 *
 116 * FUNCTION:    acpi_ev_fixed_event_initialize
 117 *
 118 * PARAMETERS:  None
 119 *
 120 * RETURN:      Status
 121 *
 122 * DESCRIPTION: Install the fixed event handlers and disable all fixed events.
 123 *
 124 ******************************************************************************/
 125
 126static acpi_status acpi_ev_fixed_event_initialize(void)
 127{
 128        u32 i;
 129        acpi_status status;
 130
 131        /*
 132         * Initialize the structure that keeps track of fixed event handlers and
 133         * enable the fixed events.
 134         */
 135        for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
 136                acpi_gbl_fixed_event_handlers[i].handler = NULL;
 137                acpi_gbl_fixed_event_handlers[i].context = NULL;
 138
 139                /* Disable the fixed event */
 140
 141                if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
 142                        status =
 143                            acpi_write_bit_register(acpi_gbl_fixed_event_info
 144                                                    [i].enable_register_id,
 145                                                    ACPI_DISABLE_EVENT);
 146                        if (ACPI_FAILURE(status)) {
 147                                return (status);
 148                        }
 149                }
 150        }
 151
 152        return (AE_OK);
 153}
 154
 155/*******************************************************************************
 156 *
 157 * FUNCTION:    acpi_ev_fixed_event_detect
 158 *
 159 * PARAMETERS:  None
 160 *
 161 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
 162 *
 163 * DESCRIPTION: Checks the PM status register for active fixed events
 164 *
 165 ******************************************************************************/
 166
 167u32 acpi_ev_fixed_event_detect(void)
 168{
 169        u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
 170        u32 fixed_status;
 171        u32 fixed_enable;
 172        u32 i;
 173        acpi_status status;
 174
 175        ACPI_FUNCTION_NAME(ev_fixed_event_detect);
 176
 177        /*
 178         * Read the fixed feature status and enable registers, as all the cases
 179         * depend on their values. Ignore errors here.
 180         */
 181        status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
 182        status |=
 183            acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
 184        if (ACPI_FAILURE(status)) {
 185                return (int_status);
 186        }
 187
 188        ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
 189                          "Fixed Event Block: Enable %08X Status %08X\n",
 190                          fixed_enable, fixed_status));
 191
 192        /*
 193         * Check for all possible Fixed Events and dispatch those that are active
 194         */
 195        for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
 196
 197                /* Both the status and enable bits must be on for this event */
 198
 199                if ((fixed_status & acpi_gbl_fixed_event_info[i].
 200                     status_bit_mask)
 201                    && (fixed_enable & acpi_gbl_fixed_event_info[i].
 202                        enable_bit_mask)) {
 203                        /*
 204                         * Found an active (signalled) event. Invoke global event
 205                         * handler if present.
 206                         */
 207                        acpi_fixed_event_count[i]++;
 208                        if (acpi_gbl_global_event_handler) {
 209                                acpi_gbl_global_event_handler
 210                                    (ACPI_EVENT_TYPE_FIXED, NULL, i,
 211                                     acpi_gbl_global_event_handler_context);
 212                        }
 213
 214                        int_status |= acpi_ev_fixed_event_dispatch(i);
 215                }
 216        }
 217
 218        return (int_status);
 219}
 220
 221/*******************************************************************************
 222 *
 223 * FUNCTION:    acpi_ev_fixed_event_dispatch
 224 *
 225 * PARAMETERS:  event               - Event type
 226 *
 227 * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
 228 *
 229 * DESCRIPTION: Clears the status bit for the requested event, calls the
 230 *              handler that previously registered for the event.
 231 *              NOTE: If there is no handler for the event, the event is
 232 *              disabled to prevent further interrupts.
 233 *
 234 ******************************************************************************/
 235
 236static u32 acpi_ev_fixed_event_dispatch(u32 event)
 237{
 238
 239        ACPI_FUNCTION_ENTRY();
 240
 241        /* Clear the status bit */
 242
 243        (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
 244                                      status_register_id, ACPI_CLEAR_STATUS);
 245
 246        /*
 247         * Make sure that a handler exists. If not, report an error
 248         * and disable the event to prevent further interrupts.
 249         */
 250        if (!acpi_gbl_fixed_event_handlers[event].handler) {
 251                (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
 252                                              enable_register_id,
 253                                              ACPI_DISABLE_EVENT);
 254
 255                ACPI_ERROR((AE_INFO,
 256                            "No installed handler for fixed event - %s (%u), disabling",
 257                            acpi_ut_get_event_name(event), event));
 258
 259                return (ACPI_INTERRUPT_NOT_HANDLED);
 260        }
 261
 262        /* Invoke the Fixed Event handler */
 263
 264        return ((acpi_gbl_fixed_event_handlers[event].
 265                 handler) (acpi_gbl_fixed_event_handlers[event].context));
 266}
 267
 268#endif                          /* !ACPI_REDUCED_HARDWARE */
 269