xref: /openbmc/linux/drivers/acpi/acpica/evxfevnt.c (revision 612c2932)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
595b482a8SLen Brown  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown  *
895857638SErik Schmauss  *****************************************************************************/
995b482a8SLen Brown 
10839e928fSLv Zheng #define EXPORT_ACPI_INTERFACES
11839e928fSLv Zheng 
1295b482a8SLen Brown #include <acpi/acpi.h>
13e2f7a777SLen Brown #include "accommon.h"
14e2f7a777SLen Brown #include "actables.h"
1595b482a8SLen Brown 
1695b482a8SLen Brown #define _COMPONENT          ACPI_EVENTS
1795b482a8SLen Brown ACPI_MODULE_NAME("evxfevnt")
1895b482a8SLen Brown 
1933620c54SBob Moore #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
2095b482a8SLen Brown /*******************************************************************************
2195b482a8SLen Brown  *
2295b482a8SLen Brown  * FUNCTION:    acpi_enable
2395b482a8SLen Brown  *
2495b482a8SLen Brown  * PARAMETERS:  None
2595b482a8SLen Brown  *
2695b482a8SLen Brown  * RETURN:      Status
2795b482a8SLen Brown  *
2895b482a8SLen Brown  * DESCRIPTION: Transfers the system into ACPI mode.
2995b482a8SLen Brown  *
3095b482a8SLen Brown  ******************************************************************************/
acpi_enable(void)3195b482a8SLen Brown acpi_status acpi_enable(void)
3295b482a8SLen Brown {
33b430acbdSLen Brown 	acpi_status status;
343d695839SLen Brown 	int retry;
3595b482a8SLen Brown 
3695b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_enable);
3795b482a8SLen Brown 
3895b482a8SLen Brown 	/* ACPI tables must be present */
3995b482a8SLen Brown 
4062fcce91SLv Zheng 	if (acpi_gbl_fadt_index == ACPI_INVALID_TABLE_INDEX) {
4195b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
4295b482a8SLen Brown 	}
4395b482a8SLen Brown 
44c39660b2SBob Moore 	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
45c39660b2SBob Moore 
46c39660b2SBob Moore 	if (acpi_gbl_reduced_hardware) {
47c39660b2SBob Moore 		return_ACPI_STATUS(AE_OK);
48c39660b2SBob Moore 	}
49c39660b2SBob Moore 
5095b482a8SLen Brown 	/* Check current mode */
5195b482a8SLen Brown 
5295b482a8SLen Brown 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
5395b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
5495b482a8SLen Brown 				  "System is already in ACPI mode\n"));
55b430acbdSLen Brown 		return_ACPI_STATUS(AE_OK);
56b430acbdSLen Brown 	}
57b430acbdSLen Brown 
5895b482a8SLen Brown 	/* Transition to ACPI mode */
5995b482a8SLen Brown 
6095b482a8SLen Brown 	status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
6195b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
6295b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
6395b482a8SLen Brown 			    "Could not transition to ACPI mode"));
6495b482a8SLen Brown 		return_ACPI_STATUS(status);
6595b482a8SLen Brown 	}
6695b482a8SLen Brown 
67b430acbdSLen Brown 	/* Sanity check that transition succeeded */
68b430acbdSLen Brown 
693d695839SLen Brown 	for (retry = 0; retry < 30000; ++retry) {
703d695839SLen Brown 		if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
713d695839SLen Brown 			if (retry != 0)
723d695839SLen Brown 				ACPI_WARNING((AE_INFO,
733d695839SLen Brown 				"Platform took > %d00 usec to enter ACPI mode", retry));
743d695839SLen Brown 			return_ACPI_STATUS(AE_OK);
753d695839SLen Brown 		}
763d695839SLen Brown 		acpi_os_stall(100);	/* 100 usec */
7795b482a8SLen Brown 	}
7895b482a8SLen Brown 
793d695839SLen Brown 	ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
803d695839SLen Brown 	return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
8195b482a8SLen Brown }
8295b482a8SLen Brown 
ACPI_EXPORT_SYMBOL(acpi_enable)8395b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_enable)
8495b482a8SLen Brown 
8595b482a8SLen Brown /*******************************************************************************
8695b482a8SLen Brown  *
8795b482a8SLen Brown  * FUNCTION:    acpi_disable
8895b482a8SLen Brown  *
8995b482a8SLen Brown  * PARAMETERS:  None
9095b482a8SLen Brown  *
9195b482a8SLen Brown  * RETURN:      Status
9295b482a8SLen Brown  *
9395b482a8SLen Brown  * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
9495b482a8SLen Brown  *
9595b482a8SLen Brown  ******************************************************************************/
9695b482a8SLen Brown acpi_status acpi_disable(void)
9795b482a8SLen Brown {
9895b482a8SLen Brown 	acpi_status status = AE_OK;
9995b482a8SLen Brown 
10095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_disable);
10195b482a8SLen Brown 
102c39660b2SBob Moore 	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
103c39660b2SBob Moore 
104c39660b2SBob Moore 	if (acpi_gbl_reduced_hardware) {
105c39660b2SBob Moore 		return_ACPI_STATUS(AE_OK);
106c39660b2SBob Moore 	}
107c39660b2SBob Moore 
10895b482a8SLen Brown 	if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
10995b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
11095b482a8SLen Brown 				  "System is already in legacy (non-ACPI) mode\n"));
11195b482a8SLen Brown 	} else {
11295b482a8SLen Brown 		/* Transition to LEGACY mode */
11395b482a8SLen Brown 
11495b482a8SLen Brown 		status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
11595b482a8SLen Brown 
11695b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
11795b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
11895b482a8SLen Brown 				    "Could not exit ACPI mode to legacy mode"));
11995b482a8SLen Brown 			return_ACPI_STATUS(status);
12095b482a8SLen Brown 		}
12195b482a8SLen Brown 
12295b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
12395b482a8SLen Brown 	}
12495b482a8SLen Brown 
12595b482a8SLen Brown 	return_ACPI_STATUS(status);
12695b482a8SLen Brown }
12795b482a8SLen Brown 
ACPI_EXPORT_SYMBOL(acpi_disable)12895b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_disable)
12995b482a8SLen Brown 
13095b482a8SLen Brown /*******************************************************************************
13195b482a8SLen Brown  *
13295b482a8SLen Brown  * FUNCTION:    acpi_enable_event
13395b482a8SLen Brown  *
134ba494beeSBob Moore  * PARAMETERS:  event           - The fixed eventto be enabled
135ba494beeSBob Moore  *              flags           - Reserved
13695b482a8SLen Brown  *
13795b482a8SLen Brown  * RETURN:      Status
13895b482a8SLen Brown  *
13995b482a8SLen Brown  * DESCRIPTION: Enable an ACPI event (fixed)
14095b482a8SLen Brown  *
14195b482a8SLen Brown  ******************************************************************************/
14295b482a8SLen Brown acpi_status acpi_enable_event(u32 event, u32 flags)
14395b482a8SLen Brown {
14495b482a8SLen Brown 	acpi_status status = AE_OK;
14595b482a8SLen Brown 	u32 value;
14695b482a8SLen Brown 
14795b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_enable_event);
14895b482a8SLen Brown 
149861ba635SLv Zheng 	/* If Hardware Reduced flag is set, there are no fixed events */
150861ba635SLv Zheng 
151861ba635SLv Zheng 	if (acpi_gbl_reduced_hardware) {
152861ba635SLv Zheng 		return_ACPI_STATUS(AE_OK);
153861ba635SLv Zheng 	}
154861ba635SLv Zheng 
15595b482a8SLen Brown 	/* Decode the Fixed Event */
15695b482a8SLen Brown 
15795b482a8SLen Brown 	if (event > ACPI_EVENT_MAX) {
15895b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
15995b482a8SLen Brown 	}
16095b482a8SLen Brown 
16195b482a8SLen Brown 	/*
16295b482a8SLen Brown 	 * Enable the requested fixed event (by writing a one to the enable
16395b482a8SLen Brown 	 * register bit)
16495b482a8SLen Brown 	 */
16595b482a8SLen Brown 	status =
16650ffba1bSBob Moore 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
167768aaaf1SBob Moore 				    enable_register_id, ACPI_ENABLE_EVENT);
16895b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
16995b482a8SLen Brown 		return_ACPI_STATUS(status);
17095b482a8SLen Brown 	}
17195b482a8SLen Brown 
17295b482a8SLen Brown 	/* Make sure that the hardware responded */
17395b482a8SLen Brown 
17495b482a8SLen Brown 	status =
17550ffba1bSBob Moore 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
17695b482a8SLen Brown 				   enable_register_id, &value);
17795b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
17895b482a8SLen Brown 		return_ACPI_STATUS(status);
17995b482a8SLen Brown 	}
18095b482a8SLen Brown 
18195b482a8SLen Brown 	if (value != 1) {
18295b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
18395b482a8SLen Brown 			    "Could not enable %s event",
18495b482a8SLen Brown 			    acpi_ut_get_event_name(event)));
18595b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
18695b482a8SLen Brown 	}
18795b482a8SLen Brown 
18895b482a8SLen Brown 	return_ACPI_STATUS(status);
18995b482a8SLen Brown }
19095b482a8SLen Brown 
ACPI_EXPORT_SYMBOL(acpi_enable_event)19195b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_enable_event)
19295b482a8SLen Brown 
19395b482a8SLen Brown /*******************************************************************************
19495b482a8SLen Brown  *
19595b482a8SLen Brown  * FUNCTION:    acpi_disable_event
19695b482a8SLen Brown  *
19775c8044fSLv Zheng  * PARAMETERS:  event           - The fixed event to be disabled
19875c8044fSLv Zheng  *              flags           - Reserved
19995b482a8SLen Brown  *
20095b482a8SLen Brown  * RETURN:      Status
20195b482a8SLen Brown  *
20295b482a8SLen Brown  * DESCRIPTION: Disable an ACPI event (fixed)
20395b482a8SLen Brown  *
20495b482a8SLen Brown  ******************************************************************************/
20595b482a8SLen Brown acpi_status acpi_disable_event(u32 event, u32 flags)
20695b482a8SLen Brown {
20795b482a8SLen Brown 	acpi_status status = AE_OK;
20895b482a8SLen Brown 	u32 value;
20995b482a8SLen Brown 
21095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_disable_event);
21195b482a8SLen Brown 
212861ba635SLv Zheng 	/* If Hardware Reduced flag is set, there are no fixed events */
213861ba635SLv Zheng 
214861ba635SLv Zheng 	if (acpi_gbl_reduced_hardware) {
215861ba635SLv Zheng 		return_ACPI_STATUS(AE_OK);
216861ba635SLv Zheng 	}
217861ba635SLv Zheng 
21895b482a8SLen Brown 	/* Decode the Fixed Event */
21995b482a8SLen Brown 
22095b482a8SLen Brown 	if (event > ACPI_EVENT_MAX) {
22195b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
22295b482a8SLen Brown 	}
22395b482a8SLen Brown 
22495b482a8SLen Brown 	/*
22595b482a8SLen Brown 	 * Disable the requested fixed event (by writing a zero to the enable
22695b482a8SLen Brown 	 * register bit)
22795b482a8SLen Brown 	 */
22895b482a8SLen Brown 	status =
22950ffba1bSBob Moore 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
230768aaaf1SBob Moore 				    enable_register_id, ACPI_DISABLE_EVENT);
23195b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
23295b482a8SLen Brown 		return_ACPI_STATUS(status);
23395b482a8SLen Brown 	}
23495b482a8SLen Brown 
23595b482a8SLen Brown 	status =
23650ffba1bSBob Moore 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
23795b482a8SLen Brown 				   enable_register_id, &value);
23895b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
23995b482a8SLen Brown 		return_ACPI_STATUS(status);
24095b482a8SLen Brown 	}
24195b482a8SLen Brown 
24295b482a8SLen Brown 	if (value != 0) {
24395b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
24495b482a8SLen Brown 			    "Could not disable %s events",
24595b482a8SLen Brown 			    acpi_ut_get_event_name(event)));
24695b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
24795b482a8SLen Brown 	}
24895b482a8SLen Brown 
24995b482a8SLen Brown 	return_ACPI_STATUS(status);
25095b482a8SLen Brown }
25195b482a8SLen Brown 
ACPI_EXPORT_SYMBOL(acpi_disable_event)25295b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_disable_event)
25395b482a8SLen Brown 
25495b482a8SLen Brown /*******************************************************************************
25595b482a8SLen Brown  *
25695b482a8SLen Brown  * FUNCTION:    acpi_clear_event
25795b482a8SLen Brown  *
258ba494beeSBob Moore  * PARAMETERS:  event           - The fixed event to be cleared
25995b482a8SLen Brown  *
26095b482a8SLen Brown  * RETURN:      Status
26195b482a8SLen Brown  *
26295b482a8SLen Brown  * DESCRIPTION: Clear an ACPI event (fixed)
26395b482a8SLen Brown  *
26495b482a8SLen Brown  ******************************************************************************/
26595b482a8SLen Brown acpi_status acpi_clear_event(u32 event)
26695b482a8SLen Brown {
26795b482a8SLen Brown 	acpi_status status = AE_OK;
26895b482a8SLen Brown 
26995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_clear_event);
27095b482a8SLen Brown 
271861ba635SLv Zheng 	/* If Hardware Reduced flag is set, there are no fixed events */
272861ba635SLv Zheng 
273861ba635SLv Zheng 	if (acpi_gbl_reduced_hardware) {
274861ba635SLv Zheng 		return_ACPI_STATUS(AE_OK);
275861ba635SLv Zheng 	}
276861ba635SLv Zheng 
27795b482a8SLen Brown 	/* Decode the Fixed Event */
27895b482a8SLen Brown 
27995b482a8SLen Brown 	if (event > ACPI_EVENT_MAX) {
28095b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
28195b482a8SLen Brown 	}
28295b482a8SLen Brown 
28395b482a8SLen Brown 	/*
28495b482a8SLen Brown 	 * Clear the requested fixed event (By writing a one to the status
28595b482a8SLen Brown 	 * register bit)
28695b482a8SLen Brown 	 */
28795b482a8SLen Brown 	status =
28850ffba1bSBob Moore 	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
289768aaaf1SBob Moore 				    status_register_id, ACPI_CLEAR_STATUS);
29095b482a8SLen Brown 
29195b482a8SLen Brown 	return_ACPI_STATUS(status);
29295b482a8SLen Brown }
29395b482a8SLen Brown 
ACPI_EXPORT_SYMBOL(acpi_clear_event)29495b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_clear_event)
29595b482a8SLen Brown 
29695b482a8SLen Brown /*******************************************************************************
29795b482a8SLen Brown  *
29895b482a8SLen Brown  * FUNCTION:    acpi_get_event_status
29995b482a8SLen Brown  *
300ba494beeSBob Moore  * PARAMETERS:  event           - The fixed event
30195b482a8SLen Brown  *              event_status    - Where the current status of the event will
30295b482a8SLen Brown  *                                be returned
30395b482a8SLen Brown  *
30495b482a8SLen Brown  * RETURN:      Status
30595b482a8SLen Brown  *
30695b482a8SLen Brown  * DESCRIPTION: Obtains and returns the current status of the event
30795b482a8SLen Brown  *
30895b482a8SLen Brown  ******************************************************************************/
30995b482a8SLen Brown acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
31095b482a8SLen Brown {
311a08f813eSLv Zheng 	acpi_status status;
312a08f813eSLv Zheng 	acpi_event_status local_event_status = 0;
313a08f813eSLv Zheng 	u32 in_byte;
31495b482a8SLen Brown 
31595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(acpi_get_event_status);
31695b482a8SLen Brown 
31795b482a8SLen Brown 	if (!event_status) {
31895b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
31995b482a8SLen Brown 	}
32095b482a8SLen Brown 
32195b482a8SLen Brown 	/* Decode the Fixed Event */
32295b482a8SLen Brown 
32395b482a8SLen Brown 	if (event > ACPI_EVENT_MAX) {
32495b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
32595b482a8SLen Brown 	}
32695b482a8SLen Brown 
327a08f813eSLv Zheng 	/* Fixed event currently can be dispatched? */
328a08f813eSLv Zheng 
329a08f813eSLv Zheng 	if (acpi_gbl_fixed_event_handlers[event].handler) {
3302f857234SLv Zheng 		local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
331a08f813eSLv Zheng 	}
332a08f813eSLv Zheng 
333a08f813eSLv Zheng 	/* Fixed event currently enabled? */
33495b482a8SLen Brown 
33595b482a8SLen Brown 	status =
33650ffba1bSBob Moore 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
337a08f813eSLv Zheng 				   enable_register_id, &in_byte);
338a08f813eSLv Zheng 	if (ACPI_FAILURE(status)) {
33995b482a8SLen Brown 		return_ACPI_STATUS(status);
340a08f813eSLv Zheng 	}
34195b482a8SLen Brown 
342a08f813eSLv Zheng 	if (in_byte) {
34309af8e82SLv Zheng 		local_event_status |=
34409af8e82SLv Zheng 		    (ACPI_EVENT_FLAG_ENABLED | ACPI_EVENT_FLAG_ENABLE_SET);
345a08f813eSLv Zheng 	}
346a08f813eSLv Zheng 
347a08f813eSLv Zheng 	/* Fixed event currently active? */
34895b482a8SLen Brown 
34995b482a8SLen Brown 	status =
35050ffba1bSBob Moore 	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
351a08f813eSLv Zheng 				   status_register_id, &in_byte);
352a08f813eSLv Zheng 	if (ACPI_FAILURE(status)) {
35395b482a8SLen Brown 		return_ACPI_STATUS(status);
354a08f813eSLv Zheng 	}
35595b482a8SLen Brown 
356a08f813eSLv Zheng 	if (in_byte) {
35709af8e82SLv Zheng 		local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
358a08f813eSLv Zheng 	}
35995b482a8SLen Brown 
360a08f813eSLv Zheng 	(*event_status) = local_event_status;
361a08f813eSLv Zheng 	return_ACPI_STATUS(AE_OK);
36295b482a8SLen Brown }
36395b482a8SLen Brown 
36495b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_event_status)
36533620c54SBob Moore #endif				/* !ACPI_REDUCED_HARDWARE */
366