brintos

brintos / linux-shallow public Read only

0
0
Text · 9.8 KiB · 8dbf83a Raw
366 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#define EXPORT_ACPI_INTERFACES11 12#include <acpi/acpi.h>13#include "accommon.h"14 15#define _COMPONENT          ACPI_HARDWARE16ACPI_MODULE_NAME("hwxfsleep")17 18/* Local prototypes */19static acpi_status20acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,21				   acpi_physical_address physical_address,22				   acpi_physical_address physical_address64);23 24/*******************************************************************************25 *26 * FUNCTION:    acpi_hw_set_firmware_waking_vector27 *28 * PARAMETERS:  facs                - Pointer to FACS table29 *              physical_address    - 32-bit physical address of ACPI real mode30 *                                    entry point31 *              physical_address64  - 64-bit physical address of ACPI protected32 *                                    mode entry point33 *34 * RETURN:      Status35 *36 * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS37 *38 ******************************************************************************/39 40static acpi_status41acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,42				   acpi_physical_address physical_address,43				   acpi_physical_address physical_address64)44{45	ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vector);46 47 48	/*49	 * According to the ACPI specification 2.0c and later, the 64-bit50	 * waking vector should be cleared and the 32-bit waking vector should51	 * be used, unless we want the wake-up code to be called by the BIOS in52	 * Protected Mode.  Some systems (for example HP dv5-1004nr) are known53	 * to fail to resume if the 64-bit vector is used.54	 */55 56	/* Set the 32-bit vector */57 58	facs->firmware_waking_vector = (u32)physical_address;59 60	if (facs->length > 32) {61		if (facs->version >= 1) {62 63			/* Set the 64-bit vector */64 65			facs->xfirmware_waking_vector = physical_address64;66		} else {67			/* Clear the 64-bit vector if it exists */68 69			facs->xfirmware_waking_vector = 0;70		}71	}72 73	return_ACPI_STATUS(AE_OK);74}75 76/*******************************************************************************77 *78 * FUNCTION:    acpi_set_firmware_waking_vector79 *80 * PARAMETERS:  physical_address    - 32-bit physical address of ACPI real mode81 *                                    entry point82 *              physical_address64  - 64-bit physical address of ACPI protected83 *                                    mode entry point84 *85 * RETURN:      Status86 *87 * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS88 *89 ******************************************************************************/90 91acpi_status92acpi_set_firmware_waking_vector(acpi_physical_address physical_address,93				acpi_physical_address physical_address64)94{95 96	ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);97 98	if (acpi_gbl_FACS) {99		(void)acpi_hw_set_firmware_waking_vector(acpi_gbl_FACS,100							 physical_address,101							 physical_address64);102	}103 104	return_ACPI_STATUS(AE_OK);105}106 107ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)108 109/*110 * These functions are removed for the ACPI_REDUCED_HARDWARE case:111 *      acpi_enter_sleep_state_s4bios112 */113 114#if (!ACPI_REDUCED_HARDWARE)115/*******************************************************************************116 *117 * FUNCTION:    acpi_enter_sleep_state_s4bios118 *119 * PARAMETERS:  None120 *121 * RETURN:      Status122 *123 * DESCRIPTION: Perform a S4 bios request.124 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED125 *126 ******************************************************************************/127acpi_status acpi_enter_sleep_state_s4bios(void)128{129	u32 in_value;130	acpi_status status;131 132	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios);133 134	/* Clear the wake status bit (PM1) */135 136	status =137	    acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);138	if (ACPI_FAILURE(status)) {139		return_ACPI_STATUS(status);140	}141 142	status = acpi_hw_clear_acpi_status();143	if (ACPI_FAILURE(status)) {144		return_ACPI_STATUS(status);145	}146 147	/*148	 * 1) Disable all GPEs149	 * 2) Enable all wakeup GPEs150	 */151	status = acpi_hw_disable_all_gpes();152	if (ACPI_FAILURE(status)) {153		return_ACPI_STATUS(status);154	}155	acpi_gbl_system_awake_and_running = FALSE;156 157	status = acpi_hw_enable_all_wakeup_gpes();158	if (ACPI_FAILURE(status)) {159		return_ACPI_STATUS(status);160	}161 162	status = acpi_hw_write_port(acpi_gbl_FADT.smi_command,163				    (u32)acpi_gbl_FADT.s4_bios_request, 8);164	if (ACPI_FAILURE(status)) {165		return_ACPI_STATUS(status);166	}167 168	do {169		acpi_os_stall(ACPI_USEC_PER_MSEC);170		status =171		    acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);172		if (ACPI_FAILURE(status)) {173			return_ACPI_STATUS(status);174		}175 176	} while (!in_value);177 178	return_ACPI_STATUS(AE_OK);179}180 181ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)182#endif				/* !ACPI_REDUCED_HARDWARE */183 184/*******************************************************************************185 *186 * FUNCTION:    acpi_enter_sleep_state_prep187 *188 * PARAMETERS:  sleep_state         - Which sleep state to enter189 *190 * RETURN:      Status191 *192 * DESCRIPTION: Prepare to enter a system sleep state.193 *              This function must execute with interrupts enabled.194 *              We break sleeping into 2 stages so that OSPM can handle195 *              various OS-specific tasks between the two steps.196 *197 ******************************************************************************/198 199acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)200{201	acpi_status status;202	struct acpi_object_list arg_list;203	union acpi_object arg;204	u32 sst_value;205 206	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);207 208	status = acpi_get_sleep_type_data(sleep_state,209					  &acpi_gbl_sleep_type_a,210					  &acpi_gbl_sleep_type_b);211	if (ACPI_FAILURE(status)) {212		return_ACPI_STATUS(status);213	}214 215	status = acpi_get_sleep_type_data(ACPI_STATE_S0,216					  &acpi_gbl_sleep_type_a_s0,217					  &acpi_gbl_sleep_type_b_s0);218	if (ACPI_FAILURE(status)) {219		acpi_gbl_sleep_type_a_s0 = ACPI_SLEEP_TYPE_INVALID;220	}221 222	/* Execute the _PTS method (Prepare To Sleep) */223 224	arg_list.count = 1;225	arg_list.pointer = &arg;226	arg.type = ACPI_TYPE_INTEGER;227	arg.integer.value = sleep_state;228 229	status =230	    acpi_evaluate_object(NULL, METHOD_PATHNAME__PTS, &arg_list, NULL);231	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {232		return_ACPI_STATUS(status);233	}234 235	/* Setup the argument to the _SST method (System STatus) */236 237	switch (sleep_state) {238	case ACPI_STATE_S0:239 240		sst_value = ACPI_SST_WORKING;241		break;242 243	case ACPI_STATE_S1:244	case ACPI_STATE_S2:245	case ACPI_STATE_S3:246 247		sst_value = ACPI_SST_SLEEPING;248		break;249 250	case ACPI_STATE_S4:251 252		sst_value = ACPI_SST_SLEEP_CONTEXT;253		break;254 255	default:256 257		sst_value = ACPI_SST_INDICATOR_OFF;	/* Default is off */258		break;259	}260 261	/*262	 * Set the system indicators to show the desired sleep state.263	 * _SST is an optional method (return no error if not found)264	 */265	acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, sst_value);266	return_ACPI_STATUS(AE_OK);267}268 269ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)270 271/*******************************************************************************272 *273 * FUNCTION:    acpi_enter_sleep_state274 *275 * PARAMETERS:  sleep_state         - Which sleep state to enter276 *277 * RETURN:      Status278 *279 * DESCRIPTION: Enter a system sleep state280 *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED281 *282 ******************************************************************************/283acpi_status acpi_enter_sleep_state(u8 sleep_state)284{285	acpi_status status;286 287	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);288 289	if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||290	    (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {291		ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X",292			    acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));293		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);294	}295 296#if !ACPI_REDUCED_HARDWARE297	if (!acpi_gbl_reduced_hardware)298		status = acpi_hw_legacy_sleep(sleep_state);299	else300#endif301		status = acpi_hw_extended_sleep(sleep_state);302	return_ACPI_STATUS(status);303}304 305ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)306 307/*******************************************************************************308 *309 * FUNCTION:    acpi_leave_sleep_state_prep310 *311 * PARAMETERS:  sleep_state         - Which sleep state we are exiting312 *313 * RETURN:      Status314 *315 * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a316 *              sleep. Called with interrupts DISABLED.317 *              We break wake/resume into 2 stages so that OSPM can handle318 *              various OS-specific tasks between the two steps.319 *320 ******************************************************************************/321acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)322{323	acpi_status status;324 325	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);326 327#if !ACPI_REDUCED_HARDWARE328	if (!acpi_gbl_reduced_hardware)329		status = acpi_hw_legacy_wake_prep(sleep_state);330	else331#endif332		status = acpi_hw_extended_wake_prep(sleep_state);333	return_ACPI_STATUS(status);334}335 336ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state_prep)337 338/*******************************************************************************339 *340 * FUNCTION:    acpi_leave_sleep_state341 *342 * PARAMETERS:  sleep_state         - Which sleep state we are exiting343 *344 * RETURN:      Status345 *346 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep347 *              Called with interrupts ENABLED.348 *349 ******************************************************************************/350acpi_status acpi_leave_sleep_state(u8 sleep_state)351{352	acpi_status status;353 354	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);355 356#if !ACPI_REDUCED_HARDWARE357	if (!acpi_gbl_reduced_hardware)358		status = acpi_hw_legacy_wake(sleep_state);359	else360#endif361		status = acpi_hw_extended_wake(sleep_state);362	return_ACPI_STATUS(status);363}364 365ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)366