1/******************************************************************************
2 *
3 * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, 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
51ACPI_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 ******************************************************************************/
65acpi_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_tb_tables_loaded()) {
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
117ACPI_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 ******************************************************************************/
130acpi_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
162ACPI_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 ******************************************************************************/
176acpi_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
219ACPI_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 ******************************************************************************/
233acpi_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
274ACPI_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 ******************************************************************************/
287acpi_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
310ACPI_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 ******************************************************************************/
325acpi_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
380ACPI_EXPORT_SYMBOL(acpi_get_event_status)
381#endif				/* !ACPI_REDUCED_HARDWARE */
382