Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/******************************************************************************
  3 *
  4 * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces
  5 *
  6 * Copyright (C) 2000 - 2019, Intel Corp.
  7 *
  8 *****************************************************************************/
  9
 10#define EXPORT_ACPI_INTERFACES
 11
 12#include <acpi/acpi.h>
 13#include "accommon.h"
 14
 15#define _COMPONENT          ACPI_HARDWARE
 16ACPI_MODULE_NAME("hwxfsleep")
 17
 18/* Local prototypes */
 19#if (!ACPI_REDUCED_HARDWARE)
 20static acpi_status
 21acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
 22				   acpi_physical_address physical_address,
 23				   acpi_physical_address physical_address64);
 24#endif
 25
 26/*
 27 * These functions are removed for the ACPI_REDUCED_HARDWARE case:
 28 *      acpi_set_firmware_waking_vector
 29 *      acpi_enter_sleep_state_s4bios
 30 */
 31
 32#if (!ACPI_REDUCED_HARDWARE)
 33/*******************************************************************************
 34 *
 35 * FUNCTION:    acpi_hw_set_firmware_waking_vector
 36 *
 37 * PARAMETERS:  facs                - Pointer to FACS table
 38 *              physical_address    - 32-bit physical address of ACPI real mode
 39 *                                    entry point
 40 *              physical_address64  - 64-bit physical address of ACPI protected
 41 *                                    mode entry point
 42 *
 43 * RETURN:      Status
 44 *
 45 * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS
 46 *
 47 ******************************************************************************/
 48
 49static acpi_status
 50acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
 51				   acpi_physical_address physical_address,
 52				   acpi_physical_address physical_address64)
 53{
 54	ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vector);
 55
 56
 57	/*
 58	 * According to the ACPI specification 2.0c and later, the 64-bit
 59	 * waking vector should be cleared and the 32-bit waking vector should
 60	 * be used, unless we want the wake-up code to be called by the BIOS in
 61	 * Protected Mode.  Some systems (for example HP dv5-1004nr) are known
 62	 * to fail to resume if the 64-bit vector is used.
 63	 */
 64
 65	/* Set the 32-bit vector */
 66
 67	facs->firmware_waking_vector = (u32)physical_address;
 68
 69	if (facs->length > 32) {
 70		if (facs->version >= 1) {
 71
 72			/* Set the 64-bit vector */
 73
 74			facs->xfirmware_waking_vector = physical_address64;
 75		} else {
 76			/* Clear the 64-bit vector if it exists */
 77
 78			facs->xfirmware_waking_vector = 0;
 79		}
 80	}
 81
 82	return_ACPI_STATUS(AE_OK);
 83}
 84
 85/*******************************************************************************
 86 *
 87 * FUNCTION:    acpi_set_firmware_waking_vector
 88 *
 89 * PARAMETERS:  physical_address    - 32-bit physical address of ACPI real mode
 90 *                                    entry point
 91 *              physical_address64  - 64-bit physical address of ACPI protected
 92 *                                    mode entry point
 93 *
 94 * RETURN:      Status
 95 *
 96 * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS
 97 *
 98 ******************************************************************************/
 99
100acpi_status
101acpi_set_firmware_waking_vector(acpi_physical_address physical_address,
102				acpi_physical_address physical_address64)
103{
104
105	ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
106
107	if (acpi_gbl_FACS) {
108		(void)acpi_hw_set_firmware_waking_vector(acpi_gbl_FACS,
109							 physical_address,
110							 physical_address64);
111	}
112
113	return_ACPI_STATUS(AE_OK);
114}
115
116ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
117
118/*******************************************************************************
119 *
120 * FUNCTION:    acpi_enter_sleep_state_s4bios
121 *
122 * PARAMETERS:  None
123 *
124 * RETURN:      Status
125 *
126 * DESCRIPTION: Perform a S4 bios request.
127 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
128 *
129 ******************************************************************************/
130acpi_status acpi_enter_sleep_state_s4bios(void)
131{
132	u32 in_value;
133	acpi_status status;
134
135	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios);
136
137	/* Clear the wake status bit (PM1) */
138
139	status =
140	    acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
141	if (ACPI_FAILURE(status)) {
142		return_ACPI_STATUS(status);
143	}
144
145	status = acpi_hw_clear_acpi_status();
146	if (ACPI_FAILURE(status)) {
147		return_ACPI_STATUS(status);
148	}
149
150	/*
151	 * 1) Disable all GPEs
152	 * 2) Enable all wakeup GPEs
153	 */
154	status = acpi_hw_disable_all_gpes();
155	if (ACPI_FAILURE(status)) {
156		return_ACPI_STATUS(status);
157	}
158	acpi_gbl_system_awake_and_running = FALSE;
159
160	status = acpi_hw_enable_all_wakeup_gpes();
161	if (ACPI_FAILURE(status)) {
162		return_ACPI_STATUS(status);
163	}
164
165	ACPI_FLUSH_CPU_CACHE();
166
167	status = acpi_hw_write_port(acpi_gbl_FADT.smi_command,
168				    (u32)acpi_gbl_FADT.s4_bios_request, 8);
169
170	do {
171		acpi_os_stall(ACPI_USEC_PER_MSEC);
172		status =
173		    acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
174		if (ACPI_FAILURE(status)) {
175			return_ACPI_STATUS(status);
176		}
177
178	} while (!in_value);
179
180	return_ACPI_STATUS(AE_OK);
181}
182
183ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
184#endif				/* !ACPI_REDUCED_HARDWARE */
185
186/*******************************************************************************
187 *
188 * FUNCTION:    acpi_enter_sleep_state_prep
189 *
190 * PARAMETERS:  sleep_state         - Which sleep state to enter
191 *
192 * RETURN:      Status
193 *
194 * DESCRIPTION: Prepare to enter a system sleep state.
195 *              This function must execute with interrupts enabled.
196 *              We break sleeping into 2 stages so that OSPM can handle
197 *              various OS-specific tasks between the two steps.
198 *
199 ******************************************************************************/
200
201acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
202{
203	acpi_status status;
204	struct acpi_object_list arg_list;
205	union acpi_object arg;
206	u32 sst_value;
207
208	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);
209
210	status = acpi_get_sleep_type_data(sleep_state,
211					  &acpi_gbl_sleep_type_a,
212					  &acpi_gbl_sleep_type_b);
213	if (ACPI_FAILURE(status)) {
214		return_ACPI_STATUS(status);
215	}
216
217	/* Execute the _PTS method (Prepare To Sleep) */
218
219	arg_list.count = 1;
220	arg_list.pointer = &arg;
221	arg.type = ACPI_TYPE_INTEGER;
222	arg.integer.value = sleep_state;
223
224	status =
225	    acpi_evaluate_object(NULL, METHOD_PATHNAME__PTS, &arg_list, NULL);
226	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
227		return_ACPI_STATUS(status);
228	}
229
230	/* Setup the argument to the _SST method (System STatus) */
231
232	switch (sleep_state) {
233	case ACPI_STATE_S0:
234
235		sst_value = ACPI_SST_WORKING;
236		break;
237
238	case ACPI_STATE_S1:
239	case ACPI_STATE_S2:
240	case ACPI_STATE_S3:
241
242		sst_value = ACPI_SST_SLEEPING;
243		break;
244
245	case ACPI_STATE_S4:
246
247		sst_value = ACPI_SST_SLEEP_CONTEXT;
248		break;
249
250	default:
251
252		sst_value = ACPI_SST_INDICATOR_OFF;	/* Default is off */
253		break;
254	}
255
256	/*
257	 * Set the system indicators to show the desired sleep state.
258	 * _SST is an optional method (return no error if not found)
259	 */
260	acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, sst_value);
261	return_ACPI_STATUS(AE_OK);
262}
263
264ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
265
266/*******************************************************************************
267 *
268 * FUNCTION:    acpi_enter_sleep_state
269 *
270 * PARAMETERS:  sleep_state         - Which sleep state to enter
271 *
272 * RETURN:      Status
273 *
274 * DESCRIPTION: Enter a system sleep state
275 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
276 *
277 ******************************************************************************/
278acpi_status acpi_enter_sleep_state(u8 sleep_state)
279{
280	acpi_status status;
281
282	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
283
284	if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
285	    (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
286		ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X",
287			    acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
288		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
289	}
290
291#if !ACPI_REDUCED_HARDWARE
292	if (!acpi_gbl_reduced_hardware)
293		status = acpi_hw_legacy_sleep(sleep_state);
294	else
295#endif
296		status = acpi_hw_extended_sleep(sleep_state);
297	return_ACPI_STATUS(status);
298}
299
300ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
301
302/*******************************************************************************
303 *
304 * FUNCTION:    acpi_leave_sleep_state_prep
305 *
306 * PARAMETERS:  sleep_state         - Which sleep state we are exiting
307 *
308 * RETURN:      Status
309 *
310 * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
311 *              sleep. Called with interrupts DISABLED.
312 *              We break wake/resume into 2 stages so that OSPM can handle
313 *              various OS-specific tasks between the two steps.
314 *
315 ******************************************************************************/
316acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
317{
318	acpi_status status;
319
320	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
321
322#if !ACPI_REDUCED_HARDWARE
323	if (!acpi_gbl_reduced_hardware)
324		status = acpi_hw_legacy_wake_prep(sleep_state);
325	else
326#endif
327		status = acpi_hw_extended_wake_prep(sleep_state);
328	return_ACPI_STATUS(status);
329}
330
331ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state_prep)
332
333/*******************************************************************************
334 *
335 * FUNCTION:    acpi_leave_sleep_state
336 *
337 * PARAMETERS:  sleep_state         - Which sleep state we are exiting
338 *
339 * RETURN:      Status
340 *
341 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
342 *              Called with interrupts ENABLED.
343 *
344 ******************************************************************************/
345acpi_status acpi_leave_sleep_state(u8 sleep_state)
346{
347	acpi_status status;
348
349	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
350
351#if !ACPI_REDUCED_HARDWARE
352	if (!acpi_gbl_reduced_hardware)
353		status = acpi_hw_legacy_wake(sleep_state);
354	else
355#endif
356		status = acpi_hw_extended_wake(sleep_state);
357	return_ACPI_STATUS(status);
358}
359
360ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)