xref: /openbmc/linux/drivers/acpi/acpica/evxfevnt.c (revision dea54fba)
1 /******************************************************************************
2  *
3  * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #define EXPORT_ACPI_INTERFACES
45 
46 #include <acpi/acpi.h>
47 #include "accommon.h"
48 #include "actables.h"
49 
50 #define _COMPONENT          ACPI_EVENTS
51 ACPI_MODULE_NAME("evxfevnt")
52 
53 #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
54 /*******************************************************************************
55  *
56  * FUNCTION:    acpi_enable
57  *
58  * PARAMETERS:  None
59  *
60  * RETURN:      Status
61  *
62  * DESCRIPTION: Transfers the system into ACPI mode.
63  *
64  ******************************************************************************/
65 acpi_status acpi_enable(void)
66 {
67 	acpi_status status;
68 	int retry;
69 
70 	ACPI_FUNCTION_TRACE(acpi_enable);
71 
72 	/* ACPI tables must be present */
73 
74 	if (acpi_gbl_fadt_index == ACPI_INVALID_TABLE_INDEX) {
75 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
76 	}
77 
78 	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
79 
80 	if (acpi_gbl_reduced_hardware) {
81 		return_ACPI_STATUS(AE_OK);
82 	}
83 
84 	/* Check current mode */
85 
86 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
87 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
88 				  "System is already in ACPI mode\n"));
89 		return_ACPI_STATUS(AE_OK);
90 	}
91 
92 	/* Transition to ACPI mode */
93 
94 	status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
95 	if (ACPI_FAILURE(status)) {
96 		ACPI_ERROR((AE_INFO,
97 			    "Could not transition to ACPI mode"));
98 		return_ACPI_STATUS(status);
99 	}
100 
101 	/* Sanity check that transition succeeded */
102 
103 	for (retry = 0; retry < 30000; ++retry) {
104 		if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
105 			if (retry != 0)
106 				ACPI_WARNING((AE_INFO,
107 				"Platform took > %d00 usec to enter ACPI mode", retry));
108 			return_ACPI_STATUS(AE_OK);
109 		}
110 		acpi_os_stall(100);	/* 100 usec */
111 	}
112 
113 	ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
114 	return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
115 }
116 
117 ACPI_EXPORT_SYMBOL(acpi_enable)
118 
119 /*******************************************************************************
120  *
121  * FUNCTION:    acpi_disable
122  *
123  * PARAMETERS:  None
124  *
125  * RETURN:      Status
126  *
127  * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
128  *
129  ******************************************************************************/
130 acpi_status acpi_disable(void)
131 {
132 	acpi_status status = AE_OK;
133 
134 	ACPI_FUNCTION_TRACE(acpi_disable);
135 
136 	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
137 
138 	if (acpi_gbl_reduced_hardware) {
139 		return_ACPI_STATUS(AE_OK);
140 	}
141 
142 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
143 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
144 				  "System is already in legacy (non-ACPI) mode\n"));
145 	} else {
146 		/* Transition to LEGACY mode */
147 
148 		status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
149 
150 		if (ACPI_FAILURE(status)) {
151 			ACPI_ERROR((AE_INFO,
152 				    "Could not exit ACPI mode to legacy mode"));
153 			return_ACPI_STATUS(status);
154 		}
155 
156 		ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
157 	}
158 
159 	return_ACPI_STATUS(status);
160 }
161 
162 ACPI_EXPORT_SYMBOL(acpi_disable)
163 
164 /*******************************************************************************
165  *
166  * FUNCTION:    acpi_enable_event
167  *
168  * PARAMETERS:  event           - The fixed eventto be enabled
169  *              flags           - Reserved
170  *
171  * RETURN:      Status
172  *
173  * DESCRIPTION: Enable an ACPI event (fixed)
174  *
175  ******************************************************************************/
176 acpi_status acpi_enable_event(u32 event, u32 flags)
177 {
178 	acpi_status status = AE_OK;
179 	u32 value;
180 
181 	ACPI_FUNCTION_TRACE(acpi_enable_event);
182 
183 	/* If Hardware Reduced flag is set, there are no fixed events */
184 
185 	if (acpi_gbl_reduced_hardware) {
186 		return_ACPI_STATUS(AE_OK);
187 	}
188 
189 	/* Decode the Fixed Event */
190 
191 	if (event > ACPI_EVENT_MAX) {
192 		return_ACPI_STATUS(AE_BAD_PARAMETER);
193 	}
194 
195 	/*
196 	 * Enable the requested fixed event (by writing a one to the enable
197 	 * register bit)
198 	 */
199 	status =
200 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
201 				    enable_register_id, ACPI_ENABLE_EVENT);
202 	if (ACPI_FAILURE(status)) {
203 		return_ACPI_STATUS(status);
204 	}
205 
206 	/* Make sure that the hardware responded */
207 
208 	status =
209 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
210 				   enable_register_id, &value);
211 	if (ACPI_FAILURE(status)) {
212 		return_ACPI_STATUS(status);
213 	}
214 
215 	if (value != 1) {
216 		ACPI_ERROR((AE_INFO,
217 			    "Could not enable %s event",
218 			    acpi_ut_get_event_name(event)));
219 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
220 	}
221 
222 	return_ACPI_STATUS(status);
223 }
224 
225 ACPI_EXPORT_SYMBOL(acpi_enable_event)
226 
227 /*******************************************************************************
228  *
229  * FUNCTION:    acpi_disable_event
230  *
231  * PARAMETERS:  event           - The fixed event to be disabled
232  *              flags           - Reserved
233  *
234  * RETURN:      Status
235  *
236  * DESCRIPTION: Disable an ACPI event (fixed)
237  *
238  ******************************************************************************/
239 acpi_status acpi_disable_event(u32 event, u32 flags)
240 {
241 	acpi_status status = AE_OK;
242 	u32 value;
243 
244 	ACPI_FUNCTION_TRACE(acpi_disable_event);
245 
246 	/* If Hardware Reduced flag is set, there are no fixed events */
247 
248 	if (acpi_gbl_reduced_hardware) {
249 		return_ACPI_STATUS(AE_OK);
250 	}
251 
252 	/* Decode the Fixed Event */
253 
254 	if (event > ACPI_EVENT_MAX) {
255 		return_ACPI_STATUS(AE_BAD_PARAMETER);
256 	}
257 
258 	/*
259 	 * Disable the requested fixed event (by writing a zero to the enable
260 	 * register bit)
261 	 */
262 	status =
263 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
264 				    enable_register_id, ACPI_DISABLE_EVENT);
265 	if (ACPI_FAILURE(status)) {
266 		return_ACPI_STATUS(status);
267 	}
268 
269 	status =
270 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
271 				   enable_register_id, &value);
272 	if (ACPI_FAILURE(status)) {
273 		return_ACPI_STATUS(status);
274 	}
275 
276 	if (value != 0) {
277 		ACPI_ERROR((AE_INFO,
278 			    "Could not disable %s events",
279 			    acpi_ut_get_event_name(event)));
280 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
281 	}
282 
283 	return_ACPI_STATUS(status);
284 }
285 
286 ACPI_EXPORT_SYMBOL(acpi_disable_event)
287 
288 /*******************************************************************************
289  *
290  * FUNCTION:    acpi_clear_event
291  *
292  * PARAMETERS:  event           - The fixed event to be cleared
293  *
294  * RETURN:      Status
295  *
296  * DESCRIPTION: Clear an ACPI event (fixed)
297  *
298  ******************************************************************************/
299 acpi_status acpi_clear_event(u32 event)
300 {
301 	acpi_status status = AE_OK;
302 
303 	ACPI_FUNCTION_TRACE(acpi_clear_event);
304 
305 	/* If Hardware Reduced flag is set, there are no fixed events */
306 
307 	if (acpi_gbl_reduced_hardware) {
308 		return_ACPI_STATUS(AE_OK);
309 	}
310 
311 	/* Decode the Fixed Event */
312 
313 	if (event > ACPI_EVENT_MAX) {
314 		return_ACPI_STATUS(AE_BAD_PARAMETER);
315 	}
316 
317 	/*
318 	 * Clear the requested fixed event (By writing a one to the status
319 	 * register bit)
320 	 */
321 	status =
322 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
323 				    status_register_id, ACPI_CLEAR_STATUS);
324 
325 	return_ACPI_STATUS(status);
326 }
327 
328 ACPI_EXPORT_SYMBOL(acpi_clear_event)
329 
330 /*******************************************************************************
331  *
332  * FUNCTION:    acpi_get_event_status
333  *
334  * PARAMETERS:  event           - The fixed event
335  *              event_status    - Where the current status of the event will
336  *                                be returned
337  *
338  * RETURN:      Status
339  *
340  * DESCRIPTION: Obtains and returns the current status of the event
341  *
342  ******************************************************************************/
343 acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
344 {
345 	acpi_status status;
346 	acpi_event_status local_event_status = 0;
347 	u32 in_byte;
348 
349 	ACPI_FUNCTION_TRACE(acpi_get_event_status);
350 
351 	if (!event_status) {
352 		return_ACPI_STATUS(AE_BAD_PARAMETER);
353 	}
354 
355 	/* Decode the Fixed Event */
356 
357 	if (event > ACPI_EVENT_MAX) {
358 		return_ACPI_STATUS(AE_BAD_PARAMETER);
359 	}
360 
361 	/* Fixed event currently can be dispatched? */
362 
363 	if (acpi_gbl_fixed_event_handlers[event].handler) {
364 		local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
365 	}
366 
367 	/* Fixed event currently enabled? */
368 
369 	status =
370 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
371 				   enable_register_id, &in_byte);
372 	if (ACPI_FAILURE(status)) {
373 		return_ACPI_STATUS(status);
374 	}
375 
376 	if (in_byte) {
377 		local_event_status |=
378 		    (ACPI_EVENT_FLAG_ENABLED | ACPI_EVENT_FLAG_ENABLE_SET);
379 	}
380 
381 	/* Fixed event currently active? */
382 
383 	status =
384 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
385 				   status_register_id, &in_byte);
386 	if (ACPI_FAILURE(status)) {
387 		return_ACPI_STATUS(status);
388 	}
389 
390 	if (in_byte) {
391 		local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
392 	}
393 
394 	(*event_status) = local_event_status;
395 	return_ACPI_STATUS(AE_OK);
396 }
397 
398 ACPI_EXPORT_SYMBOL(acpi_get_event_status)
399 #endif				/* !ACPI_REDUCED_HARDWARE */
400