Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: evevent - Fixed Event handling and dispatch
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acevents.h"
0013 
0014 #define _COMPONENT          ACPI_EVENTS
0015 ACPI_MODULE_NAME("evevent")
0016 #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
0017 /* Local prototypes */
0018 static acpi_status acpi_ev_fixed_event_initialize(void);
0019 
0020 static u32 acpi_ev_fixed_event_dispatch(u32 event);
0021 
0022 /*******************************************************************************
0023  *
0024  * FUNCTION:    acpi_ev_initialize_events
0025  *
0026  * PARAMETERS:  None
0027  *
0028  * RETURN:      Status
0029  *
0030  * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE)
0031  *
0032  ******************************************************************************/
0033 
0034 acpi_status acpi_ev_initialize_events(void)
0035 {
0036     acpi_status status;
0037 
0038     ACPI_FUNCTION_TRACE(ev_initialize_events);
0039 
0040     /* If Hardware Reduced flag is set, there are no fixed events */
0041 
0042     if (acpi_gbl_reduced_hardware) {
0043         return_ACPI_STATUS(AE_OK);
0044     }
0045 
0046     /*
0047      * Initialize the Fixed and General Purpose Events. This is done prior to
0048      * enabling SCIs to prevent interrupts from occurring before the handlers
0049      * are installed.
0050      */
0051     status = acpi_ev_fixed_event_initialize();
0052     if (ACPI_FAILURE(status)) {
0053         ACPI_EXCEPTION((AE_INFO, status,
0054                 "Unable to initialize fixed events"));
0055         return_ACPI_STATUS(status);
0056     }
0057 
0058     status = acpi_ev_gpe_initialize();
0059     if (ACPI_FAILURE(status)) {
0060         ACPI_EXCEPTION((AE_INFO, status,
0061                 "Unable to initialize general purpose events"));
0062         return_ACPI_STATUS(status);
0063     }
0064 
0065     return_ACPI_STATUS(status);
0066 }
0067 
0068 /*******************************************************************************
0069  *
0070  * FUNCTION:    acpi_ev_install_xrupt_handlers
0071  *
0072  * PARAMETERS:  None
0073  *
0074  * RETURN:      Status
0075  *
0076  * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
0077  *
0078  ******************************************************************************/
0079 
0080 acpi_status acpi_ev_install_xrupt_handlers(void)
0081 {
0082     acpi_status status;
0083 
0084     ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers);
0085 
0086     /* If Hardware Reduced flag is set, there is no ACPI h/w */
0087 
0088     if (acpi_gbl_reduced_hardware) {
0089         return_ACPI_STATUS(AE_OK);
0090     }
0091 
0092     /* Install the SCI handler */
0093 
0094     status = acpi_ev_install_sci_handler();
0095     if (ACPI_FAILURE(status)) {
0096         ACPI_EXCEPTION((AE_INFO, status,
0097                 "Unable to install System Control Interrupt handler"));
0098         return_ACPI_STATUS(status);
0099     }
0100 
0101     /* Install the handler for the Global Lock */
0102 
0103     status = acpi_ev_init_global_lock_handler();
0104     if (ACPI_FAILURE(status)) {
0105         ACPI_EXCEPTION((AE_INFO, status,
0106                 "Unable to initialize Global Lock handler"));
0107         return_ACPI_STATUS(status);
0108     }
0109 
0110     acpi_gbl_events_initialized = TRUE;
0111     return_ACPI_STATUS(status);
0112 }
0113 
0114 /*******************************************************************************
0115  *
0116  * FUNCTION:    acpi_ev_fixed_event_initialize
0117  *
0118  * PARAMETERS:  None
0119  *
0120  * RETURN:      Status
0121  *
0122  * DESCRIPTION: Install the fixed event handlers and disable all fixed events.
0123  *
0124  ******************************************************************************/
0125 
0126 static acpi_status acpi_ev_fixed_event_initialize(void)
0127 {
0128     u32 i;
0129     acpi_status status;
0130 
0131     /*
0132      * Initialize the structure that keeps track of fixed event handlers and
0133      * disable all of the fixed events.
0134      */
0135     for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
0136         acpi_gbl_fixed_event_handlers[i].handler = NULL;
0137         acpi_gbl_fixed_event_handlers[i].context = NULL;
0138 
0139         /* Disable the fixed event */
0140 
0141         if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
0142             status =
0143                 acpi_write_bit_register(acpi_gbl_fixed_event_info
0144                             [i].enable_register_id,
0145                             ACPI_DISABLE_EVENT);
0146             if (ACPI_FAILURE(status)) {
0147                 return (status);
0148             }
0149         }
0150     }
0151 
0152     return (AE_OK);
0153 }
0154 
0155 /*******************************************************************************
0156  *
0157  * FUNCTION:    acpi_ev_fixed_event_detect
0158  *
0159  * PARAMETERS:  None
0160  *
0161  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
0162  *
0163  * DESCRIPTION: Checks the PM status register for active fixed events
0164  *
0165  ******************************************************************************/
0166 
0167 u32 acpi_ev_fixed_event_detect(void)
0168 {
0169     u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
0170     u32 fixed_status;
0171     u32 fixed_enable;
0172     u32 i;
0173     acpi_status status;
0174 
0175     ACPI_FUNCTION_NAME(ev_fixed_event_detect);
0176 
0177     /*
0178      * Read the fixed feature status and enable registers, as all the cases
0179      * depend on their values. Ignore errors here.
0180      */
0181     status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
0182     status |=
0183         acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
0184     if (ACPI_FAILURE(status)) {
0185         return (int_status);
0186     }
0187 
0188     ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
0189               "Fixed Event Block: Enable %08X Status %08X\n",
0190               fixed_enable, fixed_status));
0191 
0192     /*
0193      * Check for all possible Fixed Events and dispatch those that are active
0194      */
0195     for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
0196 
0197         /* Both the status and enable bits must be on for this event */
0198 
0199         if ((fixed_status & acpi_gbl_fixed_event_info[i].
0200              status_bit_mask)
0201             && (fixed_enable & acpi_gbl_fixed_event_info[i].
0202             enable_bit_mask)) {
0203             /*
0204              * Found an active (signalled) event. Invoke global event
0205              * handler if present.
0206              */
0207             acpi_fixed_event_count[i]++;
0208             if (acpi_gbl_global_event_handler) {
0209                 acpi_gbl_global_event_handler
0210                     (ACPI_EVENT_TYPE_FIXED, NULL, i,
0211                      acpi_gbl_global_event_handler_context);
0212             }
0213 
0214             int_status |= acpi_ev_fixed_event_dispatch(i);
0215         }
0216     }
0217 
0218     return (int_status);
0219 }
0220 
0221 /*******************************************************************************
0222  *
0223  * FUNCTION:    acpi_ev_fixed_event_dispatch
0224  *
0225  * PARAMETERS:  event               - Event type
0226  *
0227  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
0228  *
0229  * DESCRIPTION: Clears the status bit for the requested event, calls the
0230  *              handler that previously registered for the event.
0231  *              NOTE: If there is no handler for the event, the event is
0232  *              disabled to prevent further interrupts.
0233  *
0234  ******************************************************************************/
0235 
0236 static u32 acpi_ev_fixed_event_dispatch(u32 event)
0237 {
0238 
0239     ACPI_FUNCTION_ENTRY();
0240 
0241     /* Clear the status bit */
0242 
0243     (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
0244                       status_register_id, ACPI_CLEAR_STATUS);
0245 
0246     /*
0247      * Make sure that a handler exists. If not, report an error
0248      * and disable the event to prevent further interrupts.
0249      */
0250     if (!acpi_gbl_fixed_event_handlers[event].handler) {
0251         (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
0252                           enable_register_id,
0253                           ACPI_DISABLE_EVENT);
0254 
0255         ACPI_ERROR((AE_INFO,
0256                 "No installed handler for fixed event - %s (%u), disabling",
0257                 acpi_ut_get_event_name(event), event));
0258 
0259         return (ACPI_INTERRUPT_NOT_HANDLED);
0260     }
0261 
0262     /* Invoke the Fixed Event handler */
0263 
0264     return ((acpi_gbl_fixed_event_handlers[event].
0265          handler) (acpi_gbl_fixed_event_handlers[event].context));
0266 }
0267 
0268 /*******************************************************************************
0269  *
0270  * FUNCTION:    acpi_any_fixed_event_status_set
0271  *
0272  * PARAMETERS:  None
0273  *
0274  * RETURN:      TRUE or FALSE
0275  *
0276  * DESCRIPTION: Checks the PM status register for active fixed events
0277  *
0278  ******************************************************************************/
0279 
0280 u32 acpi_any_fixed_event_status_set(void)
0281 {
0282     acpi_status status;
0283     u32 in_status;
0284     u32 in_enable;
0285     u32 i;
0286 
0287     status = acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &in_enable);
0288     if (ACPI_FAILURE(status)) {
0289         return (FALSE);
0290     }
0291 
0292     status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &in_status);
0293     if (ACPI_FAILURE(status)) {
0294         return (FALSE);
0295     }
0296 
0297     /*
0298      * Check for all possible Fixed Events and dispatch those that are active
0299      */
0300     for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
0301 
0302         /* Both the status and enable bits must be on for this event */
0303 
0304         if ((in_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
0305             (in_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
0306             return (TRUE);
0307         }
0308     }
0309 
0310     return (FALSE);
0311 }
0312 
0313 #endif              /* !ACPI_REDUCED_HARDWARE */