205 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the5 * extended FADT-V5 sleep registers.6 *7 * Copyright (C) 2000 - 2023, Intel Corp.8 *9 *****************************************************************************/10 11#include <acpi/acpi.h>12#include "accommon.h"13 14#define _COMPONENT ACPI_HARDWARE15ACPI_MODULE_NAME("hwesleep")16 17/*******************************************************************************18 *19 * FUNCTION: acpi_hw_execute_sleep_method20 *21 * PARAMETERS: method_pathname - Pathname of method to execute22 * integer_argument - Argument to pass to the method23 *24 * RETURN: None25 *26 * DESCRIPTION: Execute a sleep/wake related method with one integer argument27 * and no return value.28 *29 ******************************************************************************/30void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument)31{32 struct acpi_object_list arg_list;33 union acpi_object arg;34 acpi_status status;35 36 ACPI_FUNCTION_TRACE(hw_execute_sleep_method);37 38 /* One argument, integer_argument; No return value expected */39 40 arg_list.count = 1;41 arg_list.pointer = &arg;42 arg.type = ACPI_TYPE_INTEGER;43 arg.integer.value = (u64)integer_argument;44 45 status = acpi_evaluate_object(NULL, method_pathname, &arg_list, NULL);46 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {47 ACPI_EXCEPTION((AE_INFO, status, "While executing method %s",48 method_pathname));49 }50 51 return_VOID;52}53 54/*******************************************************************************55 *56 * FUNCTION: acpi_hw_extended_sleep57 *58 * PARAMETERS: sleep_state - Which sleep state to enter59 *60 * RETURN: Status61 *62 * DESCRIPTION: Enter a system sleep state via the extended FADT sleep63 * registers (V5 FADT).64 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED65 *66 ******************************************************************************/67 68acpi_status acpi_hw_extended_sleep(u8 sleep_state)69{70 acpi_status status;71 u8 sleep_control;72 u64 sleep_status;73 74 ACPI_FUNCTION_TRACE(hw_extended_sleep);75 76 /* Extended sleep registers must be valid */77 78 if (!acpi_gbl_FADT.sleep_control.address ||79 !acpi_gbl_FADT.sleep_status.address) {80 return_ACPI_STATUS(AE_NOT_EXIST);81 }82 83 /* Clear wake status (WAK_STS) */84 85 status = acpi_write((u64)ACPI_X_WAKE_STATUS,86 &acpi_gbl_FADT.sleep_status);87 if (ACPI_FAILURE(status)) {88 return_ACPI_STATUS(status);89 }90 91 acpi_gbl_system_awake_and_running = FALSE;92 93 /*94 * Set the SLP_TYP and SLP_EN bits.95 *96 * Note: We only use the first value returned by the \_Sx method97 * (acpi_gbl_sleep_type_a) - As per ACPI specification.98 */99 ACPI_DEBUG_PRINT((ACPI_DB_INIT,100 "Entering sleep state [S%u]\n", sleep_state));101 102 sleep_control = ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &103 ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE;104 105 /* Flush caches, as per ACPI specification */106 107 if (sleep_state < ACPI_STATE_S4) {108 ACPI_FLUSH_CPU_CACHE();109 }110 111 status = acpi_os_enter_sleep(sleep_state, sleep_control, 0);112 if (status == AE_CTRL_TERMINATE) {113 return_ACPI_STATUS(AE_OK);114 }115 if (ACPI_FAILURE(status)) {116 return_ACPI_STATUS(status);117 }118 119 status = acpi_write((u64)sleep_control, &acpi_gbl_FADT.sleep_control);120 if (ACPI_FAILURE(status)) {121 return_ACPI_STATUS(status);122 }123 124 /* Wait for transition back to Working State */125 126 do {127 status = acpi_read(&sleep_status, &acpi_gbl_FADT.sleep_status);128 if (ACPI_FAILURE(status)) {129 return_ACPI_STATUS(status);130 }131 132 } while (!(((u8)sleep_status) & ACPI_X_WAKE_STATUS));133 134 return_ACPI_STATUS(AE_OK);135}136 137/*******************************************************************************138 *139 * FUNCTION: acpi_hw_extended_wake_prep140 *141 * PARAMETERS: sleep_state - Which sleep state we just exited142 *143 * RETURN: Status144 *145 * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after146 * a sleep. Called with interrupts ENABLED.147 *148 ******************************************************************************/149 150acpi_status acpi_hw_extended_wake_prep(u8 sleep_state)151{152 u8 sleep_type_value;153 154 ACPI_FUNCTION_TRACE(hw_extended_wake_prep);155 156 if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) {157 sleep_type_value =158 ((acpi_gbl_sleep_type_a_s0 << ACPI_X_SLEEP_TYPE_POSITION) &159 ACPI_X_SLEEP_TYPE_MASK);160 161 (void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE),162 &acpi_gbl_FADT.sleep_control);163 }164 165 return_ACPI_STATUS(AE_OK);166}167 168/*******************************************************************************169 *170 * FUNCTION: acpi_hw_extended_wake171 *172 * PARAMETERS: sleep_state - Which sleep state we just exited173 *174 * RETURN: Status175 *176 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep177 * Called with interrupts ENABLED.178 *179 ******************************************************************************/180 181acpi_status acpi_hw_extended_wake(u8 sleep_state)182{183 ACPI_FUNCTION_TRACE(hw_extended_wake);184 185 /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */186 187 acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;188 189 /* Execute the wake methods */190 191 acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);192 acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);193 194 /*195 * Some BIOS code assumes that WAK_STS will be cleared on resume196 * and use it to determine whether the system is rebooting or197 * resuming. Clear WAK_STS for compatibility.198 */199 (void)acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);200 acpi_gbl_system_awake_and_running = TRUE;201 202 acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);203 return_ACPI_STATUS(AE_OK);204}205