xref: /openbmc/linux/drivers/acpi/acpica/hwesleep.c (revision 612c2932)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
270958576SBob Moore /******************************************************************************
370958576SBob Moore  *
470958576SBob Moore  * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the
570958576SBob Moore  *                    extended FADT-V5 sleep registers.
670958576SBob Moore  *
7*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
870958576SBob Moore  *
995857638SErik Schmauss  *****************************************************************************/
1070958576SBob Moore 
1170958576SBob Moore #include <acpi/acpi.h>
1270958576SBob Moore #include "accommon.h"
1370958576SBob Moore 
1470958576SBob Moore #define _COMPONENT          ACPI_HARDWARE
1570958576SBob Moore ACPI_MODULE_NAME("hwesleep")
1670958576SBob Moore 
1770958576SBob Moore /*******************************************************************************
1870958576SBob Moore  *
1970958576SBob Moore  * FUNCTION:    acpi_hw_execute_sleep_method
2070958576SBob Moore  *
214efeeecdSBob Moore  * PARAMETERS:  method_pathname     - Pathname of method to execute
2270958576SBob Moore  *              integer_argument    - Argument to pass to the method
2370958576SBob Moore  *
2470958576SBob Moore  * RETURN:      None
2570958576SBob Moore  *
2670958576SBob Moore  * DESCRIPTION: Execute a sleep/wake related method with one integer argument
2770958576SBob Moore  *              and no return value.
2870958576SBob Moore  *
2970958576SBob Moore  ******************************************************************************/
acpi_hw_execute_sleep_method(char * method_pathname,u32 integer_argument)304efeeecdSBob Moore void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument)
3170958576SBob Moore {
3270958576SBob Moore 	struct acpi_object_list arg_list;
3370958576SBob Moore 	union acpi_object arg;
3470958576SBob Moore 	acpi_status status;
3570958576SBob Moore 
3670958576SBob Moore 	ACPI_FUNCTION_TRACE(hw_execute_sleep_method);
3770958576SBob Moore 
3870958576SBob Moore 	/* One argument, integer_argument; No return value expected */
3970958576SBob Moore 
4070958576SBob Moore 	arg_list.count = 1;
4170958576SBob Moore 	arg_list.pointer = &arg;
4270958576SBob Moore 	arg.type = ACPI_TYPE_INTEGER;
4370958576SBob Moore 	arg.integer.value = (u64)integer_argument;
4470958576SBob Moore 
454efeeecdSBob Moore 	status = acpi_evaluate_object(NULL, method_pathname, &arg_list, NULL);
4670958576SBob Moore 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
4770958576SBob Moore 		ACPI_EXCEPTION((AE_INFO, status, "While executing method %s",
484efeeecdSBob Moore 				method_pathname));
4970958576SBob Moore 	}
5070958576SBob Moore 
5170958576SBob Moore 	return_VOID;
5270958576SBob Moore }
5370958576SBob Moore 
5470958576SBob Moore /*******************************************************************************
5570958576SBob Moore  *
5670958576SBob Moore  * FUNCTION:    acpi_hw_extended_sleep
5770958576SBob Moore  *
5870958576SBob Moore  * PARAMETERS:  sleep_state         - Which sleep state to enter
5970958576SBob Moore  *
6070958576SBob Moore  * RETURN:      Status
6170958576SBob Moore  *
6270958576SBob Moore  * DESCRIPTION: Enter a system sleep state via the extended FADT sleep
6370958576SBob Moore  *              registers (V5 FADT).
6470958576SBob Moore  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
6570958576SBob Moore  *
6670958576SBob Moore  ******************************************************************************/
6770958576SBob Moore 
acpi_hw_extended_sleep(u8 sleep_state)683f6f49c7SLen Brown acpi_status acpi_hw_extended_sleep(u8 sleep_state)
6970958576SBob Moore {
7070958576SBob Moore 	acpi_status status;
710fc5e8f4SLv Zheng 	u8 sleep_control;
7270958576SBob Moore 	u64 sleep_status;
7370958576SBob Moore 
7470958576SBob Moore 	ACPI_FUNCTION_TRACE(hw_extended_sleep);
7570958576SBob Moore 
7670958576SBob Moore 	/* Extended sleep registers must be valid */
7770958576SBob Moore 
7870958576SBob Moore 	if (!acpi_gbl_FADT.sleep_control.address ||
7970958576SBob Moore 	    !acpi_gbl_FADT.sleep_status.address) {
8070958576SBob Moore 		return_ACPI_STATUS(AE_NOT_EXIST);
8170958576SBob Moore 	}
8270958576SBob Moore 
8370958576SBob Moore 	/* Clear wake status (WAK_STS) */
8470958576SBob Moore 
851fad8738SBob Moore 	status = acpi_write((u64)ACPI_X_WAKE_STATUS,
861fad8738SBob Moore 			    &acpi_gbl_FADT.sleep_status);
8770958576SBob Moore 	if (ACPI_FAILURE(status)) {
8870958576SBob Moore 		return_ACPI_STATUS(status);
8970958576SBob Moore 	}
9070958576SBob Moore 
9170958576SBob Moore 	acpi_gbl_system_awake_and_running = FALSE;
9270958576SBob Moore 
9370958576SBob Moore 	/*
9470958576SBob Moore 	 * Set the SLP_TYP and SLP_EN bits.
9570958576SBob Moore 	 *
9670958576SBob Moore 	 * Note: We only use the first value returned by the \_Sx method
9770958576SBob Moore 	 * (acpi_gbl_sleep_type_a) - As per ACPI specification.
9870958576SBob Moore 	 */
9970958576SBob Moore 	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
10070958576SBob Moore 			  "Entering sleep state [S%u]\n", sleep_state));
10170958576SBob Moore 
1020fc5e8f4SLv Zheng 	sleep_control = ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
1030fc5e8f4SLv Zheng 			 ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE;
10470958576SBob Moore 
1050fc5e8f4SLv Zheng 	/* Flush caches, as per ACPI specification */
1060fc5e8f4SLv Zheng 
1071d4e0b3aSKirill A. Shutemov 	if (sleep_state < ACPI_STATE_S4) {
1080fc5e8f4SLv Zheng 		ACPI_FLUSH_CPU_CACHE();
1091d4e0b3aSKirill A. Shutemov 	}
1100fc5e8f4SLv Zheng 
1110fc5e8f4SLv Zheng 	status = acpi_os_enter_sleep(sleep_state, sleep_control, 0);
1120fc5e8f4SLv Zheng 	if (status == AE_CTRL_TERMINATE) {
1130fc5e8f4SLv Zheng 		return_ACPI_STATUS(AE_OK);
1140fc5e8f4SLv Zheng 	}
1150fc5e8f4SLv Zheng 	if (ACPI_FAILURE(status)) {
1160fc5e8f4SLv Zheng 		return_ACPI_STATUS(status);
1170fc5e8f4SLv Zheng 	}
1180fc5e8f4SLv Zheng 
1190fc5e8f4SLv Zheng 	status = acpi_write((u64)sleep_control, &acpi_gbl_FADT.sleep_control);
12070958576SBob Moore 	if (ACPI_FAILURE(status)) {
12170958576SBob Moore 		return_ACPI_STATUS(status);
12270958576SBob Moore 	}
12370958576SBob Moore 
12470958576SBob Moore 	/* Wait for transition back to Working State */
12570958576SBob Moore 
12670958576SBob Moore 	do {
12770958576SBob Moore 		status = acpi_read(&sleep_status, &acpi_gbl_FADT.sleep_status);
12870958576SBob Moore 		if (ACPI_FAILURE(status)) {
12970958576SBob Moore 			return_ACPI_STATUS(status);
13070958576SBob Moore 		}
13170958576SBob Moore 
13270958576SBob Moore 	} while (!(((u8)sleep_status) & ACPI_X_WAKE_STATUS));
13370958576SBob Moore 
13470958576SBob Moore 	return_ACPI_STATUS(AE_OK);
13570958576SBob Moore }
13670958576SBob Moore 
13770958576SBob Moore /*******************************************************************************
13870958576SBob Moore  *
13970958576SBob Moore  * FUNCTION:    acpi_hw_extended_wake_prep
14070958576SBob Moore  *
14170958576SBob Moore  * PARAMETERS:  sleep_state         - Which sleep state we just exited
14270958576SBob Moore  *
14370958576SBob Moore  * RETURN:      Status
14470958576SBob Moore  *
14570958576SBob Moore  * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
14670958576SBob Moore  *              a sleep. Called with interrupts ENABLED.
14770958576SBob Moore  *
14870958576SBob Moore  ******************************************************************************/
14970958576SBob Moore 
acpi_hw_extended_wake_prep(u8 sleep_state)1503f6f49c7SLen Brown acpi_status acpi_hw_extended_wake_prep(u8 sleep_state)
15170958576SBob Moore {
15270958576SBob Moore 	u8 sleep_type_value;
15370958576SBob Moore 
15470958576SBob Moore 	ACPI_FUNCTION_TRACE(hw_extended_wake_prep);
15570958576SBob Moore 
156d3c4b6f6SRafael J. Wysocki 	if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) {
15770958576SBob Moore 		sleep_type_value =
158d3c4b6f6SRafael J. Wysocki 		    ((acpi_gbl_sleep_type_a_s0 << ACPI_X_SLEEP_TYPE_POSITION) &
15970958576SBob Moore 		     ACPI_X_SLEEP_TYPE_MASK);
16070958576SBob Moore 
1615134abfcSBob Moore 		(void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE),
16270958576SBob Moore 				 &acpi_gbl_FADT.sleep_control);
16370958576SBob Moore 	}
16470958576SBob Moore 
16570958576SBob Moore 	return_ACPI_STATUS(AE_OK);
16670958576SBob Moore }
16770958576SBob Moore 
16870958576SBob Moore /*******************************************************************************
16970958576SBob Moore  *
17070958576SBob Moore  * FUNCTION:    acpi_hw_extended_wake
17170958576SBob Moore  *
17270958576SBob Moore  * PARAMETERS:  sleep_state         - Which sleep state we just exited
17370958576SBob Moore  *
17470958576SBob Moore  * RETURN:      Status
17570958576SBob Moore  *
17670958576SBob Moore  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
17770958576SBob Moore  *              Called with interrupts ENABLED.
17870958576SBob Moore  *
17970958576SBob Moore  ******************************************************************************/
18070958576SBob Moore 
acpi_hw_extended_wake(u8 sleep_state)1813f6f49c7SLen Brown acpi_status acpi_hw_extended_wake(u8 sleep_state)
18270958576SBob Moore {
18370958576SBob Moore 	ACPI_FUNCTION_TRACE(hw_extended_wake);
18470958576SBob Moore 
18570958576SBob Moore 	/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
18670958576SBob Moore 
18770958576SBob Moore 	acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
18870958576SBob Moore 
18970958576SBob Moore 	/* Execute the wake methods */
19070958576SBob Moore 
1914efeeecdSBob Moore 	acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);
1924efeeecdSBob Moore 	acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);
19370958576SBob Moore 
19470958576SBob Moore 	/*
19570958576SBob Moore 	 * Some BIOS code assumes that WAK_STS will be cleared on resume
19670958576SBob Moore 	 * and use it to determine whether the system is rebooting or
19770958576SBob Moore 	 * resuming. Clear WAK_STS for compatibility.
19870958576SBob Moore 	 */
1995134abfcSBob Moore 	(void)acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
20070958576SBob Moore 	acpi_gbl_system_awake_and_running = TRUE;
20170958576SBob Moore 
2024efeeecdSBob Moore 	acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
20370958576SBob Moore 	return_ACPI_STATUS(AE_OK);
20470958576SBob Moore }
205