xref: /openbmc/linux/drivers/acpi/acpica/evsci.c (revision 9187a415fd119c1d89a5ad2fd05513cd43699ebf)
195b482a8SLen Brown /*******************************************************************************
295b482a8SLen Brown  *
395b482a8SLen Brown  * Module Name: evsci - System Control Interrupt configuration and
495b482a8SLen Brown  *                      legacy to ACPI mode state transition functions
595b482a8SLen Brown  *
695b482a8SLen Brown  ******************************************************************************/
795b482a8SLen Brown 
895b482a8SLen Brown /*
925f044e6SBob Moore  * Copyright (C) 2000 - 2013, Intel Corp.
1095b482a8SLen Brown  * All rights reserved.
1195b482a8SLen Brown  *
1295b482a8SLen Brown  * Redistribution and use in source and binary forms, with or without
1395b482a8SLen Brown  * modification, are permitted provided that the following conditions
1495b482a8SLen Brown  * are met:
1595b482a8SLen Brown  * 1. Redistributions of source code must retain the above copyright
1695b482a8SLen Brown  *    notice, this list of conditions, and the following disclaimer,
1795b482a8SLen Brown  *    without modification.
1895b482a8SLen Brown  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1995b482a8SLen Brown  *    substantially similar to the "NO WARRANTY" disclaimer below
2095b482a8SLen Brown  *    ("Disclaimer") and any redistribution must be conditioned upon
2195b482a8SLen Brown  *    including a substantially similar Disclaimer requirement for further
2295b482a8SLen Brown  *    binary redistribution.
2395b482a8SLen Brown  * 3. Neither the names of the above-listed copyright holders nor the names
2495b482a8SLen Brown  *    of any contributors may be used to endorse or promote products derived
2595b482a8SLen Brown  *    from this software without specific prior written permission.
2695b482a8SLen Brown  *
2795b482a8SLen Brown  * Alternatively, this software may be distributed under the terms of the
2895b482a8SLen Brown  * GNU General Public License ("GPL") version 2 as published by the Free
2995b482a8SLen Brown  * Software Foundation.
3095b482a8SLen Brown  *
3195b482a8SLen Brown  * NO WARRANTY
3295b482a8SLen Brown  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3395b482a8SLen Brown  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3495b482a8SLen Brown  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3595b482a8SLen Brown  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3695b482a8SLen Brown  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3795b482a8SLen Brown  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3895b482a8SLen Brown  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3995b482a8SLen Brown  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4095b482a8SLen Brown  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4195b482a8SLen Brown  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4295b482a8SLen Brown  * POSSIBILITY OF SUCH DAMAGES.
4395b482a8SLen Brown  */
4495b482a8SLen Brown 
4595b482a8SLen Brown #include <acpi/acpi.h>
46e2f7a777SLen Brown #include "accommon.h"
47e2f7a777SLen Brown #include "acevents.h"
4895b482a8SLen Brown 
4995b482a8SLen Brown #define _COMPONENT          ACPI_EVENTS
5095b482a8SLen Brown ACPI_MODULE_NAME("evsci")
5133620c54SBob Moore #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
5295b482a8SLen Brown /* Local prototypes */
5395b482a8SLen Brown static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
5495b482a8SLen Brown 
5595b482a8SLen Brown /*******************************************************************************
5695b482a8SLen Brown  *
57a2fd4b4bSLv Zheng  * FUNCTION:    acpi_ev_sci_dispatch
58a2fd4b4bSLv Zheng  *
59a2fd4b4bSLv Zheng  * PARAMETERS:  None
60a2fd4b4bSLv Zheng  *
61a2fd4b4bSLv Zheng  * RETURN:      Status code indicates whether interrupt was handled.
62a2fd4b4bSLv Zheng  *
63a2fd4b4bSLv Zheng  * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
64a2fd4b4bSLv Zheng  *
65a2fd4b4bSLv Zheng  ******************************************************************************/
66a2fd4b4bSLv Zheng 
67a2fd4b4bSLv Zheng u32 acpi_ev_sci_dispatch(void)
68a2fd4b4bSLv Zheng {
69a2fd4b4bSLv Zheng 	struct acpi_sci_handler_info *sci_handler;
70a2fd4b4bSLv Zheng 	acpi_cpu_flags flags;
71a2fd4b4bSLv Zheng 	u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
72a2fd4b4bSLv Zheng 
73a2fd4b4bSLv Zheng 	ACPI_FUNCTION_NAME(ev_sci_dispatch);
74a2fd4b4bSLv Zheng 
75a2fd4b4bSLv Zheng 	/* Are there any host-installed SCI handlers? */
76a2fd4b4bSLv Zheng 
77a2fd4b4bSLv Zheng 	if (!acpi_gbl_sci_handler_list) {
78a2fd4b4bSLv Zheng 		return (int_status);
79a2fd4b4bSLv Zheng 	}
80a2fd4b4bSLv Zheng 
81a2fd4b4bSLv Zheng 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
82a2fd4b4bSLv Zheng 
83a2fd4b4bSLv Zheng 	/* Invoke all host-installed SCI handlers */
84a2fd4b4bSLv Zheng 
85a2fd4b4bSLv Zheng 	sci_handler = acpi_gbl_sci_handler_list;
86a2fd4b4bSLv Zheng 	while (sci_handler) {
87a2fd4b4bSLv Zheng 
88a2fd4b4bSLv Zheng 		/* Invoke the installed handler (at interrupt level) */
89a2fd4b4bSLv Zheng 
90c53ae3a6SBob Moore 		int_status |= sci_handler->address(sci_handler->context);
91a2fd4b4bSLv Zheng 
92a2fd4b4bSLv Zheng 		sci_handler = sci_handler->next;
93a2fd4b4bSLv Zheng 	}
94a2fd4b4bSLv Zheng 
95a2fd4b4bSLv Zheng 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
96a2fd4b4bSLv Zheng 	return (int_status);
97a2fd4b4bSLv Zheng }
98a2fd4b4bSLv Zheng 
99a2fd4b4bSLv Zheng /*******************************************************************************
100a2fd4b4bSLv Zheng  *
10195b482a8SLen Brown  * FUNCTION:    acpi_ev_sci_xrupt_handler
10295b482a8SLen Brown  *
103ba494beeSBob Moore  * PARAMETERS:  context   - Calling Context
10495b482a8SLen Brown  *
10595b482a8SLen Brown  * RETURN:      Status code indicates whether interrupt was handled.
10695b482a8SLen Brown  *
10795b482a8SLen Brown  * DESCRIPTION: Interrupt handler that will figure out what function or
10895b482a8SLen Brown  *              control method to call to deal with a SCI.
10995b482a8SLen Brown  *
11095b482a8SLen Brown  ******************************************************************************/
11195b482a8SLen Brown 
11295b482a8SLen Brown static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
11395b482a8SLen Brown {
11495b482a8SLen Brown 	struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
11595b482a8SLen Brown 	u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
11695b482a8SLen Brown 
11795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
11895b482a8SLen Brown 
11995b482a8SLen Brown 	/*
12095b482a8SLen Brown 	 * We are guaranteed by the ACPI CA initialization/shutdown code that
12195b482a8SLen Brown 	 * if this interrupt handler is installed, ACPI is enabled.
12295b482a8SLen Brown 	 */
12395b482a8SLen Brown 
12495b482a8SLen Brown 	/*
12595b482a8SLen Brown 	 * Fixed Events:
12695b482a8SLen Brown 	 * Check for and dispatch any Fixed Events that have occurred
12795b482a8SLen Brown 	 */
12895b482a8SLen Brown 	interrupt_handled |= acpi_ev_fixed_event_detect();
12995b482a8SLen Brown 
13095b482a8SLen Brown 	/*
13195b482a8SLen Brown 	 * General Purpose Events:
13295b482a8SLen Brown 	 * Check for and dispatch any GPEs that have occurred
13395b482a8SLen Brown 	 */
13495b482a8SLen Brown 	interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
13595b482a8SLen Brown 
136a2fd4b4bSLv Zheng 	/* Invoke all host-installed SCI handlers */
137a2fd4b4bSLv Zheng 
138a2fd4b4bSLv Zheng 	interrupt_handled |= acpi_ev_sci_dispatch();
139a2fd4b4bSLv Zheng 
140*9187a415SLv Zheng 	acpi_sci_count++;
141fd1af712SBob Moore 	return_UINT32(interrupt_handled);
14295b482a8SLen Brown }
14395b482a8SLen Brown 
14495b482a8SLen Brown /*******************************************************************************
14595b482a8SLen Brown  *
14695b482a8SLen Brown  * FUNCTION:    acpi_ev_gpe_xrupt_handler
14795b482a8SLen Brown  *
148ba494beeSBob Moore  * PARAMETERS:  context   - Calling Context
14995b482a8SLen Brown  *
15095b482a8SLen Brown  * RETURN:      Status code indicates whether interrupt was handled.
15195b482a8SLen Brown  *
15295b482a8SLen Brown  * DESCRIPTION: Handler for GPE Block Device interrupts
15395b482a8SLen Brown  *
15495b482a8SLen Brown  ******************************************************************************/
15595b482a8SLen Brown 
15695b482a8SLen Brown u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
15795b482a8SLen Brown {
15895b482a8SLen Brown 	struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
15995b482a8SLen Brown 	u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
16095b482a8SLen Brown 
16195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
16295b482a8SLen Brown 
16395b482a8SLen Brown 	/*
16495b482a8SLen Brown 	 * We are guaranteed by the ACPICA initialization/shutdown code that
16595b482a8SLen Brown 	 * if this interrupt handler is installed, ACPI is enabled.
16695b482a8SLen Brown 	 */
16795b482a8SLen Brown 
16895b482a8SLen Brown 	/* GPEs: Check for and dispatch any GPEs that have occurred */
16995b482a8SLen Brown 
17095b482a8SLen Brown 	interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
171fd1af712SBob Moore 	return_UINT32(interrupt_handled);
17295b482a8SLen Brown }
17395b482a8SLen Brown 
17495b482a8SLen Brown /******************************************************************************
17595b482a8SLen Brown  *
17695b482a8SLen Brown  * FUNCTION:    acpi_ev_install_sci_handler
17795b482a8SLen Brown  *
17895b482a8SLen Brown  * PARAMETERS:  none
17995b482a8SLen Brown  *
18095b482a8SLen Brown  * RETURN:      Status
18195b482a8SLen Brown  *
18295b482a8SLen Brown  * DESCRIPTION: Installs SCI handler.
18395b482a8SLen Brown  *
18495b482a8SLen Brown  ******************************************************************************/
18595b482a8SLen Brown 
18695b482a8SLen Brown u32 acpi_ev_install_sci_handler(void)
18795b482a8SLen Brown {
18895b482a8SLen Brown 	u32 status = AE_OK;
18995b482a8SLen Brown 
19095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ev_install_sci_handler);
19195b482a8SLen Brown 
19295b482a8SLen Brown 	status =
19395b482a8SLen Brown 	    acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
19495b482a8SLen Brown 					      acpi_ev_sci_xrupt_handler,
19595b482a8SLen Brown 					      acpi_gbl_gpe_xrupt_list_head);
19695b482a8SLen Brown 	return_ACPI_STATUS(status);
19795b482a8SLen Brown }
19895b482a8SLen Brown 
19995b482a8SLen Brown /******************************************************************************
20095b482a8SLen Brown  *
201a2fd4b4bSLv Zheng  * FUNCTION:    acpi_ev_remove_all_sci_handlers
20295b482a8SLen Brown  *
20395b482a8SLen Brown  * PARAMETERS:  none
20495b482a8SLen Brown  *
205a2fd4b4bSLv Zheng  * RETURN:      AE_OK if handler uninstalled, AE_ERROR if handler was not
20695b482a8SLen Brown  *              installed to begin with
20795b482a8SLen Brown  *
20895b482a8SLen Brown  * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
209a2fd4b4bSLv Zheng  *              taken. Remove all host-installed SCI handlers.
21095b482a8SLen Brown  *
21195b482a8SLen Brown  * Note:  It doesn't seem important to disable all events or set the event
21295b482a8SLen Brown  *        enable registers to their original values. The OS should disable
21395b482a8SLen Brown  *        the SCI interrupt level when the handler is removed, so no more
21495b482a8SLen Brown  *        events will come in.
21595b482a8SLen Brown  *
21695b482a8SLen Brown  ******************************************************************************/
21795b482a8SLen Brown 
218a2fd4b4bSLv Zheng acpi_status acpi_ev_remove_all_sci_handlers(void)
21995b482a8SLen Brown {
220a2fd4b4bSLv Zheng 	struct acpi_sci_handler_info *sci_handler;
221a2fd4b4bSLv Zheng 	acpi_cpu_flags flags;
22295b482a8SLen Brown 	acpi_status status;
22395b482a8SLen Brown 
224a2fd4b4bSLv Zheng 	ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
22595b482a8SLen Brown 
22695b482a8SLen Brown 	/* Just let the OS remove the handler and disable the level */
22795b482a8SLen Brown 
22895b482a8SLen Brown 	status =
22995b482a8SLen Brown 	    acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
23095b482a8SLen Brown 					     acpi_ev_sci_xrupt_handler);
23195b482a8SLen Brown 
232a2fd4b4bSLv Zheng 	if (!acpi_gbl_sci_handler_list) {
233a2fd4b4bSLv Zheng 		return (status);
234a2fd4b4bSLv Zheng 	}
235a2fd4b4bSLv Zheng 
236a2fd4b4bSLv Zheng 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
237a2fd4b4bSLv Zheng 
238a2fd4b4bSLv Zheng 	/* Free all host-installed SCI handlers */
239a2fd4b4bSLv Zheng 
240a2fd4b4bSLv Zheng 	while (acpi_gbl_sci_handler_list) {
241a2fd4b4bSLv Zheng 		sci_handler = acpi_gbl_sci_handler_list;
242a2fd4b4bSLv Zheng 		acpi_gbl_sci_handler_list = sci_handler->next;
243a2fd4b4bSLv Zheng 		ACPI_FREE(sci_handler);
244a2fd4b4bSLv Zheng 	}
245a2fd4b4bSLv Zheng 
246a2fd4b4bSLv Zheng 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
24795b482a8SLen Brown 	return_ACPI_STATUS(status);
24895b482a8SLen Brown }
24933620c54SBob Moore 
25033620c54SBob Moore #endif				/* !ACPI_REDUCED_HARDWARE */
251