1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
5  *
6  * Copyright (C) 2000 - 2022, Intel Corp.
7  *
8  *****************************************************************************/
9 
10 #define EXPORT_ACPI_INTERFACES
11 
12 #include <acpi/acpi.h>
13 #include "accommon.h"
14 #include "actables.h"
15 
16 #define _COMPONENT          ACPI_EVENTS
17 ACPI_MODULE_NAME("evxfevnt")
18 
19 #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
20 /*******************************************************************************
21  *
22  * FUNCTION:    acpi_enable
23  *
24  * PARAMETERS:  None
25  *
26  * RETURN:      Status
27  *
28  * DESCRIPTION: Transfers the system into ACPI mode.
29  *
30  ******************************************************************************/
acpi_enable(void)31 acpi_status acpi_enable(void)
32 {
33 	acpi_status status;
34 	int retry;
35 
36 	ACPI_FUNCTION_TRACE(acpi_enable);
37 
38 	/* ACPI tables must be present */
39 
40 	if (acpi_gbl_fadt_index == ACPI_INVALID_TABLE_INDEX) {
41 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
42 	}
43 
44 	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
45 
46 	if (acpi_gbl_reduced_hardware) {
47 		return_ACPI_STATUS(AE_OK);
48 	}
49 
50 	/* Check current mode */
51 
52 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
53 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
54 				  "System is already in ACPI mode\n"));
55 		return_ACPI_STATUS(AE_OK);
56 	}
57 
58 	/* Transition to ACPI mode */
59 
60 	status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
61 	if (ACPI_FAILURE(status)) {
62 		ACPI_ERROR((AE_INFO,
63 			    "Could not transition to ACPI mode"));
64 		return_ACPI_STATUS(status);
65 	}
66 
67 	/* Sanity check that transition succeeded */
68 
69 	for (retry = 0; retry < 30000; ++retry) {
70 		if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
71 			if (retry != 0)
72 				ACPI_WARNING((AE_INFO,
73 				"Platform took > %d00 usec to enter ACPI mode", retry));
74 			return_ACPI_STATUS(AE_OK);
75 		}
76 		acpi_os_stall(100);	/* 100 usec */
77 	}
78 
79 	ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
80 	return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
81 }
82 
ACPI_EXPORT_SYMBOL(acpi_enable)83 ACPI_EXPORT_SYMBOL(acpi_enable)
84 
85 /*******************************************************************************
86  *
87  * FUNCTION:    acpi_disable
88  *
89  * PARAMETERS:  None
90  *
91  * RETURN:      Status
92  *
93  * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
94  *
95  ******************************************************************************/
96 acpi_status acpi_disable(void)
97 {
98 	acpi_status status = AE_OK;
99 
100 	ACPI_FUNCTION_TRACE(acpi_disable);
101 
102 	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
103 
104 	if (acpi_gbl_reduced_hardware) {
105 		return_ACPI_STATUS(AE_OK);
106 	}
107 
108 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
109 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
110 				  "System is already in legacy (non-ACPI) mode\n"));
111 	} else {
112 		/* Transition to LEGACY mode */
113 
114 		status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
115 
116 		if (ACPI_FAILURE(status)) {
117 			ACPI_ERROR((AE_INFO,
118 				    "Could not exit ACPI mode to legacy mode"));
119 			return_ACPI_STATUS(status);
120 		}
121 
122 		ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
123 	}
124 
125 	return_ACPI_STATUS(status);
126 }
127 
ACPI_EXPORT_SYMBOL(acpi_disable)128 ACPI_EXPORT_SYMBOL(acpi_disable)
129 
130 /*******************************************************************************
131  *
132  * FUNCTION:    acpi_enable_event
133  *
134  * PARAMETERS:  event           - The fixed eventto be enabled
135  *              flags           - Reserved
136  *
137  * RETURN:      Status
138  *
139  * DESCRIPTION: Enable an ACPI event (fixed)
140  *
141  ******************************************************************************/
142 acpi_status acpi_enable_event(u32 event, u32 flags)
143 {
144 	acpi_status status = AE_OK;
145 	u32 value;
146 
147 	ACPI_FUNCTION_TRACE(acpi_enable_event);
148 
149 	/* If Hardware Reduced flag is set, there are no fixed events */
150 
151 	if (acpi_gbl_reduced_hardware) {
152 		return_ACPI_STATUS(AE_OK);
153 	}
154 
155 	/* Decode the Fixed Event */
156 
157 	if (event > ACPI_EVENT_MAX) {
158 		return_ACPI_STATUS(AE_BAD_PARAMETER);
159 	}
160 
161 	/*
162 	 * Enable the requested fixed event (by writing a one to the enable
163 	 * register bit)
164 	 */
165 	status =
166 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
167 				    enable_register_id, ACPI_ENABLE_EVENT);
168 	if (ACPI_FAILURE(status)) {
169 		return_ACPI_STATUS(status);
170 	}
171 
172 	/* Make sure that the hardware responded */
173 
174 	status =
175 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
176 				   enable_register_id, &value);
177 	if (ACPI_FAILURE(status)) {
178 		return_ACPI_STATUS(status);
179 	}
180 
181 	if (value != 1) {
182 		ACPI_ERROR((AE_INFO,
183 			    "Could not enable %s event",
184 			    acpi_ut_get_event_name(event)));
185 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
186 	}
187 
188 	return_ACPI_STATUS(status);
189 }
190 
ACPI_EXPORT_SYMBOL(acpi_enable_event)191 ACPI_EXPORT_SYMBOL(acpi_enable_event)
192 
193 /*******************************************************************************
194  *
195  * FUNCTION:    acpi_disable_event
196  *
197  * PARAMETERS:  event           - The fixed event to be disabled
198  *              flags           - Reserved
199  *
200  * RETURN:      Status
201  *
202  * DESCRIPTION: Disable an ACPI event (fixed)
203  *
204  ******************************************************************************/
205 acpi_status acpi_disable_event(u32 event, u32 flags)
206 {
207 	acpi_status status = AE_OK;
208 	u32 value;
209 
210 	ACPI_FUNCTION_TRACE(acpi_disable_event);
211 
212 	/* If Hardware Reduced flag is set, there are no fixed events */
213 
214 	if (acpi_gbl_reduced_hardware) {
215 		return_ACPI_STATUS(AE_OK);
216 	}
217 
218 	/* Decode the Fixed Event */
219 
220 	if (event > ACPI_EVENT_MAX) {
221 		return_ACPI_STATUS(AE_BAD_PARAMETER);
222 	}
223 
224 	/*
225 	 * Disable the requested fixed event (by writing a zero to the enable
226 	 * register bit)
227 	 */
228 	status =
229 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
230 				    enable_register_id, ACPI_DISABLE_EVENT);
231 	if (ACPI_FAILURE(status)) {
232 		return_ACPI_STATUS(status);
233 	}
234 
235 	status =
236 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
237 				   enable_register_id, &value);
238 	if (ACPI_FAILURE(status)) {
239 		return_ACPI_STATUS(status);
240 	}
241 
242 	if (value != 0) {
243 		ACPI_ERROR((AE_INFO,
244 			    "Could not disable %s events",
245 			    acpi_ut_get_event_name(event)));
246 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
247 	}
248 
249 	return_ACPI_STATUS(status);
250 }
251 
ACPI_EXPORT_SYMBOL(acpi_disable_event)252 ACPI_EXPORT_SYMBOL(acpi_disable_event)
253 
254 /*******************************************************************************
255  *
256  * FUNCTION:    acpi_clear_event
257  *
258  * PARAMETERS:  event           - The fixed event to be cleared
259  *
260  * RETURN:      Status
261  *
262  * DESCRIPTION: Clear an ACPI event (fixed)
263  *
264  ******************************************************************************/
265 acpi_status acpi_clear_event(u32 event)
266 {
267 	acpi_status status = AE_OK;
268 
269 	ACPI_FUNCTION_TRACE(acpi_clear_event);
270 
271 	/* If Hardware Reduced flag is set, there are no fixed events */
272 
273 	if (acpi_gbl_reduced_hardware) {
274 		return_ACPI_STATUS(AE_OK);
275 	}
276 
277 	/* Decode the Fixed Event */
278 
279 	if (event > ACPI_EVENT_MAX) {
280 		return_ACPI_STATUS(AE_BAD_PARAMETER);
281 	}
282 
283 	/*
284 	 * Clear the requested fixed event (By writing a one to the status
285 	 * register bit)
286 	 */
287 	status =
288 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
289 				    status_register_id, ACPI_CLEAR_STATUS);
290 
291 	return_ACPI_STATUS(status);
292 }
293 
ACPI_EXPORT_SYMBOL(acpi_clear_event)294 ACPI_EXPORT_SYMBOL(acpi_clear_event)
295 
296 /*******************************************************************************
297  *
298  * FUNCTION:    acpi_get_event_status
299  *
300  * PARAMETERS:  event           - The fixed event
301  *              event_status    - Where the current status of the event will
302  *                                be returned
303  *
304  * RETURN:      Status
305  *
306  * DESCRIPTION: Obtains and returns the current status of the event
307  *
308  ******************************************************************************/
309 acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
310 {
311 	acpi_status status;
312 	acpi_event_status local_event_status = 0;
313 	u32 in_byte;
314 
315 	ACPI_FUNCTION_TRACE(acpi_get_event_status);
316 
317 	if (!event_status) {
318 		return_ACPI_STATUS(AE_BAD_PARAMETER);
319 	}
320 
321 	/* Decode the Fixed Event */
322 
323 	if (event > ACPI_EVENT_MAX) {
324 		return_ACPI_STATUS(AE_BAD_PARAMETER);
325 	}
326 
327 	/* Fixed event currently can be dispatched? */
328 
329 	if (acpi_gbl_fixed_event_handlers[event].handler) {
330 		local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
331 	}
332 
333 	/* Fixed event currently enabled? */
334 
335 	status =
336 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
337 				   enable_register_id, &in_byte);
338 	if (ACPI_FAILURE(status)) {
339 		return_ACPI_STATUS(status);
340 	}
341 
342 	if (in_byte) {
343 		local_event_status |=
344 		    (ACPI_EVENT_FLAG_ENABLED | ACPI_EVENT_FLAG_ENABLE_SET);
345 	}
346 
347 	/* Fixed event currently active? */
348 
349 	status =
350 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
351 				   status_register_id, &in_byte);
352 	if (ACPI_FAILURE(status)) {
353 		return_ACPI_STATUS(status);
354 	}
355 
356 	if (in_byte) {
357 		local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
358 	}
359 
360 	(*event_status) = local_event_status;
361 	return_ACPI_STATUS(AE_OK);
362 }
363 
364 ACPI_EXPORT_SYMBOL(acpi_get_event_status)
365 #endif				/* !ACPI_REDUCED_HARDWARE */
366