162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/******************************************************************************* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: evsci - System Control Interrupt configuration and 562306a36Sopenharmony_ci * legacy to ACPI mode state transition functions 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci ******************************************************************************/ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <acpi/acpi.h> 1062306a36Sopenharmony_ci#include "accommon.h" 1162306a36Sopenharmony_ci#include "acevents.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define _COMPONENT ACPI_EVENTS 1462306a36Sopenharmony_ciACPI_MODULE_NAME("evsci") 1562306a36Sopenharmony_ci#if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 1662306a36Sopenharmony_ci/* Local prototypes */ 1762306a36Sopenharmony_cistatic u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context); 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/******************************************************************************* 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * FUNCTION: acpi_ev_sci_dispatch 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * PARAMETERS: None 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * RETURN: Status code indicates whether interrupt was handled. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci ******************************************************************************/ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciu32 acpi_ev_sci_dispatch(void) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci struct acpi_sci_handler_info *sci_handler; 3462306a36Sopenharmony_ci acpi_cpu_flags flags; 3562306a36Sopenharmony_ci u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci ACPI_FUNCTION_NAME(ev_sci_dispatch); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci /* Are there any host-installed SCI handlers? */ 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci if (!acpi_gbl_sci_handler_list) { 4262306a36Sopenharmony_ci return (int_status); 4362306a36Sopenharmony_ci } 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci /* Invoke all host-installed SCI handlers */ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci sci_handler = acpi_gbl_sci_handler_list; 5062306a36Sopenharmony_ci while (sci_handler) { 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci /* Invoke the installed handler (at interrupt level) */ 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci int_status |= sci_handler->address(sci_handler->context); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci sci_handler = sci_handler->next; 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 6062306a36Sopenharmony_ci return (int_status); 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/******************************************************************************* 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * FUNCTION: acpi_ev_sci_xrupt_handler 6662306a36Sopenharmony_ci * 6762306a36Sopenharmony_ci * PARAMETERS: context - Calling Context 6862306a36Sopenharmony_ci * 6962306a36Sopenharmony_ci * RETURN: Status code indicates whether interrupt was handled. 7062306a36Sopenharmony_ci * 7162306a36Sopenharmony_ci * DESCRIPTION: Interrupt handler that will figure out what function or 7262306a36Sopenharmony_ci * control method to call to deal with a SCI. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci ******************************************************************************/ 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; 7962306a36Sopenharmony_ci u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* 8462306a36Sopenharmony_ci * We are guaranteed by the ACPICA initialization/shutdown code that 8562306a36Sopenharmony_ci * if this interrupt handler is installed, ACPI is enabled. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* 8962306a36Sopenharmony_ci * Fixed Events: 9062306a36Sopenharmony_ci * Check for and dispatch any Fixed Events that have occurred 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_ci interrupt_handled |= acpi_ev_fixed_event_detect(); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /* 9562306a36Sopenharmony_ci * General Purpose Events: 9662306a36Sopenharmony_ci * Check for and dispatch any GPEs that have occurred 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* Invoke all host-installed SCI handlers */ 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci interrupt_handled |= acpi_ev_sci_dispatch(); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci acpi_sci_count++; 10562306a36Sopenharmony_ci return_UINT32(interrupt_handled); 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/******************************************************************************* 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * FUNCTION: acpi_ev_gpe_xrupt_handler 11162306a36Sopenharmony_ci * 11262306a36Sopenharmony_ci * PARAMETERS: context - Calling Context 11362306a36Sopenharmony_ci * 11462306a36Sopenharmony_ci * RETURN: Status code indicates whether interrupt was handled. 11562306a36Sopenharmony_ci * 11662306a36Sopenharmony_ci * DESCRIPTION: Handler for GPE Block Device interrupts 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci ******************************************************************************/ 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ciu32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; 12362306a36Sopenharmony_ci u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* 12862306a36Sopenharmony_ci * We are guaranteed by the ACPICA initialization/shutdown code that 12962306a36Sopenharmony_ci * if this interrupt handler is installed, ACPI is enabled. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* GPEs: Check for and dispatch any GPEs that have occurred */ 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); 13562306a36Sopenharmony_ci return_UINT32(interrupt_handled); 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/****************************************************************************** 13962306a36Sopenharmony_ci * 14062306a36Sopenharmony_ci * FUNCTION: acpi_ev_install_sci_handler 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * PARAMETERS: none 14362306a36Sopenharmony_ci * 14462306a36Sopenharmony_ci * RETURN: Status 14562306a36Sopenharmony_ci * 14662306a36Sopenharmony_ci * DESCRIPTION: Installs SCI handler. 14762306a36Sopenharmony_ci * 14862306a36Sopenharmony_ci ******************************************************************************/ 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ciu32 acpi_ev_install_sci_handler(void) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci u32 status = AE_OK; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ev_install_sci_handler); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci status = 15762306a36Sopenharmony_ci acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, 15862306a36Sopenharmony_ci acpi_ev_sci_xrupt_handler, 15962306a36Sopenharmony_ci acpi_gbl_gpe_xrupt_list_head); 16062306a36Sopenharmony_ci return_ACPI_STATUS(status); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci/****************************************************************************** 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * FUNCTION: acpi_ev_remove_all_sci_handlers 16662306a36Sopenharmony_ci * 16762306a36Sopenharmony_ci * PARAMETERS: none 16862306a36Sopenharmony_ci * 16962306a36Sopenharmony_ci * RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not 17062306a36Sopenharmony_ci * installed to begin with 17162306a36Sopenharmony_ci * 17262306a36Sopenharmony_ci * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be 17362306a36Sopenharmony_ci * taken. Remove all host-installed SCI handlers. 17462306a36Sopenharmony_ci * 17562306a36Sopenharmony_ci * Note: It doesn't seem important to disable all events or set the event 17662306a36Sopenharmony_ci * enable registers to their original values. The OS should disable 17762306a36Sopenharmony_ci * the SCI interrupt level when the handler is removed, so no more 17862306a36Sopenharmony_ci * events will come in. 17962306a36Sopenharmony_ci * 18062306a36Sopenharmony_ci ******************************************************************************/ 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ciacpi_status acpi_ev_remove_all_sci_handlers(void) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci struct acpi_sci_handler_info *sci_handler; 18562306a36Sopenharmony_ci acpi_cpu_flags flags; 18662306a36Sopenharmony_ci acpi_status status; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* Just let the OS remove the handler and disable the level */ 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci status = 19362306a36Sopenharmony_ci acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, 19462306a36Sopenharmony_ci acpi_ev_sci_xrupt_handler); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (!acpi_gbl_sci_handler_list) { 19762306a36Sopenharmony_ci return (status); 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci /* Free all host-installed SCI handlers */ 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci while (acpi_gbl_sci_handler_list) { 20562306a36Sopenharmony_ci sci_handler = acpi_gbl_sci_handler_list; 20662306a36Sopenharmony_ci acpi_gbl_sci_handler_list = sci_handler->next; 20762306a36Sopenharmony_ci ACPI_FREE(sci_handler); 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 21162306a36Sopenharmony_ci return_ACPI_STATUS(status); 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci#endif /* !ACPI_REDUCED_HARDWARE */ 215