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