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