Branch data Line data Source code
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 - 2020, Intel Corp. 7 : : * 8 : : *****************************************************************************/ 9 : : 10 : : #include <acpi/acpi.h> 11 : : #include "accommon.h" 12 : : #include "acevents.h" 13 : : 14 : : #define _COMPONENT ACPI_EVENTS 15 : : ACPI_MODULE_NAME("evevent") 16 : : #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 17 : : /* Local prototypes */ 18 : : static acpi_status acpi_ev_fixed_event_initialize(void); 19 : : 20 : : static 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 : : 34 : 78 : acpi_status acpi_ev_initialize_events(void) 35 : : { 36 : 78 : acpi_status status; 37 : : 38 : 78 : ACPI_FUNCTION_TRACE(ev_initialize_events); 39 : : 40 : : /* If Hardware Reduced flag is set, there are no fixed events */ 41 : : 42 [ + - ]: 78 : 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 : 78 : status = acpi_ev_fixed_event_initialize(); 52 [ - + ]: 78 : if (ACPI_FAILURE(status)) { 53 : 0 : ACPI_EXCEPTION((AE_INFO, status, 54 : : "Unable to initialize fixed events")); 55 : 0 : return_ACPI_STATUS(status); 56 : : } 57 : : 58 : 78 : status = acpi_ev_gpe_initialize(); 59 [ - + ]: 78 : if (ACPI_FAILURE(status)) { 60 : 0 : ACPI_EXCEPTION((AE_INFO, status, 61 : : "Unable to initialize general purpose events")); 62 : 0 : 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 : : 80 : 78 : acpi_status acpi_ev_install_xrupt_handlers(void) 81 : : { 82 : 78 : acpi_status status; 83 : : 84 : 78 : ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers); 85 : : 86 : : /* If Hardware Reduced flag is set, there is no ACPI h/w */ 87 : : 88 [ + - ]: 78 : if (acpi_gbl_reduced_hardware) { 89 : : return_ACPI_STATUS(AE_OK); 90 : : } 91 : : 92 : : /* Install the SCI handler */ 93 : : 94 : 78 : status = acpi_ev_install_sci_handler(); 95 [ - + ]: 78 : if (ACPI_FAILURE(status)) { 96 : 0 : ACPI_EXCEPTION((AE_INFO, status, 97 : : "Unable to install System Control Interrupt handler")); 98 : 0 : return_ACPI_STATUS(status); 99 : : } 100 : : 101 : : /* Install the handler for the Global Lock */ 102 : : 103 : 78 : status = acpi_ev_init_global_lock_handler(); 104 [ - + ]: 78 : if (ACPI_FAILURE(status)) { 105 : 0 : ACPI_EXCEPTION((AE_INFO, status, 106 : : "Unable to initialize Global Lock handler")); 107 : 0 : return_ACPI_STATUS(status); 108 : : } 109 : : 110 : 78 : acpi_gbl_events_initialized = TRUE; 111 : 78 : 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 : : 126 : 78 : static acpi_status acpi_ev_fixed_event_initialize(void) 127 : : { 128 : 78 : u32 i; 129 : 78 : acpi_status status; 130 : : 131 : : /* 132 : : * Initialize the structure that keeps track of fixed event handlers and 133 : : * enable the fixed events. 134 : : */ 135 [ + + ]: 468 : for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { 136 : 390 : acpi_gbl_fixed_event_handlers[i].handler = NULL; 137 : 390 : acpi_gbl_fixed_event_handlers[i].context = NULL; 138 : : 139 : : /* Disable the fixed event */ 140 : : 141 [ + - ]: 390 : if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { 142 : 390 : status = 143 : 390 : acpi_write_bit_register(acpi_gbl_fixed_event_info 144 : : [i].enable_register_id, 145 : : ACPI_DISABLE_EVENT); 146 [ - + ]: 390 : if (ACPI_FAILURE(status)) { 147 : 0 : 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 : : 167 : 0 : u32 acpi_ev_fixed_event_detect(void) 168 : : { 169 : 0 : u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; 170 : 0 : u32 fixed_status; 171 : 0 : u32 fixed_enable; 172 : 0 : u32 i; 173 : 0 : acpi_status status; 174 : : 175 : 0 : 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 : 0 : status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status); 182 : 0 : status |= 183 : 0 : acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable); 184 [ # # ]: 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : if ((fixed_status & acpi_gbl_fixed_event_info[i]. 200 : : status_bit_mask) 201 [ # # ]: 0 : && (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 : 0 : acpi_fixed_event_count[i]++; 208 [ # # ]: 0 : if (acpi_gbl_global_event_handler) { 209 : 0 : acpi_gbl_global_event_handler 210 : : (ACPI_EVENT_TYPE_FIXED, NULL, i, 211 : : acpi_gbl_global_event_handler_context); 212 : : } 213 : : 214 : 0 : 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 : : 236 : 0 : static u32 acpi_ev_fixed_event_dispatch(u32 event) 237 : : { 238 : : 239 : 0 : ACPI_FUNCTION_ENTRY(); 240 : : 241 : : /* Clear the status bit */ 242 : : 243 : 0 : (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 [ # # ]: 0 : if (!acpi_gbl_fixed_event_handlers[event].handler) { 251 : 0 : (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. 252 : : enable_register_id, 253 : : ACPI_DISABLE_EVENT); 254 : : 255 : 0 : ACPI_ERROR((AE_INFO, 256 : : "No installed handler for fixed event - %s (%u), disabling", 257 : : acpi_ut_get_event_name(event), event)); 258 : : 259 : 0 : return (ACPI_INTERRUPT_NOT_HANDLED); 260 : : } 261 : : 262 : : /* Invoke the Fixed Event handler */ 263 : : 264 : 0 : return ((acpi_gbl_fixed_event_handlers[event]. 265 : : handler) (acpi_gbl_fixed_event_handlers[event].context)); 266 : : } 267 : : 268 : : /******************************************************************************* 269 : : * 270 : : * FUNCTION: acpi_any_fixed_event_status_set 271 : : * 272 : : * PARAMETERS: None 273 : : * 274 : : * RETURN: TRUE or FALSE 275 : : * 276 : : * DESCRIPTION: Checks the PM status register for active fixed events 277 : : * 278 : : ******************************************************************************/ 279 : : 280 : 0 : u32 acpi_any_fixed_event_status_set(void) 281 : : { 282 : 0 : acpi_status status; 283 : 0 : u32 in_status; 284 : 0 : u32 in_enable; 285 : 0 : u32 i; 286 : : 287 : 0 : status = acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &in_enable); 288 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 289 : : return (FALSE); 290 : : } 291 : : 292 : 0 : status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &in_status); 293 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 294 : : return (FALSE); 295 : : } 296 : : 297 : : /* 298 : : * Check for all possible Fixed Events and dispatch those that are active 299 : : */ 300 [ # # ]: 0 : for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { 301 : : 302 : : /* Both the status and enable bits must be on for this event */ 303 : : 304 [ # # ]: 0 : if ((in_status & acpi_gbl_fixed_event_info[i].status_bit_mask) && 305 [ # # ]: 0 : (in_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) { 306 : : return (TRUE); 307 : : } 308 : : } 309 : : 310 : : return (FALSE); 311 : : } 312 : : 313 : : #endif /* !ACPI_REDUCED_HARDWARE */