1 /******************************************************************************
2 *
3 * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the
4 * extended FADT-V5 sleep registers.
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000 - 2023, Intel Corp.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45 #include "acpi.h"
46 #include "accommon.h"
47
48 #define _COMPONENT ACPI_HARDWARE
49 ACPI_MODULE_NAME ("hwesleep")
50
51
52 /*******************************************************************************
53 *
54 * FUNCTION: AcpiHwExecuteSleepMethod
55 *
56 * PARAMETERS: MethodPathname - Pathname of method to execute
57 * IntegerArgument - Argument to pass to the method
58 *
59 * RETURN: None
60 *
61 * DESCRIPTION: Execute a sleep/wake related method with one integer argument
62 * and no return value.
63 *
64 ******************************************************************************/
65
66 void
AcpiHwExecuteSleepMethod(const char * MethodPathname,UINT32 IntegerArgument)67 AcpiHwExecuteSleepMethod (
68 const char *MethodPathname,
69 UINT32 IntegerArgument)
70 {
71 ACPI_OBJECT_LIST ArgList;
72 ACPI_OBJECT Arg;
73 ACPI_STATUS Status;
74
75
76 ACPI_FUNCTION_TRACE (HwExecuteSleepMethod);
77
78
79 /* One argument, IntegerArgument; No return value expected */
80
81 ArgList.Count = 1;
82 ArgList.Pointer = &Arg;
83 Arg.Type = ACPI_TYPE_INTEGER;
84 Arg.Integer.Value = (UINT64) IntegerArgument;
85
86 Status = AcpiEvaluateObject (NULL, MethodPathname, &ArgList, NULL);
87 if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND)
88 {
89 ACPI_EXCEPTION ((AE_INFO, Status, "While executing method %s",
90 MethodPathname));
91 }
92
93 return_VOID;
94 }
95
96
97 /*******************************************************************************
98 *
99 * FUNCTION: AcpiHwExtendedSleep
100 *
101 * PARAMETERS: SleepState - Which sleep state to enter
102 *
103 * RETURN: Status
104 *
105 * DESCRIPTION: Enter a system sleep state via the extended FADT sleep
106 * registers (V5 FADT).
107 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
108 *
109 ******************************************************************************/
110
111 ACPI_STATUS
AcpiHwExtendedSleep(UINT8 SleepState)112 AcpiHwExtendedSleep (
113 UINT8 SleepState)
114 {
115 ACPI_STATUS Status;
116 UINT8 SleepControl;
117 UINT64 SleepStatus;
118
119
120 ACPI_FUNCTION_TRACE (HwExtendedSleep);
121
122
123 /* Extended sleep registers must be valid */
124
125 if (!AcpiGbl_FADT.SleepControl.Address ||
126 !AcpiGbl_FADT.SleepStatus.Address)
127 {
128 return_ACPI_STATUS (AE_NOT_EXIST);
129 }
130
131 /* Clear wake status (WAK_STS) */
132
133 Status = AcpiWrite ((UINT64) ACPI_X_WAKE_STATUS,
134 &AcpiGbl_FADT.SleepStatus);
135 if (ACPI_FAILURE (Status))
136 {
137 return_ACPI_STATUS (Status);
138 }
139
140 AcpiGbl_SystemAwakeAndRunning = FALSE;
141
142 /*
143 * Set the SLP_TYP and SLP_EN bits.
144 *
145 * Note: We only use the first value returned by the \_Sx method
146 * (AcpiGbl_SleepTypeA) - As per ACPI specification.
147 */
148 ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
149 "Entering sleep state [S%u]\n", SleepState));
150
151 SleepControl = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) &
152 ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE;
153
154 /* Flush caches, as per ACPI specification */
155
156 ACPI_FLUSH_CPU_CACHE ();
157
158 Status = AcpiOsEnterSleep (SleepState, SleepControl, 0);
159 if (Status == AE_CTRL_TERMINATE)
160 {
161 return_ACPI_STATUS (AE_OK);
162 }
163 if (ACPI_FAILURE (Status))
164 {
165 return_ACPI_STATUS (Status);
166 }
167
168 Status = AcpiWrite ((UINT64) SleepControl, &AcpiGbl_FADT.SleepControl);
169 if (ACPI_FAILURE (Status))
170 {
171 return_ACPI_STATUS (Status);
172 }
173
174 /* Wait for transition back to Working State */
175
176 do
177 {
178 Status = AcpiRead (&SleepStatus, &AcpiGbl_FADT.SleepStatus);
179 if (ACPI_FAILURE (Status))
180 {
181 return_ACPI_STATUS (Status);
182 }
183
184 } while (!(((UINT8) SleepStatus) & ACPI_X_WAKE_STATUS));
185
186 return_ACPI_STATUS (AE_OK);
187 }
188
189
190 /*******************************************************************************
191 *
192 * FUNCTION: AcpiHwExtendedWakePrep
193 *
194 * PARAMETERS: SleepState - Which sleep state we just exited
195 *
196 * RETURN: Status
197 *
198 * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
199 * a sleep. Called with interrupts ENABLED.
200 *
201 ******************************************************************************/
202
203 ACPI_STATUS
AcpiHwExtendedWakePrep(UINT8 SleepState)204 AcpiHwExtendedWakePrep (
205 UINT8 SleepState)
206 {
207 UINT8 SleepTypeValue;
208
209
210 ACPI_FUNCTION_TRACE (HwExtendedWakePrep);
211
212
213 if (AcpiGbl_SleepTypeAS0 != ACPI_SLEEP_TYPE_INVALID)
214 {
215 SleepTypeValue = ((AcpiGbl_SleepTypeAS0 << ACPI_X_SLEEP_TYPE_POSITION) &
216 ACPI_X_SLEEP_TYPE_MASK);
217
218 (void) AcpiWrite ((UINT64) (SleepTypeValue | ACPI_X_SLEEP_ENABLE),
219 &AcpiGbl_FADT.SleepControl);
220 }
221
222 return_ACPI_STATUS (AE_OK);
223 }
224
225
226 /*******************************************************************************
227 *
228 * FUNCTION: AcpiHwExtendedWake
229 *
230 * PARAMETERS: SleepState - Which sleep state we just exited
231 *
232 * RETURN: Status
233 *
234 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
235 * Called with interrupts ENABLED.
236 *
237 ******************************************************************************/
238
239 ACPI_STATUS
AcpiHwExtendedWake(UINT8 SleepState)240 AcpiHwExtendedWake (
241 UINT8 SleepState)
242 {
243 ACPI_FUNCTION_TRACE (HwExtendedWake);
244
245
246 /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */
247
248 AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID;
249
250 /* Execute the wake methods */
251
252 AcpiHwExecuteSleepMethod (__UNCONST(METHOD_PATHNAME__SST), ACPI_SST_WAKING);
253 AcpiHwExecuteSleepMethod (__UNCONST(METHOD_PATHNAME__WAK), SleepState);
254
255 /*
256 * Some BIOS code assumes that WAK_STS will be cleared on resume
257 * and use it to determine whether the system is rebooting or
258 * resuming. Clear WAK_STS for compatibility.
259 */
260 (void) AcpiWrite ((UINT64) ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus);
261 AcpiGbl_SystemAwakeAndRunning = TRUE;
262
263 AcpiHwExecuteSleepMethod (__UNCONST(METHOD_PATHNAME__SST), ACPI_SST_WORKING);
264 return_ACPI_STATUS (AE_OK);
265 }
266