xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/evevent.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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