Linux-libre 5.4.48-gnu
[librecmc/linux-libre.git] / drivers / acpi / acpica / evsci.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
3  *
4  * Module Name: evsci - System Control Interrupt configuration and
5  *                      legacy to ACPI mode state transition functions
6  *
7  ******************************************************************************/
8
9 #include <acpi/acpi.h>
10 #include "accommon.h"
11 #include "acevents.h"
12
13 #define _COMPONENT          ACPI_EVENTS
14 ACPI_MODULE_NAME("evsci")
15 #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
16 /* Local prototypes */
17 static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
18
19 /*******************************************************************************
20  *
21  * FUNCTION:    acpi_ev_sci_dispatch
22  *
23  * PARAMETERS:  None
24  *
25  * RETURN:      Status code indicates whether interrupt was handled.
26  *
27  * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
28  *
29  ******************************************************************************/
30
31 u32 acpi_ev_sci_dispatch(void)
32 {
33         struct acpi_sci_handler_info *sci_handler;
34         acpi_cpu_flags flags;
35         u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
36
37         ACPI_FUNCTION_NAME(ev_sci_dispatch);
38
39         /* Are there any host-installed SCI handlers? */
40
41         if (!acpi_gbl_sci_handler_list) {
42                 return (int_status);
43         }
44
45         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
46
47         /* Invoke all host-installed SCI handlers */
48
49         sci_handler = acpi_gbl_sci_handler_list;
50         while (sci_handler) {
51
52                 /* Invoke the installed handler (at interrupt level) */
53
54                 int_status |= sci_handler->address(sci_handler->context);
55
56                 sci_handler = sci_handler->next;
57         }
58
59         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
60         return (int_status);
61 }
62
63 /*******************************************************************************
64  *
65  * FUNCTION:    acpi_ev_sci_xrupt_handler
66  *
67  * PARAMETERS:  context   - Calling Context
68  *
69  * RETURN:      Status code indicates whether interrupt was handled.
70  *
71  * DESCRIPTION: Interrupt handler that will figure out what function or
72  *              control method to call to deal with a SCI.
73  *
74  ******************************************************************************/
75
76 static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
77 {
78         struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
79         u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
80
81         ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
82
83         /*
84          * We are guaranteed by the ACPICA initialization/shutdown code that
85          * if this interrupt handler is installed, ACPI is enabled.
86          */
87
88         /*
89          * Fixed Events:
90          * Check for and dispatch any Fixed Events that have occurred
91          */
92         interrupt_handled |= acpi_ev_fixed_event_detect();
93
94         /*
95          * General Purpose Events:
96          * Check for and dispatch any GPEs that have occurred
97          */
98         interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
99
100         /* Invoke all host-installed SCI handlers */
101
102         interrupt_handled |= acpi_ev_sci_dispatch();
103
104         acpi_sci_count++;
105         return_UINT32(interrupt_handled);
106 }
107
108 /*******************************************************************************
109  *
110  * FUNCTION:    acpi_ev_gpe_xrupt_handler
111  *
112  * PARAMETERS:  context   - Calling Context
113  *
114  * RETURN:      Status code indicates whether interrupt was handled.
115  *
116  * DESCRIPTION: Handler for GPE Block Device interrupts
117  *
118  ******************************************************************************/
119
120 u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
121 {
122         struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
123         u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
124
125         ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
126
127         /*
128          * We are guaranteed by the ACPICA initialization/shutdown code that
129          * if this interrupt handler is installed, ACPI is enabled.
130          */
131
132         /* GPEs: Check for and dispatch any GPEs that have occurred */
133
134         interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
135         return_UINT32(interrupt_handled);
136 }
137
138 /******************************************************************************
139  *
140  * FUNCTION:    acpi_ev_install_sci_handler
141  *
142  * PARAMETERS:  none
143  *
144  * RETURN:      Status
145  *
146  * DESCRIPTION: Installs SCI handler.
147  *
148  ******************************************************************************/
149
150 u32 acpi_ev_install_sci_handler(void)
151 {
152         u32 status = AE_OK;
153
154         ACPI_FUNCTION_TRACE(ev_install_sci_handler);
155
156         status =
157             acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
158                                               acpi_ev_sci_xrupt_handler,
159                                               acpi_gbl_gpe_xrupt_list_head);
160         return_ACPI_STATUS(status);
161 }
162
163 /******************************************************************************
164  *
165  * FUNCTION:    acpi_ev_remove_all_sci_handlers
166  *
167  * PARAMETERS:  none
168  *
169  * RETURN:      AE_OK if handler uninstalled, AE_ERROR if handler was not
170  *              installed to begin with
171  *
172  * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
173  *              taken. Remove all host-installed SCI handlers.
174  *
175  * Note:  It doesn't seem important to disable all events or set the event
176  *        enable registers to their original values. The OS should disable
177  *        the SCI interrupt level when the handler is removed, so no more
178  *        events will come in.
179  *
180  ******************************************************************************/
181
182 acpi_status acpi_ev_remove_all_sci_handlers(void)
183 {
184         struct acpi_sci_handler_info *sci_handler;
185         acpi_cpu_flags flags;
186         acpi_status status;
187
188         ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
189
190         /* Just let the OS remove the handler and disable the level */
191
192         status =
193             acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
194                                              acpi_ev_sci_xrupt_handler);
195
196         if (!acpi_gbl_sci_handler_list) {
197                 return (status);
198         }
199
200         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
201
202         /* Free all host-installed SCI handlers */
203
204         while (acpi_gbl_sci_handler_list) {
205                 sci_handler = acpi_gbl_sci_handler_list;
206                 acpi_gbl_sci_handler_list = sci_handler->next;
207                 ACPI_FREE(sci_handler);
208         }
209
210         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
211         return_ACPI_STATUS(status);
212 }
213
214 #endif                          /* !ACPI_REDUCED_HARDWARE */