Commit | Line | Data |
---|---|---|
95857638 | 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
1da177e4 LT |
2 | /****************************************************************************** |
3 | * | |
4 | * Module Name: evevent - Fixed Event handling and dispatch | |
5 | * | |
800ba7c5 | 6 | * Copyright (C) 2000 - 2020, Intel Corp. |
1da177e4 | 7 | * |
95857638 | 8 | *****************************************************************************/ |
1da177e4 LT |
9 | |
10 | #include <acpi/acpi.h> | |
e2f7a777 LB |
11 | #include "accommon.h" |
12 | #include "acevents.h" | |
1da177e4 LT |
13 | |
14 | #define _COMPONENT ACPI_EVENTS | |
4be44fcd | 15 | ACPI_MODULE_NAME("evevent") |
33620c54 | 16 | #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ |
44f6c012 | 17 | /* Local prototypes */ |
4be44fcd | 18 | static acpi_status acpi_ev_fixed_event_initialize(void); |
44f6c012 | 19 | |
4be44fcd | 20 | static u32 acpi_ev_fixed_event_dispatch(u32 event); |
1da177e4 LT |
21 | |
22 | /******************************************************************************* | |
23 | * | |
24 | * FUNCTION: acpi_ev_initialize_events | |
25 | * | |
26 | * PARAMETERS: None | |
27 | * | |
28 | * RETURN: Status | |
29 | * | |
44f6c012 | 30 | * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE) |
1da177e4 LT |
31 | * |
32 | ******************************************************************************/ | |
33 | ||
4be44fcd | 34 | acpi_status acpi_ev_initialize_events(void) |
1da177e4 | 35 | { |
4be44fcd | 36 | acpi_status status; |
1da177e4 | 37 | |
b229cf92 | 38 | ACPI_FUNCTION_TRACE(ev_initialize_events); |
1da177e4 | 39 | |
22e5b40a BM |
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 | ||
1da177e4 | 46 | /* |
44f6c012 | 47 | * Initialize the Fixed and General Purpose Events. This is done prior to |
9f15fc66 BM |
48 | * enabling SCIs to prevent interrupts from occurring before the handlers |
49 | * are installed. | |
1da177e4 | 50 | */ |
4be44fcd LB |
51 | status = acpi_ev_fixed_event_initialize(); |
52 | if (ACPI_FAILURE(status)) { | |
b8e4d893 BM |
53 | ACPI_EXCEPTION((AE_INFO, status, |
54 | "Unable to initialize fixed events")); | |
4be44fcd | 55 | return_ACPI_STATUS(status); |
1da177e4 LT |
56 | } |
57 | ||
4be44fcd LB |
58 | status = acpi_ev_gpe_initialize(); |
59 | if (ACPI_FAILURE(status)) { | |
b8e4d893 BM |
60 | ACPI_EXCEPTION((AE_INFO, status, |
61 | "Unable to initialize general purpose events")); | |
4be44fcd | 62 | return_ACPI_STATUS(status); |
1da177e4 LT |
63 | } |
64 | ||
4be44fcd | 65 | return_ACPI_STATUS(status); |
1da177e4 LT |
66 | } |
67 | ||
1da177e4 LT |
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 | ||
4be44fcd | 80 | acpi_status acpi_ev_install_xrupt_handlers(void) |
1da177e4 | 81 | { |
4be44fcd | 82 | acpi_status status; |
1da177e4 | 83 | |
b229cf92 | 84 | ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers); |
1da177e4 | 85 | |
22e5b40a BM |
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 | ||
1da177e4 LT |
92 | /* Install the SCI handler */ |
93 | ||
4be44fcd LB |
94 | status = acpi_ev_install_sci_handler(); |
95 | if (ACPI_FAILURE(status)) { | |
b8e4d893 BM |
96 | ACPI_EXCEPTION((AE_INFO, status, |
97 | "Unable to install System Control Interrupt handler")); | |
4be44fcd | 98 | return_ACPI_STATUS(status); |
1da177e4 LT |
99 | } |
100 | ||
101 | /* Install the handler for the Global Lock */ | |
102 | ||
4be44fcd LB |
103 | status = acpi_ev_init_global_lock_handler(); |
104 | if (ACPI_FAILURE(status)) { | |
b8e4d893 BM |
105 | ACPI_EXCEPTION((AE_INFO, status, |
106 | "Unable to initialize Global Lock handler")); | |
4be44fcd | 107 | return_ACPI_STATUS(status); |
1da177e4 LT |
108 | } |
109 | ||
110 | acpi_gbl_events_initialized = TRUE; | |
4be44fcd | 111 | return_ACPI_STATUS(status); |
1da177e4 LT |
112 | } |
113 | ||
1da177e4 LT |
114 | /******************************************************************************* |
115 | * | |
116 | * FUNCTION: acpi_ev_fixed_event_initialize | |
117 | * | |
118 | * PARAMETERS: None | |
119 | * | |
120 | * RETURN: Status | |
121 | * | |
768aaaf1 | 122 | * DESCRIPTION: Install the fixed event handlers and disable all fixed events. |
1da177e4 LT |
123 | * |
124 | ******************************************************************************/ | |
125 | ||
4be44fcd | 126 | static acpi_status acpi_ev_fixed_event_initialize(void) |
1da177e4 | 127 | { |
67a119f9 | 128 | u32 i; |
4be44fcd | 129 | acpi_status status; |
1da177e4 LT |
130 | |
131 | /* | |
9f15fc66 BM |
132 | * Initialize the structure that keeps track of fixed event handlers and |
133 | * enable the fixed events. | |
1da177e4 LT |
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 | ||
768aaaf1 | 139 | /* Disable the fixed event */ |
1da177e4 LT |
140 | |
141 | if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { | |
4be44fcd | 142 | status = |
50ffba1b | 143 | acpi_write_bit_register(acpi_gbl_fixed_event_info |
768aaaf1 BM |
144 | [i].enable_register_id, |
145 | ACPI_DISABLE_EVENT); | |
4be44fcd | 146 | if (ACPI_FAILURE(status)) { |
1da177e4 LT |
147 | return (status); |
148 | } | |
149 | } | |
150 | } | |
151 | ||
152 | return (AE_OK); | |
153 | } | |
154 | ||
1da177e4 LT |
155 | /******************************************************************************* |
156 | * | |
157 | * FUNCTION: acpi_ev_fixed_event_detect | |
158 | * | |
159 | * PARAMETERS: None | |
160 | * | |
161 | * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED | |
162 | * | |
44f6c012 | 163 | * DESCRIPTION: Checks the PM status register for active fixed events |
1da177e4 LT |
164 | * |
165 | ******************************************************************************/ | |
166 | ||
4be44fcd | 167 | u32 acpi_ev_fixed_event_detect(void) |
1da177e4 | 168 | { |
4be44fcd LB |
169 | u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; |
170 | u32 fixed_status; | |
171 | u32 fixed_enable; | |
67a119f9 | 172 | u32 i; |
b4c0de31 | 173 | acpi_status status; |
1da177e4 | 174 | |
b229cf92 | 175 | ACPI_FUNCTION_NAME(ev_fixed_event_detect); |
1da177e4 LT |
176 | |
177 | /* | |
178 | * Read the fixed feature status and enable registers, as all the cases | |
9f15fc66 | 179 | * depend on their values. Ignore errors here. |
1da177e4 | 180 | */ |
b4c0de31 ES |
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 | } | |
1da177e4 | 187 | |
4be44fcd LB |
188 | ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, |
189 | "Fixed Event Block: Enable %08X Status %08X\n", | |
190 | fixed_enable, fixed_status)); | |
1da177e4 LT |
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++) { | |
52fc0b02 | 196 | |
1da177e4 LT |
197 | /* Both the status and enable bits must be on for this event */ |
198 | ||
4be44fcd LB |
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)) { | |
a0fcdb23 LM |
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 | } | |
52fc0b02 | 213 | |
67a119f9 | 214 | int_status |= acpi_ev_fixed_event_dispatch(i); |
1da177e4 LT |
215 | } |
216 | } | |
217 | ||
218 | return (int_status); | |
219 | } | |
220 | ||
1da177e4 LT |
221 | /******************************************************************************* |
222 | * | |
223 | * FUNCTION: acpi_ev_fixed_event_dispatch | |
224 | * | |
ba494bee | 225 | * PARAMETERS: event - Event type |
1da177e4 LT |
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. | |
d4d32195 | 231 | * NOTE: If there is no handler for the event, the event is |
b07a383f | 232 | * disabled to prevent further interrupts. |
1da177e4 LT |
233 | * |
234 | ******************************************************************************/ | |
235 | ||
4be44fcd | 236 | static u32 acpi_ev_fixed_event_dispatch(u32 event) |
1da177e4 LT |
237 | { |
238 | ||
4be44fcd | 239 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
240 | |
241 | /* Clear the status bit */ | |
242 | ||
50ffba1b | 243 | (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. |
768aaaf1 | 244 | status_register_id, ACPI_CLEAR_STATUS); |
1da177e4 LT |
245 | |
246 | /* | |
d4d32195 BM |
247 | * Make sure that a handler exists. If not, report an error |
248 | * and disable the event to prevent further interrupts. | |
1da177e4 | 249 | */ |
d4d32195 | 250 | if (!acpi_gbl_fixed_event_handlers[event].handler) { |
50ffba1b | 251 | (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. |
768aaaf1 BM |
252 | enable_register_id, |
253 | ACPI_DISABLE_EVENT); | |
1da177e4 | 254 | |
b8e4d893 | 255 | ACPI_ERROR((AE_INFO, |
d4d32195 BM |
256 | "No installed handler for fixed event - %s (%u), disabling", |
257 | acpi_ut_get_event_name(event), event)); | |
1da177e4 LT |
258 | |
259 | return (ACPI_INTERRUPT_NOT_HANDLED); | |
260 | } | |
261 | ||
262 | /* Invoke the Fixed Event handler */ | |
263 | ||
4be44fcd LB |
264 | return ((acpi_gbl_fixed_event_handlers[event]. |
265 | handler) (acpi_gbl_fixed_event_handlers[event].context)); | |
1da177e4 | 266 | } |
33620c54 | 267 | |
63fb9623 RW |
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 | u32 acpi_any_fixed_event_status_set(void) | |
281 | { | |
282 | acpi_status status; | |
283 | u32 in_status; | |
284 | u32 in_enable; | |
285 | u32 i; | |
286 | ||
287 | status = acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &in_enable); | |
288 | if (ACPI_FAILURE(status)) { | |
289 | return (FALSE); | |
290 | } | |
291 | ||
292 | status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &in_status); | |
293 | 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 | 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 | if ((in_status & acpi_gbl_fixed_event_info[i].status_bit_mask) && | |
305 | (in_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) { | |
306 | return (TRUE); | |
307 | } | |
308 | } | |
309 | ||
310 | return (FALSE); | |
311 | } | |
312 | ||
33620c54 | 313 | #endif /* !ACPI_REDUCED_HARDWARE */ |