ACPICA: Fix a comment "enable" fixed events -> "disable" all fixed events.
[linux-2.6-microblaze.git] / drivers / acpi / acpica / evevent.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: evevent - Fixed Event handling and dispatch
5  *
6  * Copyright (C) 2000 - 2020, Intel Corp.
7  *
8  *****************************************************************************/
9
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acevents.h"
13
14 #define _COMPONENT          ACPI_EVENTS
15 ACPI_MODULE_NAME("evevent")
16 #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
17 /* Local prototypes */
18 static acpi_status acpi_ev_fixed_event_initialize(void);
19
20 static u32 acpi_ev_fixed_event_dispatch(u32 event);
21
22 /*******************************************************************************
23  *
24  * FUNCTION:    acpi_ev_initialize_events
25  *
26  * PARAMETERS:  None
27  *
28  * RETURN:      Status
29  *
30  * DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE)
31  *
32  ******************************************************************************/
33
34 acpi_status acpi_ev_initialize_events(void)
35 {
36         acpi_status status;
37
38         ACPI_FUNCTION_TRACE(ev_initialize_events);
39
40         /* If Hardware Reduced flag is set, there are no fixed events */
41
42         if (acpi_gbl_reduced_hardware) {
43                 return_ACPI_STATUS(AE_OK);
44         }
45
46         /*
47          * Initialize the Fixed and General Purpose Events. This is done prior to
48          * enabling SCIs to prevent interrupts from occurring before the handlers
49          * are installed.
50          */
51         status = acpi_ev_fixed_event_initialize();
52         if (ACPI_FAILURE(status)) {
53                 ACPI_EXCEPTION((AE_INFO, status,
54                                 "Unable to initialize fixed events"));
55                 return_ACPI_STATUS(status);
56         }
57
58         status = acpi_ev_gpe_initialize();
59         if (ACPI_FAILURE(status)) {
60                 ACPI_EXCEPTION((AE_INFO, status,
61                                 "Unable to initialize general purpose events"));
62                 return_ACPI_STATUS(status);
63         }
64
65         return_ACPI_STATUS(status);
66 }
67
68 /*******************************************************************************
69  *
70  * FUNCTION:    acpi_ev_install_xrupt_handlers
71  *
72  * PARAMETERS:  None
73  *
74  * RETURN:      Status
75  *
76  * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock
77  *
78  ******************************************************************************/
79
80 acpi_status acpi_ev_install_xrupt_handlers(void)
81 {
82         acpi_status status;
83
84         ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers);
85
86         /* If Hardware Reduced flag is set, there is no ACPI h/w */
87
88         if (acpi_gbl_reduced_hardware) {
89                 return_ACPI_STATUS(AE_OK);
90         }
91
92         /* Install the SCI handler */
93
94         status = acpi_ev_install_sci_handler();
95         if (ACPI_FAILURE(status)) {
96                 ACPI_EXCEPTION((AE_INFO, status,
97                                 "Unable to install System Control Interrupt handler"));
98                 return_ACPI_STATUS(status);
99         }
100
101         /* Install the handler for the Global Lock */
102
103         status = acpi_ev_init_global_lock_handler();
104         if (ACPI_FAILURE(status)) {
105                 ACPI_EXCEPTION((AE_INFO, status,
106                                 "Unable to initialize Global Lock handler"));
107                 return_ACPI_STATUS(status);
108         }
109
110         acpi_gbl_events_initialized = TRUE;
111         return_ACPI_STATUS(status);
112 }
113
114 /*******************************************************************************
115  *
116  * FUNCTION:    acpi_ev_fixed_event_initialize
117  *
118  * PARAMETERS:  None
119  *
120  * RETURN:      Status
121  *
122  * DESCRIPTION: Install the fixed event handlers and disable all fixed events.
123  *
124  ******************************************************************************/
125
126 static acpi_status acpi_ev_fixed_event_initialize(void)
127 {
128         u32 i;
129         acpi_status status;
130
131         /*
132          * Initialize the structure that keeps track of fixed event handlers and
133          * disable all of the fixed events.
134          */
135         for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
136                 acpi_gbl_fixed_event_handlers[i].handler = NULL;
137                 acpi_gbl_fixed_event_handlers[i].context = NULL;
138
139                 /* Disable the fixed event */
140
141                 if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) {
142                         status =
143                             acpi_write_bit_register(acpi_gbl_fixed_event_info
144                                                     [i].enable_register_id,
145                                                     ACPI_DISABLE_EVENT);
146                         if (ACPI_FAILURE(status)) {
147                                 return (status);
148                         }
149                 }
150         }
151
152         return (AE_OK);
153 }
154
155 /*******************************************************************************
156  *
157  * FUNCTION:    acpi_ev_fixed_event_detect
158  *
159  * PARAMETERS:  None
160  *
161  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
162  *
163  * DESCRIPTION: Checks the PM status register for active fixed events
164  *
165  ******************************************************************************/
166
167 u32 acpi_ev_fixed_event_detect(void)
168 {
169         u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
170         u32 fixed_status;
171         u32 fixed_enable;
172         u32 i;
173         acpi_status status;
174
175         ACPI_FUNCTION_NAME(ev_fixed_event_detect);
176
177         /*
178          * Read the fixed feature status and enable registers, as all the cases
179          * depend on their values. Ignore errors here.
180          */
181         status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
182         status |=
183             acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
184         if (ACPI_FAILURE(status)) {
185                 return (int_status);
186         }
187
188         ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
189                           "Fixed Event Block: Enable %08X Status %08X\n",
190                           fixed_enable, fixed_status));
191
192         /*
193          * Check for all possible Fixed Events and dispatch those that are active
194          */
195         for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
196
197                 /* Both the status and enable bits must be on for this event */
198
199                 if ((fixed_status & acpi_gbl_fixed_event_info[i].
200                      status_bit_mask)
201                     && (fixed_enable & acpi_gbl_fixed_event_info[i].
202                         enable_bit_mask)) {
203                         /*
204                          * Found an active (signalled) event. Invoke global event
205                          * handler if present.
206                          */
207                         acpi_fixed_event_count[i]++;
208                         if (acpi_gbl_global_event_handler) {
209                                 acpi_gbl_global_event_handler
210                                     (ACPI_EVENT_TYPE_FIXED, NULL, i,
211                                      acpi_gbl_global_event_handler_context);
212                         }
213
214                         int_status |= acpi_ev_fixed_event_dispatch(i);
215                 }
216         }
217
218         return (int_status);
219 }
220
221 /*******************************************************************************
222  *
223  * FUNCTION:    acpi_ev_fixed_event_dispatch
224  *
225  * PARAMETERS:  event               - Event type
226  *
227  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
228  *
229  * DESCRIPTION: Clears the status bit for the requested event, calls the
230  *              handler that previously registered for the event.
231  *              NOTE: If there is no handler for the event, the event is
232  *              disabled to prevent further interrupts.
233  *
234  ******************************************************************************/
235
236 static u32 acpi_ev_fixed_event_dispatch(u32 event)
237 {
238
239         ACPI_FUNCTION_ENTRY();
240
241         /* Clear the status bit */
242
243         (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
244                                       status_register_id, ACPI_CLEAR_STATUS);
245
246         /*
247          * Make sure that a handler exists. If not, report an error
248          * and disable the event to prevent further interrupts.
249          */
250         if (!acpi_gbl_fixed_event_handlers[event].handler) {
251                 (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
252                                               enable_register_id,
253                                               ACPI_DISABLE_EVENT);
254
255                 ACPI_ERROR((AE_INFO,
256                             "No installed handler for fixed event - %s (%u), disabling",
257                             acpi_ut_get_event_name(event), event));
258
259                 return (ACPI_INTERRUPT_NOT_HANDLED);
260         }
261
262         /* Invoke the Fixed Event handler */
263
264         return ((acpi_gbl_fixed_event_handlers[event].
265                  handler) (acpi_gbl_fixed_event_handlers[event].context));
266 }
267
268 #endif                          /* !ACPI_REDUCED_HARDWARE */