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 - 2016, 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 MERCHANTIBILITY 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 |
67 | AcpiHwExecuteSleepMethod ( |
68 | 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 |
112 | AcpiHwExtendedSleep ( |
113 | UINT8 SleepState) |
114 | { |
115 | ACPI_STATUS Status; |
116 | UINT8 SleepTypeValue; |
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 | /* Flush caches, as per ACPI specification */ |
143 | |
144 | ACPI_FLUSH_CPU_CACHE (); |
145 | |
146 | /* |
147 | * Set the SLP_TYP and SLP_EN bits. |
148 | * |
149 | * Note: We only use the first value returned by the \_Sx method |
150 | * (AcpiGbl_SleepTypeA) - As per ACPI specification. |
151 | */ |
152 | ACPI_DEBUG_PRINT ((ACPI_DB_INIT, |
153 | "Entering sleep state [S%u]\n" , SleepState)); |
154 | |
155 | SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) & |
156 | ACPI_X_SLEEP_TYPE_MASK); |
157 | |
158 | Status = AcpiWrite ((UINT64) (SleepTypeValue | ACPI_X_SLEEP_ENABLE), |
159 | &AcpiGbl_FADT.SleepControl); |
160 | if (ACPI_FAILURE (Status)) |
161 | { |
162 | return_ACPI_STATUS (Status); |
163 | } |
164 | |
165 | /* Wait for transition back to Working State */ |
166 | |
167 | do |
168 | { |
169 | Status = AcpiRead (&SleepStatus, &AcpiGbl_FADT.SleepStatus); |
170 | if (ACPI_FAILURE (Status)) |
171 | { |
172 | return_ACPI_STATUS (Status); |
173 | } |
174 | |
175 | } while (!(((UINT8) SleepStatus) & ACPI_X_WAKE_STATUS)); |
176 | |
177 | return_ACPI_STATUS (AE_OK); |
178 | } |
179 | |
180 | |
181 | /******************************************************************************* |
182 | * |
183 | * FUNCTION: AcpiHwExtendedWakePrep |
184 | * |
185 | * PARAMETERS: SleepState - Which sleep state we just exited |
186 | * |
187 | * RETURN: Status |
188 | * |
189 | * DESCRIPTION: Perform first part of OS-independent ACPI cleanup after |
190 | * a sleep. Called with interrupts ENABLED. |
191 | * |
192 | ******************************************************************************/ |
193 | |
194 | ACPI_STATUS |
195 | AcpiHwExtendedWakePrep ( |
196 | UINT8 SleepState) |
197 | { |
198 | ACPI_STATUS Status; |
199 | UINT8 SleepTypeValue; |
200 | |
201 | |
202 | ACPI_FUNCTION_TRACE (HwExtendedWakePrep); |
203 | |
204 | |
205 | Status = AcpiGetSleepTypeData (ACPI_STATE_S0, |
206 | &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB); |
207 | if (ACPI_SUCCESS (Status)) |
208 | { |
209 | SleepTypeValue = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) & |
210 | ACPI_X_SLEEP_TYPE_MASK); |
211 | |
212 | (void) AcpiWrite ((UINT64) (SleepTypeValue | ACPI_X_SLEEP_ENABLE), |
213 | &AcpiGbl_FADT.SleepControl); |
214 | } |
215 | |
216 | return_ACPI_STATUS (AE_OK); |
217 | } |
218 | |
219 | |
220 | /******************************************************************************* |
221 | * |
222 | * FUNCTION: AcpiHwExtendedWake |
223 | * |
224 | * PARAMETERS: SleepState - Which sleep state we just exited |
225 | * |
226 | * RETURN: Status |
227 | * |
228 | * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep |
229 | * Called with interrupts ENABLED. |
230 | * |
231 | ******************************************************************************/ |
232 | |
233 | ACPI_STATUS |
234 | AcpiHwExtendedWake ( |
235 | UINT8 SleepState) |
236 | { |
237 | ACPI_FUNCTION_TRACE (HwExtendedWake); |
238 | |
239 | |
240 | /* Ensure EnterSleepStatePrep -> EnterSleepState ordering */ |
241 | |
242 | AcpiGbl_SleepTypeA = ACPI_SLEEP_TYPE_INVALID; |
243 | |
244 | /* Execute the wake methods */ |
245 | |
246 | AcpiHwExecuteSleepMethod (__UNCONST(METHOD_PATHNAME__SST), ACPI_SST_WAKING); |
247 | AcpiHwExecuteSleepMethod (__UNCONST(METHOD_PATHNAME__WAK), SleepState); |
248 | |
249 | /* |
250 | * Some BIOS code assumes that WAK_STS will be cleared on resume |
251 | * and use it to determine whether the system is rebooting or |
252 | * resuming. Clear WAK_STS for compatibility. |
253 | */ |
254 | (void) AcpiWrite ((UINT64) ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus); |
255 | AcpiGbl_SystemAwakeAndRunning = TRUE; |
256 | |
257 | AcpiHwExecuteSleepMethod (__UNCONST(METHOD_PATHNAME__SST), ACPI_SST_WORKING); |
258 | return_ACPI_STATUS (AE_OK); |
259 | } |
260 | |