xref: /openbmc/linux/drivers/acpi/acpica/evxfevnt.c (revision c39660b2)
195b482a8SLen Brown /******************************************************************************
295b482a8SLen Brown  *
395b482a8SLen Brown  * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
495b482a8SLen Brown  *
595b482a8SLen Brown  *****************************************************************************/
695b482a8SLen Brown 
795b482a8SLen Brown /*
825f044e6SBob Moore  * Copyright (C) 2000 - 2013, Intel Corp.
995b482a8SLen Brown  * All rights reserved.
1095b482a8SLen Brown  *
1195b482a8SLen Brown  * Redistribution and use in source and binary forms, with or without
1295b482a8SLen Brown  * modification, are permitted provided that the following conditions
1395b482a8SLen Brown  * are met:
1495b482a8SLen Brown  * 1. Redistributions of source code must retain the above copyright
1595b482a8SLen Brown  *    notice, this list of conditions, and the following disclaimer,
1695b482a8SLen Brown  *    without modification.
1795b482a8SLen Brown  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1895b482a8SLen Brown  *    substantially similar to the "NO WARRANTY" disclaimer below
1995b482a8SLen Brown  *    ("Disclaimer") and any redistribution must be conditioned upon
2095b482a8SLen Brown  *    including a substantially similar Disclaimer requirement for further
2195b482a8SLen Brown  *    binary redistribution.
2295b482a8SLen Brown  * 3. Neither the names of the above-listed copyright holders nor the names
2395b482a8SLen Brown  *    of any contributors may be used to endorse or promote products derived
2495b482a8SLen Brown  *    from this software without specific prior written permission.
2595b482a8SLen Brown  *
2695b482a8SLen Brown  * Alternatively, this software may be distributed under the terms of the
2795b482a8SLen Brown  * GNU General Public License ("GPL") version 2 as published by the Free
2895b482a8SLen Brown  * Software Foundation.
2995b482a8SLen Brown  *
3095b482a8SLen Brown  * NO WARRANTY
3195b482a8SLen Brown  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3295b482a8SLen Brown  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3395b482a8SLen Brown  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3495b482a8SLen Brown  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3595b482a8SLen Brown  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3695b482a8SLen Brown  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3795b482a8SLen Brown  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3895b482a8SLen Brown  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3995b482a8SLen Brown  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4095b482a8SLen Brown  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4195b482a8SLen Brown  * POSSIBILITY OF SUCH DAMAGES.
4295b482a8SLen Brown  */
4395b482a8SLen Brown 
44214f2c90SPaul Gortmaker #include <linux/export.h>
4595b482a8SLen Brown #include <acpi/acpi.h>
46e2f7a777SLen Brown #include "accommon.h"
47e2f7a777SLen Brown #include "actables.h"
4895b482a8SLen Brown 
4995b482a8SLen Brown #define _COMPONENT          ACPI_EVENTS
5095b482a8SLen Brown ACPI_MODULE_NAME("evxfevnt")
5195b482a8SLen Brown 
5233620c54SBob Moore #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
5395b482a8SLen Brown /*******************************************************************************
5495b482a8SLen Brown  *
5595b482a8SLen Brown  * FUNCTION:    acpi_enable
5695b482a8SLen Brown  *
5795b482a8SLen Brown  * PARAMETERS:  None
5895b482a8SLen Brown  *
5995b482a8SLen Brown  * RETURN:      Status
6095b482a8SLen Brown  *
6195b482a8SLen Brown  * DESCRIPTION: Transfers the system into ACPI mode.
6295b482a8SLen Brown  *
6395b482a8SLen Brown  ******************************************************************************/
6495b482a8SLen Brown acpi_status acpi_enable(void)
6595b482a8SLen Brown {
66b430acbdSLen Brown 	acpi_status status;
673d695839SLen Brown 	int retry;
6895b482a8SLen Brown 
6995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_enable);
7095b482a8SLen Brown 
7195b482a8SLen Brown 	/* ACPI tables must be present */
7295b482a8SLen Brown 
7395b482a8SLen Brown 	if (!acpi_tb_tables_loaded()) {
7495b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
7595b482a8SLen Brown 	}
7695b482a8SLen Brown 
77c39660b2SBob Moore 	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
78c39660b2SBob Moore 
79c39660b2SBob Moore 	if (acpi_gbl_reduced_hardware) {
80c39660b2SBob Moore 		return_ACPI_STATUS(AE_OK);
81c39660b2SBob Moore 	}
82c39660b2SBob Moore 
8395b482a8SLen Brown 	/* Check current mode */
8495b482a8SLen Brown 
8595b482a8SLen Brown 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
8695b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
8795b482a8SLen Brown 				  "System is already in ACPI mode\n"));
88b430acbdSLen Brown 		return_ACPI_STATUS(AE_OK);
89b430acbdSLen Brown 	}
90b430acbdSLen Brown 
9195b482a8SLen Brown 	/* Transition to ACPI mode */
9295b482a8SLen Brown 
9395b482a8SLen Brown 	status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
9495b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
9595b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
9695b482a8SLen Brown 			    "Could not transition to ACPI mode"));
9795b482a8SLen Brown 		return_ACPI_STATUS(status);
9895b482a8SLen Brown 	}
9995b482a8SLen Brown 
100b430acbdSLen Brown 	/* Sanity check that transition succeeded */
101b430acbdSLen Brown 
1023d695839SLen Brown 	for (retry = 0; retry < 30000; ++retry) {
1033d695839SLen Brown 		if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
1043d695839SLen Brown 			if (retry != 0)
1053d695839SLen Brown 				ACPI_WARNING((AE_INFO,
1063d695839SLen Brown 				"Platform took > %d00 usec to enter ACPI mode", retry));
1073d695839SLen Brown 			return_ACPI_STATUS(AE_OK);
1083d695839SLen Brown 		}
1093d695839SLen Brown 		acpi_os_stall(100);	/* 100 usec */
11095b482a8SLen Brown 	}
11195b482a8SLen Brown 
1123d695839SLen Brown 	ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
1133d695839SLen Brown 	return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
11495b482a8SLen Brown }
11595b482a8SLen Brown 
11695b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_enable)
11795b482a8SLen Brown 
11895b482a8SLen Brown /*******************************************************************************
11995b482a8SLen Brown  *
12095b482a8SLen Brown  * FUNCTION:    acpi_disable
12195b482a8SLen Brown  *
12295b482a8SLen Brown  * PARAMETERS:  None
12395b482a8SLen Brown  *
12495b482a8SLen Brown  * RETURN:      Status
12595b482a8SLen Brown  *
12695b482a8SLen Brown  * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
12795b482a8SLen Brown  *
12895b482a8SLen Brown  ******************************************************************************/
12995b482a8SLen Brown acpi_status acpi_disable(void)
13095b482a8SLen Brown {
13195b482a8SLen Brown 	acpi_status status = AE_OK;
13295b482a8SLen Brown 
13395b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_disable);
13495b482a8SLen Brown 
135c39660b2SBob Moore 	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
136c39660b2SBob Moore 
137c39660b2SBob Moore 	if (acpi_gbl_reduced_hardware) {
138c39660b2SBob Moore 		return_ACPI_STATUS(AE_OK);
139c39660b2SBob Moore 	}
140c39660b2SBob Moore 
14195b482a8SLen Brown 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
14295b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
14395b482a8SLen Brown 				  "System is already in legacy (non-ACPI) mode\n"));
14495b482a8SLen Brown 	} else {
14595b482a8SLen Brown 		/* Transition to LEGACY mode */
14695b482a8SLen Brown 
14795b482a8SLen Brown 		status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
14895b482a8SLen Brown 
14995b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
15095b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
15195b482a8SLen Brown 				    "Could not exit ACPI mode to legacy mode"));
15295b482a8SLen Brown 			return_ACPI_STATUS(status);
15395b482a8SLen Brown 		}
15495b482a8SLen Brown 
15595b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
15695b482a8SLen Brown 	}
15795b482a8SLen Brown 
15895b482a8SLen Brown 	return_ACPI_STATUS(status);
15995b482a8SLen Brown }
16095b482a8SLen Brown 
16195b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_disable)
16295b482a8SLen Brown 
16395b482a8SLen Brown /*******************************************************************************
16495b482a8SLen Brown  *
16595b482a8SLen Brown  * FUNCTION:    acpi_enable_event
16695b482a8SLen Brown  *
167ba494beeSBob Moore  * PARAMETERS:  event           - The fixed eventto be enabled
168ba494beeSBob Moore  *              flags           - Reserved
16995b482a8SLen Brown  *
17095b482a8SLen Brown  * RETURN:      Status
17195b482a8SLen Brown  *
17295b482a8SLen Brown  * DESCRIPTION: Enable an ACPI event (fixed)
17395b482a8SLen Brown  *
17495b482a8SLen Brown  ******************************************************************************/
17595b482a8SLen Brown acpi_status acpi_enable_event(u32 event, u32 flags)
17695b482a8SLen Brown {
17795b482a8SLen Brown 	acpi_status status = AE_OK;
17895b482a8SLen Brown 	u32 value;
17995b482a8SLen Brown 
18095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_enable_event);
18195b482a8SLen Brown 
18295b482a8SLen Brown 	/* Decode the Fixed Event */
18395b482a8SLen Brown 
18495b482a8SLen Brown 	if (event > ACPI_EVENT_MAX) {
18595b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
18695b482a8SLen Brown 	}
18795b482a8SLen Brown 
18895b482a8SLen Brown 	/*
18995b482a8SLen Brown 	 * Enable the requested fixed event (by writing a one to the enable
19095b482a8SLen Brown 	 * register bit)
19195b482a8SLen Brown 	 */
19295b482a8SLen Brown 	status =
19350ffba1bSBob Moore 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
194768aaaf1SBob Moore 				    enable_register_id, ACPI_ENABLE_EVENT);
19595b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
19695b482a8SLen Brown 		return_ACPI_STATUS(status);
19795b482a8SLen Brown 	}
19895b482a8SLen Brown 
19995b482a8SLen Brown 	/* Make sure that the hardware responded */
20095b482a8SLen Brown 
20195b482a8SLen Brown 	status =
20250ffba1bSBob Moore 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
20395b482a8SLen Brown 				   enable_register_id, &value);
20495b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
20595b482a8SLen Brown 		return_ACPI_STATUS(status);
20695b482a8SLen Brown 	}
20795b482a8SLen Brown 
20895b482a8SLen Brown 	if (value != 1) {
20995b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
21095b482a8SLen Brown 			    "Could not enable %s event",
21195b482a8SLen Brown 			    acpi_ut_get_event_name(event)));
21295b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
21395b482a8SLen Brown 	}
21495b482a8SLen Brown 
21595b482a8SLen Brown 	return_ACPI_STATUS(status);
21695b482a8SLen Brown }
21795b482a8SLen Brown 
21895b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_enable_event)
21995b482a8SLen Brown 
22095b482a8SLen Brown /*******************************************************************************
22195b482a8SLen Brown  *
22295b482a8SLen Brown  * FUNCTION:    acpi_disable_event
22395b482a8SLen Brown  *
22475c8044fSLv Zheng  * PARAMETERS:  event           - The fixed event to be disabled
22575c8044fSLv Zheng  *              flags           - Reserved
22695b482a8SLen Brown  *
22795b482a8SLen Brown  * RETURN:      Status
22895b482a8SLen Brown  *
22995b482a8SLen Brown  * DESCRIPTION: Disable an ACPI event (fixed)
23095b482a8SLen Brown  *
23195b482a8SLen Brown  ******************************************************************************/
23295b482a8SLen Brown acpi_status acpi_disable_event(u32 event, u32 flags)
23395b482a8SLen Brown {
23495b482a8SLen Brown 	acpi_status status = AE_OK;
23595b482a8SLen Brown 	u32 value;
23695b482a8SLen Brown 
23795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_disable_event);
23895b482a8SLen Brown 
23995b482a8SLen Brown 	/* Decode the Fixed Event */
24095b482a8SLen Brown 
24195b482a8SLen Brown 	if (event > ACPI_EVENT_MAX) {
24295b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
24395b482a8SLen Brown 	}
24495b482a8SLen Brown 
24595b482a8SLen Brown 	/*
24695b482a8SLen Brown 	 * Disable the requested fixed event (by writing a zero to the enable
24795b482a8SLen Brown 	 * register bit)
24895b482a8SLen Brown 	 */
24995b482a8SLen Brown 	status =
25050ffba1bSBob Moore 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
251768aaaf1SBob Moore 				    enable_register_id, ACPI_DISABLE_EVENT);
25295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
25395b482a8SLen Brown 		return_ACPI_STATUS(status);
25495b482a8SLen Brown 	}
25595b482a8SLen Brown 
25695b482a8SLen Brown 	status =
25750ffba1bSBob Moore 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
25895b482a8SLen Brown 				   enable_register_id, &value);
25995b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
26095b482a8SLen Brown 		return_ACPI_STATUS(status);
26195b482a8SLen Brown 	}
26295b482a8SLen Brown 
26395b482a8SLen Brown 	if (value != 0) {
26495b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
26595b482a8SLen Brown 			    "Could not disable %s events",
26695b482a8SLen Brown 			    acpi_ut_get_event_name(event)));
26795b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
26895b482a8SLen Brown 	}
26995b482a8SLen Brown 
27095b482a8SLen Brown 	return_ACPI_STATUS(status);
27195b482a8SLen Brown }
27295b482a8SLen Brown 
27395b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_disable_event)
27495b482a8SLen Brown 
27595b482a8SLen Brown /*******************************************************************************
27695b482a8SLen Brown  *
27795b482a8SLen Brown  * FUNCTION:    acpi_clear_event
27895b482a8SLen Brown  *
279ba494beeSBob Moore  * PARAMETERS:  event           - The fixed event to be cleared
28095b482a8SLen Brown  *
28195b482a8SLen Brown  * RETURN:      Status
28295b482a8SLen Brown  *
28395b482a8SLen Brown  * DESCRIPTION: Clear an ACPI event (fixed)
28495b482a8SLen Brown  *
28595b482a8SLen Brown  ******************************************************************************/
28695b482a8SLen Brown acpi_status acpi_clear_event(u32 event)
28795b482a8SLen Brown {
28895b482a8SLen Brown 	acpi_status status = AE_OK;
28995b482a8SLen Brown 
29095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_clear_event);
29195b482a8SLen Brown 
29295b482a8SLen Brown 	/* Decode the Fixed Event */
29395b482a8SLen Brown 
29495b482a8SLen Brown 	if (event > ACPI_EVENT_MAX) {
29595b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
29695b482a8SLen Brown 	}
29795b482a8SLen Brown 
29895b482a8SLen Brown 	/*
29995b482a8SLen Brown 	 * Clear the requested fixed event (By writing a one to the status
30095b482a8SLen Brown 	 * register bit)
30195b482a8SLen Brown 	 */
30295b482a8SLen Brown 	status =
30350ffba1bSBob Moore 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
304768aaaf1SBob Moore 				    status_register_id, ACPI_CLEAR_STATUS);
30595b482a8SLen Brown 
30695b482a8SLen Brown 	return_ACPI_STATUS(status);
30795b482a8SLen Brown }
30895b482a8SLen Brown 
30995b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_clear_event)
31095b482a8SLen Brown 
31195b482a8SLen Brown /*******************************************************************************
31295b482a8SLen Brown  *
31395b482a8SLen Brown  * FUNCTION:    acpi_get_event_status
31495b482a8SLen Brown  *
315ba494beeSBob Moore  * PARAMETERS:  event           - The fixed event
31695b482a8SLen Brown  *              event_status    - Where the current status of the event will
31795b482a8SLen Brown  *                                be returned
31895b482a8SLen Brown  *
31995b482a8SLen Brown  * RETURN:      Status
32095b482a8SLen Brown  *
32195b482a8SLen Brown  * DESCRIPTION: Obtains and returns the current status of the event
32295b482a8SLen Brown  *
32395b482a8SLen Brown  ******************************************************************************/
32495b482a8SLen Brown acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
32595b482a8SLen Brown {
32695b482a8SLen Brown 	acpi_status status = AE_OK;
32795b482a8SLen Brown 	u32 value;
32895b482a8SLen Brown 
32995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_event_status);
33095b482a8SLen Brown 
33195b482a8SLen Brown 	if (!event_status) {
33295b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
33395b482a8SLen Brown 	}
33495b482a8SLen Brown 
33595b482a8SLen Brown 	/* Decode the Fixed Event */
33695b482a8SLen Brown 
33795b482a8SLen Brown 	if (event > ACPI_EVENT_MAX) {
33895b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
33995b482a8SLen Brown 	}
34095b482a8SLen Brown 
34195b482a8SLen Brown 	/* Get the status of the requested fixed event */
34295b482a8SLen Brown 
34395b482a8SLen Brown 	status =
34450ffba1bSBob Moore 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
34595b482a8SLen Brown 			      enable_register_id, &value);
34695b482a8SLen Brown 	if (ACPI_FAILURE(status))
34795b482a8SLen Brown 		return_ACPI_STATUS(status);
34895b482a8SLen Brown 
34995b482a8SLen Brown 	*event_status = value;
35095b482a8SLen Brown 
35195b482a8SLen Brown 	status =
35250ffba1bSBob Moore 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
35395b482a8SLen Brown 			      status_register_id, &value);
35495b482a8SLen Brown 	if (ACPI_FAILURE(status))
35595b482a8SLen Brown 		return_ACPI_STATUS(status);
35695b482a8SLen Brown 
35795b482a8SLen Brown 	if (value)
35895b482a8SLen Brown 		*event_status |= ACPI_EVENT_FLAG_SET;
35995b482a8SLen Brown 
36095b482a8SLen Brown 	if (acpi_gbl_fixed_event_handlers[event].handler)
36195b482a8SLen Brown 		*event_status |= ACPI_EVENT_FLAG_HANDLE;
36295b482a8SLen Brown 
36395b482a8SLen Brown 	return_ACPI_STATUS(status);
36495b482a8SLen Brown }
36595b482a8SLen Brown 
36695b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_event_status)
36733620c54SBob Moore #endif				/* !ACPI_REDUCED_HARDWARE */
368