xref: /openbmc/linux/drivers/acpi/acpica/evsci.c (revision c13aca79ff3c4af5fd31a5b2743a90eba6e36a26)
1*95857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /*******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: evsci - System Control Interrupt configuration and
595b482a8SLen Brown  *                      legacy to ACPI mode state transition functions
695b482a8SLen Brown  *
795b482a8SLen Brown  ******************************************************************************/
895b482a8SLen Brown 
995b482a8SLen Brown #include <acpi/acpi.h>
10e2f7a777SLen Brown #include "accommon.h"
11e2f7a777SLen Brown #include "acevents.h"
1295b482a8SLen Brown 
1395b482a8SLen Brown #define _COMPONENT          ACPI_EVENTS
1495b482a8SLen Brown ACPI_MODULE_NAME("evsci")
1533620c54SBob Moore #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
1695b482a8SLen Brown /* Local prototypes */
1795b482a8SLen Brown static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
1895b482a8SLen Brown 
1995b482a8SLen Brown /*******************************************************************************
2095b482a8SLen Brown  *
21a2fd4b4bSLv Zheng  * FUNCTION:    acpi_ev_sci_dispatch
22a2fd4b4bSLv Zheng  *
23a2fd4b4bSLv Zheng  * PARAMETERS:  None
24a2fd4b4bSLv Zheng  *
25a2fd4b4bSLv Zheng  * RETURN:      Status code indicates whether interrupt was handled.
26a2fd4b4bSLv Zheng  *
27a2fd4b4bSLv Zheng  * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
28a2fd4b4bSLv Zheng  *
29a2fd4b4bSLv Zheng  ******************************************************************************/
30a2fd4b4bSLv Zheng 
acpi_ev_sci_dispatch(void)31a2fd4b4bSLv Zheng u32 acpi_ev_sci_dispatch(void)
32a2fd4b4bSLv Zheng {
33a2fd4b4bSLv Zheng 	struct acpi_sci_handler_info *sci_handler;
34a2fd4b4bSLv Zheng 	acpi_cpu_flags flags;
35a2fd4b4bSLv Zheng 	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
36a2fd4b4bSLv Zheng 
37a2fd4b4bSLv Zheng 	ACPI_FUNCTION_NAME(ev_sci_dispatch);
38a2fd4b4bSLv Zheng 
39a2fd4b4bSLv Zheng 	/* Are there any host-installed SCI handlers? */
40a2fd4b4bSLv Zheng 
41a2fd4b4bSLv Zheng 	if (!acpi_gbl_sci_handler_list) {
42a2fd4b4bSLv Zheng 		return (int_status);
43a2fd4b4bSLv Zheng 	}
44a2fd4b4bSLv Zheng 
45a2fd4b4bSLv Zheng 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
46a2fd4b4bSLv Zheng 
47a2fd4b4bSLv Zheng 	/* Invoke all host-installed SCI handlers */
48a2fd4b4bSLv Zheng 
49a2fd4b4bSLv Zheng 	sci_handler = acpi_gbl_sci_handler_list;
50a2fd4b4bSLv Zheng 	while (sci_handler) {
51a2fd4b4bSLv Zheng 
52a2fd4b4bSLv Zheng 		/* Invoke the installed handler (at interrupt level) */
53a2fd4b4bSLv Zheng 
54c53ae3a6SBob Moore 		int_status |= sci_handler->address(sci_handler->context);
55a2fd4b4bSLv Zheng 
56a2fd4b4bSLv Zheng 		sci_handler = sci_handler->next;
57a2fd4b4bSLv Zheng 	}
58a2fd4b4bSLv Zheng 
59a2fd4b4bSLv Zheng 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
60a2fd4b4bSLv Zheng 	return (int_status);
61a2fd4b4bSLv Zheng }
62a2fd4b4bSLv Zheng 
63a2fd4b4bSLv Zheng /*******************************************************************************
64a2fd4b4bSLv Zheng  *
6595b482a8SLen Brown  * FUNCTION:    acpi_ev_sci_xrupt_handler
6695b482a8SLen Brown  *
67ba494beeSBob Moore  * PARAMETERS:  context   - Calling Context
6895b482a8SLen Brown  *
6995b482a8SLen Brown  * RETURN:      Status code indicates whether interrupt was handled.
7095b482a8SLen Brown  *
7195b482a8SLen Brown  * DESCRIPTION: Interrupt handler that will figure out what function or
7295b482a8SLen Brown  *              control method to call to deal with a SCI.
7395b482a8SLen Brown  *
7495b482a8SLen Brown  ******************************************************************************/
7595b482a8SLen Brown 
acpi_ev_sci_xrupt_handler(void * context)7695b482a8SLen Brown static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
7795b482a8SLen Brown {
7895b482a8SLen Brown 	struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
7995b482a8SLen Brown 	u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
8095b482a8SLen Brown 
8195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
8295b482a8SLen Brown 
8395b482a8SLen Brown 	/*
8495b482a8SLen Brown 	 * We are guaranteed by the ACPICA initialization/shutdown code that
8595b482a8SLen Brown 	 * if this interrupt handler is installed, ACPI is enabled.
8695b482a8SLen Brown 	 */
8795b482a8SLen Brown 
8895b482a8SLen Brown 	/*
8995b482a8SLen Brown 	 * Fixed Events:
9095b482a8SLen Brown 	 * Check for and dispatch any Fixed Events that have occurred
9195b482a8SLen Brown 	 */
9295b482a8SLen Brown 	interrupt_handled |= acpi_ev_fixed_event_detect();
9395b482a8SLen Brown 
9495b482a8SLen Brown 	/*
9595b482a8SLen Brown 	 * General Purpose Events:
9695b482a8SLen Brown 	 * Check for and dispatch any GPEs that have occurred
9795b482a8SLen Brown 	 */
9895b482a8SLen Brown 	interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
9995b482a8SLen Brown 
100a2fd4b4bSLv Zheng 	/* Invoke all host-installed SCI handlers */
101a2fd4b4bSLv Zheng 
102a2fd4b4bSLv Zheng 	interrupt_handled |= acpi_ev_sci_dispatch();
103a2fd4b4bSLv Zheng 
1049187a415SLv Zheng 	acpi_sci_count++;
105fd1af712SBob Moore 	return_UINT32(interrupt_handled);
10695b482a8SLen Brown }
10795b482a8SLen Brown 
10895b482a8SLen Brown /*******************************************************************************
10995b482a8SLen Brown  *
11095b482a8SLen Brown  * FUNCTION:    acpi_ev_gpe_xrupt_handler
11195b482a8SLen Brown  *
112ba494beeSBob Moore  * PARAMETERS:  context   - Calling Context
11395b482a8SLen Brown  *
11495b482a8SLen Brown  * RETURN:      Status code indicates whether interrupt was handled.
11595b482a8SLen Brown  *
11695b482a8SLen Brown  * DESCRIPTION: Handler for GPE Block Device interrupts
11795b482a8SLen Brown  *
11895b482a8SLen Brown  ******************************************************************************/
11995b482a8SLen Brown 
acpi_ev_gpe_xrupt_handler(void * context)12095b482a8SLen Brown u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
12195b482a8SLen Brown {
12295b482a8SLen Brown 	struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
12395b482a8SLen Brown 	u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
12495b482a8SLen Brown 
12595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
12695b482a8SLen Brown 
12795b482a8SLen Brown 	/*
12895b482a8SLen Brown 	 * We are guaranteed by the ACPICA initialization/shutdown code that
12995b482a8SLen Brown 	 * if this interrupt handler is installed, ACPI is enabled.
13095b482a8SLen Brown 	 */
13195b482a8SLen Brown 
13295b482a8SLen Brown 	/* GPEs: Check for and dispatch any GPEs that have occurred */
13395b482a8SLen Brown 
13495b482a8SLen Brown 	interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
135fd1af712SBob Moore 	return_UINT32(interrupt_handled);
13695b482a8SLen Brown }
13795b482a8SLen Brown 
13895b482a8SLen Brown /******************************************************************************
13995b482a8SLen Brown  *
14095b482a8SLen Brown  * FUNCTION:    acpi_ev_install_sci_handler
14195b482a8SLen Brown  *
14295b482a8SLen Brown  * PARAMETERS:  none
14395b482a8SLen Brown  *
14495b482a8SLen Brown  * RETURN:      Status
14595b482a8SLen Brown  *
14695b482a8SLen Brown  * DESCRIPTION: Installs SCI handler.
14795b482a8SLen Brown  *
14895b482a8SLen Brown  ******************************************************************************/
14995b482a8SLen Brown 
acpi_ev_install_sci_handler(void)15095b482a8SLen Brown u32 acpi_ev_install_sci_handler(void)
15195b482a8SLen Brown {
15295b482a8SLen Brown 	u32 status = AE_OK;
15395b482a8SLen Brown 
15495b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ev_install_sci_handler);
15595b482a8SLen Brown 
15695b482a8SLen Brown 	status =
15795b482a8SLen Brown 	    acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
15895b482a8SLen Brown 					      acpi_ev_sci_xrupt_handler,
15995b482a8SLen Brown 					      acpi_gbl_gpe_xrupt_list_head);
16095b482a8SLen Brown 	return_ACPI_STATUS(status);
16195b482a8SLen Brown }
16295b482a8SLen Brown 
16395b482a8SLen Brown /******************************************************************************
16495b482a8SLen Brown  *
165a2fd4b4bSLv Zheng  * FUNCTION:    acpi_ev_remove_all_sci_handlers
16695b482a8SLen Brown  *
16795b482a8SLen Brown  * PARAMETERS:  none
16895b482a8SLen Brown  *
169a2fd4b4bSLv Zheng  * RETURN:      AE_OK if handler uninstalled, AE_ERROR if handler was not
17095b482a8SLen Brown  *              installed to begin with
17195b482a8SLen Brown  *
17295b482a8SLen Brown  * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
173a2fd4b4bSLv Zheng  *              taken. Remove all host-installed SCI handlers.
17495b482a8SLen Brown  *
17595b482a8SLen Brown  * Note:  It doesn't seem important to disable all events or set the event
17695b482a8SLen Brown  *        enable registers to their original values. The OS should disable
17795b482a8SLen Brown  *        the SCI interrupt level when the handler is removed, so no more
17895b482a8SLen Brown  *        events will come in.
17995b482a8SLen Brown  *
18095b482a8SLen Brown  ******************************************************************************/
18195b482a8SLen Brown 
acpi_ev_remove_all_sci_handlers(void)182a2fd4b4bSLv Zheng acpi_status acpi_ev_remove_all_sci_handlers(void)
18395b482a8SLen Brown {
184a2fd4b4bSLv Zheng 	struct acpi_sci_handler_info *sci_handler;
185a2fd4b4bSLv Zheng 	acpi_cpu_flags flags;
18695b482a8SLen Brown 	acpi_status status;
18795b482a8SLen Brown 
188a2fd4b4bSLv Zheng 	ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
18995b482a8SLen Brown 
19095b482a8SLen Brown 	/* Just let the OS remove the handler and disable the level */
19195b482a8SLen Brown 
19295b482a8SLen Brown 	status =
19395b482a8SLen Brown 	    acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
19495b482a8SLen Brown 					     acpi_ev_sci_xrupt_handler);
19595b482a8SLen Brown 
196a2fd4b4bSLv Zheng 	if (!acpi_gbl_sci_handler_list) {
197a2fd4b4bSLv Zheng 		return (status);
198a2fd4b4bSLv Zheng 	}
199a2fd4b4bSLv Zheng 
200a2fd4b4bSLv Zheng 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
201a2fd4b4bSLv Zheng 
202a2fd4b4bSLv Zheng 	/* Free all host-installed SCI handlers */
203a2fd4b4bSLv Zheng 
204a2fd4b4bSLv Zheng 	while (acpi_gbl_sci_handler_list) {
205a2fd4b4bSLv Zheng 		sci_handler = acpi_gbl_sci_handler_list;
206a2fd4b4bSLv Zheng 		acpi_gbl_sci_handler_list = sci_handler->next;
207a2fd4b4bSLv Zheng 		ACPI_FREE(sci_handler);
208a2fd4b4bSLv Zheng 	}
209a2fd4b4bSLv Zheng 
210a2fd4b4bSLv Zheng 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
21195b482a8SLen Brown 	return_ACPI_STATUS(status);
21295b482a8SLen Brown }
21333620c54SBob Moore 
21433620c54SBob Moore #endif				/* !ACPI_REDUCED_HARDWARE */
215