162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *****************************************************************************/
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#define EXPORT_ACPI_INTERFACES
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <acpi/acpi.h>
1362306a36Sopenharmony_ci#include "accommon.h"
1462306a36Sopenharmony_ci#include "actables.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define _COMPONENT          ACPI_EVENTS
1762306a36Sopenharmony_ciACPI_MODULE_NAME("evxfevnt")
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
2062306a36Sopenharmony_ci/*******************************************************************************
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * FUNCTION:    acpi_enable
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * PARAMETERS:  None
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * RETURN:      Status
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci * DESCRIPTION: Transfers the system into ACPI mode.
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci ******************************************************************************/
3162306a36Sopenharmony_ciacpi_status acpi_enable(void)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	acpi_status status;
3462306a36Sopenharmony_ci	int retry;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(acpi_enable);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	/* ACPI tables must be present */
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	if (acpi_gbl_fadt_index == ACPI_INVALID_TABLE_INDEX) {
4162306a36Sopenharmony_ci		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
4262306a36Sopenharmony_ci	}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	if (acpi_gbl_reduced_hardware) {
4762306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
4862306a36Sopenharmony_ci	}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	/* Check current mode */
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
5362306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
5462306a36Sopenharmony_ci				  "System is already in ACPI mode\n"));
5562306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	/* Transition to ACPI mode */
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
6162306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
6262306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO,
6362306a36Sopenharmony_ci			    "Could not transition to ACPI mode"));
6462306a36Sopenharmony_ci		return_ACPI_STATUS(status);
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	/* Sanity check that transition succeeded */
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	for (retry = 0; retry < 30000; ++retry) {
7062306a36Sopenharmony_ci		if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
7162306a36Sopenharmony_ci			if (retry != 0)
7262306a36Sopenharmony_ci				ACPI_WARNING((AE_INFO,
7362306a36Sopenharmony_ci				"Platform took > %d00 usec to enter ACPI mode", retry));
7462306a36Sopenharmony_ci			return_ACPI_STATUS(AE_OK);
7562306a36Sopenharmony_ci		}
7662306a36Sopenharmony_ci		acpi_os_stall(100);	/* 100 usec */
7762306a36Sopenharmony_ci	}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
8062306a36Sopenharmony_ci	return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_enable)
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci/*******************************************************************************
8662306a36Sopenharmony_ci *
8762306a36Sopenharmony_ci * FUNCTION:    acpi_disable
8862306a36Sopenharmony_ci *
8962306a36Sopenharmony_ci * PARAMETERS:  None
9062306a36Sopenharmony_ci *
9162306a36Sopenharmony_ci * RETURN:      Status
9262306a36Sopenharmony_ci *
9362306a36Sopenharmony_ci * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
9462306a36Sopenharmony_ci *
9562306a36Sopenharmony_ci ******************************************************************************/
9662306a36Sopenharmony_ciacpi_status acpi_disable(void)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	acpi_status status = AE_OK;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(acpi_disable);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	/* If the Hardware Reduced flag is set, machine is always in acpi mode */
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	if (acpi_gbl_reduced_hardware) {
10562306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
10662306a36Sopenharmony_ci	}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
10962306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
11062306a36Sopenharmony_ci				  "System is already in legacy (non-ACPI) mode\n"));
11162306a36Sopenharmony_ci	} else {
11262306a36Sopenharmony_ci		/* Transition to LEGACY mode */
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci		status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci		if (ACPI_FAILURE(status)) {
11762306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO,
11862306a36Sopenharmony_ci				    "Could not exit ACPI mode to legacy mode"));
11962306a36Sopenharmony_ci			return_ACPI_STATUS(status);
12062306a36Sopenharmony_ci		}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
12362306a36Sopenharmony_ci	}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	return_ACPI_STATUS(status);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_disable)
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/*******************************************************************************
13162306a36Sopenharmony_ci *
13262306a36Sopenharmony_ci * FUNCTION:    acpi_enable_event
13362306a36Sopenharmony_ci *
13462306a36Sopenharmony_ci * PARAMETERS:  event           - The fixed eventto be enabled
13562306a36Sopenharmony_ci *              flags           - Reserved
13662306a36Sopenharmony_ci *
13762306a36Sopenharmony_ci * RETURN:      Status
13862306a36Sopenharmony_ci *
13962306a36Sopenharmony_ci * DESCRIPTION: Enable an ACPI event (fixed)
14062306a36Sopenharmony_ci *
14162306a36Sopenharmony_ci ******************************************************************************/
14262306a36Sopenharmony_ciacpi_status acpi_enable_event(u32 event, u32 flags)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	acpi_status status = AE_OK;
14562306a36Sopenharmony_ci	u32 value;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(acpi_enable_event);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	/* If Hardware Reduced flag is set, there are no fixed events */
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	if (acpi_gbl_reduced_hardware) {
15262306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
15362306a36Sopenharmony_ci	}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	/* Decode the Fixed Event */
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	if (event > ACPI_EVENT_MAX) {
15862306a36Sopenharmony_ci		return_ACPI_STATUS(AE_BAD_PARAMETER);
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	/*
16262306a36Sopenharmony_ci	 * Enable the requested fixed event (by writing a one to the enable
16362306a36Sopenharmony_ci	 * register bit)
16462306a36Sopenharmony_ci	 */
16562306a36Sopenharmony_ci	status =
16662306a36Sopenharmony_ci	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
16762306a36Sopenharmony_ci				    enable_register_id, ACPI_ENABLE_EVENT);
16862306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
16962306a36Sopenharmony_ci		return_ACPI_STATUS(status);
17062306a36Sopenharmony_ci	}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	/* Make sure that the hardware responded */
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	status =
17562306a36Sopenharmony_ci	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
17662306a36Sopenharmony_ci				   enable_register_id, &value);
17762306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
17862306a36Sopenharmony_ci		return_ACPI_STATUS(status);
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	if (value != 1) {
18262306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO,
18362306a36Sopenharmony_ci			    "Could not enable %s event",
18462306a36Sopenharmony_ci			    acpi_ut_get_event_name(event)));
18562306a36Sopenharmony_ci		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
18662306a36Sopenharmony_ci	}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	return_ACPI_STATUS(status);
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_enable_event)
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci/*******************************************************************************
19462306a36Sopenharmony_ci *
19562306a36Sopenharmony_ci * FUNCTION:    acpi_disable_event
19662306a36Sopenharmony_ci *
19762306a36Sopenharmony_ci * PARAMETERS:  event           - The fixed event to be disabled
19862306a36Sopenharmony_ci *              flags           - Reserved
19962306a36Sopenharmony_ci *
20062306a36Sopenharmony_ci * RETURN:      Status
20162306a36Sopenharmony_ci *
20262306a36Sopenharmony_ci * DESCRIPTION: Disable an ACPI event (fixed)
20362306a36Sopenharmony_ci *
20462306a36Sopenharmony_ci ******************************************************************************/
20562306a36Sopenharmony_ciacpi_status acpi_disable_event(u32 event, u32 flags)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	acpi_status status = AE_OK;
20862306a36Sopenharmony_ci	u32 value;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(acpi_disable_event);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	/* If Hardware Reduced flag is set, there are no fixed events */
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	if (acpi_gbl_reduced_hardware) {
21562306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	/* Decode the Fixed Event */
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	if (event > ACPI_EVENT_MAX) {
22162306a36Sopenharmony_ci		return_ACPI_STATUS(AE_BAD_PARAMETER);
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	/*
22562306a36Sopenharmony_ci	 * Disable the requested fixed event (by writing a zero to the enable
22662306a36Sopenharmony_ci	 * register bit)
22762306a36Sopenharmony_ci	 */
22862306a36Sopenharmony_ci	status =
22962306a36Sopenharmony_ci	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
23062306a36Sopenharmony_ci				    enable_register_id, ACPI_DISABLE_EVENT);
23162306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
23262306a36Sopenharmony_ci		return_ACPI_STATUS(status);
23362306a36Sopenharmony_ci	}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	status =
23662306a36Sopenharmony_ci	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
23762306a36Sopenharmony_ci				   enable_register_id, &value);
23862306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
23962306a36Sopenharmony_ci		return_ACPI_STATUS(status);
24062306a36Sopenharmony_ci	}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	if (value != 0) {
24362306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO,
24462306a36Sopenharmony_ci			    "Could not disable %s events",
24562306a36Sopenharmony_ci			    acpi_ut_get_event_name(event)));
24662306a36Sopenharmony_ci		return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	return_ACPI_STATUS(status);
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_disable_event)
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci/*******************************************************************************
25562306a36Sopenharmony_ci *
25662306a36Sopenharmony_ci * FUNCTION:    acpi_clear_event
25762306a36Sopenharmony_ci *
25862306a36Sopenharmony_ci * PARAMETERS:  event           - The fixed event to be cleared
25962306a36Sopenharmony_ci *
26062306a36Sopenharmony_ci * RETURN:      Status
26162306a36Sopenharmony_ci *
26262306a36Sopenharmony_ci * DESCRIPTION: Clear an ACPI event (fixed)
26362306a36Sopenharmony_ci *
26462306a36Sopenharmony_ci ******************************************************************************/
26562306a36Sopenharmony_ciacpi_status acpi_clear_event(u32 event)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	acpi_status status = AE_OK;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(acpi_clear_event);
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	/* If Hardware Reduced flag is set, there are no fixed events */
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	if (acpi_gbl_reduced_hardware) {
27462306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
27562306a36Sopenharmony_ci	}
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	/* Decode the Fixed Event */
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	if (event > ACPI_EVENT_MAX) {
28062306a36Sopenharmony_ci		return_ACPI_STATUS(AE_BAD_PARAMETER);
28162306a36Sopenharmony_ci	}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	/*
28462306a36Sopenharmony_ci	 * Clear the requested fixed event (By writing a one to the status
28562306a36Sopenharmony_ci	 * register bit)
28662306a36Sopenharmony_ci	 */
28762306a36Sopenharmony_ci	status =
28862306a36Sopenharmony_ci	    acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
28962306a36Sopenharmony_ci				    status_register_id, ACPI_CLEAR_STATUS);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	return_ACPI_STATUS(status);
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_clear_event)
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci/*******************************************************************************
29762306a36Sopenharmony_ci *
29862306a36Sopenharmony_ci * FUNCTION:    acpi_get_event_status
29962306a36Sopenharmony_ci *
30062306a36Sopenharmony_ci * PARAMETERS:  event           - The fixed event
30162306a36Sopenharmony_ci *              event_status    - Where the current status of the event will
30262306a36Sopenharmony_ci *                                be returned
30362306a36Sopenharmony_ci *
30462306a36Sopenharmony_ci * RETURN:      Status
30562306a36Sopenharmony_ci *
30662306a36Sopenharmony_ci * DESCRIPTION: Obtains and returns the current status of the event
30762306a36Sopenharmony_ci *
30862306a36Sopenharmony_ci ******************************************************************************/
30962306a36Sopenharmony_ciacpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
31062306a36Sopenharmony_ci{
31162306a36Sopenharmony_ci	acpi_status status;
31262306a36Sopenharmony_ci	acpi_event_status local_event_status = 0;
31362306a36Sopenharmony_ci	u32 in_byte;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(acpi_get_event_status);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	if (!event_status) {
31862306a36Sopenharmony_ci		return_ACPI_STATUS(AE_BAD_PARAMETER);
31962306a36Sopenharmony_ci	}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	/* Decode the Fixed Event */
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	if (event > ACPI_EVENT_MAX) {
32462306a36Sopenharmony_ci		return_ACPI_STATUS(AE_BAD_PARAMETER);
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/* Fixed event currently can be dispatched? */
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	if (acpi_gbl_fixed_event_handlers[event].handler) {
33062306a36Sopenharmony_ci		local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
33162306a36Sopenharmony_ci	}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/* Fixed event currently enabled? */
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	status =
33662306a36Sopenharmony_ci	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
33762306a36Sopenharmony_ci				   enable_register_id, &in_byte);
33862306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
33962306a36Sopenharmony_ci		return_ACPI_STATUS(status);
34062306a36Sopenharmony_ci	}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	if (in_byte) {
34362306a36Sopenharmony_ci		local_event_status |=
34462306a36Sopenharmony_ci		    (ACPI_EVENT_FLAG_ENABLED | ACPI_EVENT_FLAG_ENABLE_SET);
34562306a36Sopenharmony_ci	}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	/* Fixed event currently active? */
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	status =
35062306a36Sopenharmony_ci	    acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
35162306a36Sopenharmony_ci				   status_register_id, &in_byte);
35262306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
35362306a36Sopenharmony_ci		return_ACPI_STATUS(status);
35462306a36Sopenharmony_ci	}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	if (in_byte) {
35762306a36Sopenharmony_ci		local_event_status |= ACPI_EVENT_FLAG_STATUS_SET;
35862306a36Sopenharmony_ci	}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	(*event_status) = local_event_status;
36162306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
36262306a36Sopenharmony_ci}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_get_event_status)
36562306a36Sopenharmony_ci#endif				/* !ACPI_REDUCED_HARDWARE */
366