xref: /openbmc/linux/drivers/acpi/acpica/evxfevnt.c (revision 8571e645)
1 /******************************************************************************
2  *
3  * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 	/* Decode the Fixed Event */
184 
185 	if (event > ACPI_EVENT_MAX) {
186 		return_ACPI_STATUS(AE_BAD_PARAMETER);
187 	}
188 
189 	/*
190 	 * Enable the requested fixed event (by writing a one to the enable
191 	 * register bit)
192 	 */
193 	status =
194 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
195 				    enable_register_id, ACPI_ENABLE_EVENT);
196 	if (ACPI_FAILURE(status)) {
197 		return_ACPI_STATUS(status);
198 	}
199 
200 	/* Make sure that the hardware responded */
201 
202 	status =
203 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
204 				   enable_register_id, &value);
205 	if (ACPI_FAILURE(status)) {
206 		return_ACPI_STATUS(status);
207 	}
208 
209 	if (value != 1) {
210 		ACPI_ERROR((AE_INFO,
211 			    "Could not enable %s event",
212 			    acpi_ut_get_event_name(event)));
213 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
214 	}
215 
216 	return_ACPI_STATUS(status);
217 }
218 
219 ACPI_EXPORT_SYMBOL(acpi_enable_event)
220 
221 /*******************************************************************************
222  *
223  * FUNCTION:    acpi_disable_event
224  *
225  * PARAMETERS:  event           - The fixed event to be disabled
226  *              flags           - Reserved
227  *
228  * RETURN:      Status
229  *
230  * DESCRIPTION: Disable an ACPI event (fixed)
231  *
232  ******************************************************************************/
233 acpi_status acpi_disable_event(u32 event, u32 flags)
234 {
235 	acpi_status status = AE_OK;
236 	u32 value;
237 
238 	ACPI_FUNCTION_TRACE(acpi_disable_event);
239 
240 	/* Decode the Fixed Event */
241 
242 	if (event > ACPI_EVENT_MAX) {
243 		return_ACPI_STATUS(AE_BAD_PARAMETER);
244 	}
245 
246 	/*
247 	 * Disable the requested fixed event (by writing a zero to the enable
248 	 * register bit)
249 	 */
250 	status =
251 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
252 				    enable_register_id, ACPI_DISABLE_EVENT);
253 	if (ACPI_FAILURE(status)) {
254 		return_ACPI_STATUS(status);
255 	}
256 
257 	status =
258 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
259 				   enable_register_id, &value);
260 	if (ACPI_FAILURE(status)) {
261 		return_ACPI_STATUS(status);
262 	}
263 
264 	if (value != 0) {
265 		ACPI_ERROR((AE_INFO,
266 			    "Could not disable %s events",
267 			    acpi_ut_get_event_name(event)));
268 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
269 	}
270 
271 	return_ACPI_STATUS(status);
272 }
273 
274 ACPI_EXPORT_SYMBOL(acpi_disable_event)
275 
276 /*******************************************************************************
277  *
278  * FUNCTION:    acpi_clear_event
279  *
280  * PARAMETERS:  event           - The fixed event to be cleared
281  *
282  * RETURN:      Status
283  *
284  * DESCRIPTION: Clear an ACPI event (fixed)
285  *
286  ******************************************************************************/
287 acpi_status acpi_clear_event(u32 event)
288 {
289 	acpi_status status = AE_OK;
290 
291 	ACPI_FUNCTION_TRACE(acpi_clear_event);
292 
293 	/* Decode the Fixed Event */
294 
295 	if (event > ACPI_EVENT_MAX) {
296 		return_ACPI_STATUS(AE_BAD_PARAMETER);
297 	}
298 
299 	/*
300 	 * Clear the requested fixed event (By writing a one to the status
301 	 * register bit)
302 	 */
303 	status =
304 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
305 				    status_register_id, ACPI_CLEAR_STATUS);
306 
307 	return_ACPI_STATUS(status);
308 }
309 
310 ACPI_EXPORT_SYMBOL(acpi_clear_event)
311 
312 /*******************************************************************************
313  *
314  * FUNCTION:    acpi_get_event_status
315  *
316  * PARAMETERS:  event           - The fixed event
317  *              event_status    - Where the current status of the event will
318  *                                be returned
319  *
320  * RETURN:      Status
321  *
322  * DESCRIPTION: Obtains and returns the current status of the event
323  *
324  ******************************************************************************/
325 acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
326 {
327 	acpi_status status;
328 	acpi_event_status local_event_status = 0;
329 	u32 in_byte;
330 
331 	ACPI_FUNCTION_TRACE(acpi_get_event_status);
332 
333 	if (!event_status) {
334 		return_ACPI_STATUS(AE_BAD_PARAMETER);
335 	}
336 
337 	/* Decode the Fixed Event */
338 
339 	if (event > ACPI_EVENT_MAX) {
340 		return_ACPI_STATUS(AE_BAD_PARAMETER);
341 	}
342 
343 	/* Fixed event currently can be dispatched? */
344 
345 	if (acpi_gbl_fixed_event_handlers[event].handler) {
346 		local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
347 	}
348 
349 	/* Fixed event currently enabled? */
350 
351 	status =
352 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
353 				   enable_register_id, &in_byte);
354 	if (ACPI_FAILURE(status)) {
355 		return_ACPI_STATUS(status);
356 	}
357 
358 	if (in_byte) {
359 		local_event_status |=
360 		    (ACPI_EVENT_FLAG_ENABLED | ACPI_EVENT_FLAG_ENABLE_SET);
361 	}
362 
363 	/* Fixed event currently active? */
364 
365 	status =
366 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
367 				   status_register_id, &in_byte);
368 	if (ACPI_FAILURE(status)) {
369 		return_ACPI_STATUS(status);
370 	}
371 
372 	if (in_byte) {
373 		local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
374 	}
375 
376 	(*event_status) = local_event_status;
377 	return_ACPI_STATUS(AE_OK);
378 }
379 
380 ACPI_EXPORT_SYMBOL(acpi_get_event_status)
381 #endif				/* !ACPI_REDUCED_HARDWARE */
382