| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 |  | 
 | 2 | /****************************************************************************** | 
 | 3 |  * | 
 | 4 |  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface | 
 | 5 |  * | 
 | 6 |  *****************************************************************************/ | 
 | 7 |  | 
 | 8 | /* | 
| Bob Moore | b4e104e | 2011-01-17 11:05:40 +0800 | [diff] [blame] | 9 |  * Copyright (C) 2000 - 2011, Intel Corp. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 45 | #include <acpi/acpi.h> | 
| Len Brown | e2f7a77 | 2009-01-09 00:30:03 -0500 | [diff] [blame] | 46 | #include "accommon.h" | 
 | 47 | #include "actables.h" | 
| Shane Wang | 69575d3 | 2009-09-01 18:25:07 -0700 | [diff] [blame] | 48 | #include <linux/tboot.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 49 |  | 
 | 50 | #define _COMPONENT          ACPI_HARDWARE | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 51 | ACPI_MODULE_NAME("hwsleep") | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 52 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 53 | /******************************************************************************* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 54 |  * | 
 | 55 |  * FUNCTION:    acpi_set_firmware_waking_vector | 
 | 56 |  * | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 57 |  * PARAMETERS:  physical_address    - 32-bit physical address of ACPI real mode | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 58 |  *                                    entry point. | 
 | 59 |  * | 
 | 60 |  * RETURN:      Status | 
 | 61 |  * | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 62 |  * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 63 |  * | 
 | 64 |  ******************************************************************************/ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 65 | acpi_status | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 66 | acpi_set_firmware_waking_vector(u32 physical_address) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 67 | { | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 68 | 	ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 69 |  | 
| Bob Moore | f3d2e78 | 2007-02-02 19:48:18 +0300 | [diff] [blame] | 70 |  | 
| Rafael J. Wysocki | a662910 | 2008-09-06 13:13:01 +0200 | [diff] [blame] | 71 | 	/* | 
 | 72 | 	 * According to the ACPI specification 2.0c and later, the 64-bit | 
 | 73 | 	 * waking vector should be cleared and the 32-bit waking vector should | 
 | 74 | 	 * be used, unless we want the wake-up code to be called by the BIOS in | 
 | 75 | 	 * Protected Mode.  Some systems (for example HP dv5-1004nr) are known | 
 | 76 | 	 * to fail to resume if the 64-bit vector is used. | 
 | 77 | 	 */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 78 |  | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 79 | 	/* Set the 32-bit vector */ | 
 | 80 |  | 
| Bob Moore | 009c4cbe | 2008-11-12 15:34:52 +0800 | [diff] [blame] | 81 | 	acpi_gbl_FACS->firmware_waking_vector = physical_address; | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 82 |  | 
 | 83 | 	/* Clear the 64-bit vector if it exists */ | 
 | 84 |  | 
| Bob Moore | 009c4cbe | 2008-11-12 15:34:52 +0800 | [diff] [blame] | 85 | 	if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) { | 
 | 86 | 		acpi_gbl_FACS->xfirmware_waking_vector = 0; | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 87 | 	} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 88 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 89 | 	return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 90 | } | 
 | 91 |  | 
| Bob Moore | 8313524 | 2006-10-03 00:00:00 -0400 | [diff] [blame] | 92 | ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) | 
 | 93 |  | 
| Bob Moore | 4f70e37 | 2009-02-18 14:52:43 +0800 | [diff] [blame] | 94 | #if ACPI_MACHINE_WIDTH == 64 | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 95 | /******************************************************************************* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 96 |  * | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 97 |  * FUNCTION:    acpi_set_firmware_waking_vector64 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 |  * | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 99 |  * PARAMETERS:  physical_address    - 64-bit physical address of ACPI protected | 
 | 100 |  *                                    mode entry point. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 101 |  * | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 102 |  * RETURN:      Status | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 103 |  * | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 104 |  * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if | 
| Bob Moore | 4f70e37 | 2009-02-18 14:52:43 +0800 | [diff] [blame] | 105 |  *              it exists in the table. This function is intended for use with | 
 | 106 |  *              64-bit host operating systems. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 107 |  * | 
 | 108 |  ******************************************************************************/ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 109 | acpi_status | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 110 | acpi_set_firmware_waking_vector64(u64 physical_address) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 111 | { | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 112 | 	ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 113 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 114 |  | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 115 | 	/* Determine if the 64-bit vector actually exists */ | 
 | 116 |  | 
| Bob Moore | 009c4cbe | 2008-11-12 15:34:52 +0800 | [diff] [blame] | 117 | 	if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) { | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 118 | 		return_ACPI_STATUS(AE_NOT_EXIST); | 
 | 119 | 	} | 
 | 120 |  | 
 | 121 | 	/* Clear 32-bit vector, set the 64-bit X_ vector */ | 
 | 122 |  | 
| Bob Moore | 009c4cbe | 2008-11-12 15:34:52 +0800 | [diff] [blame] | 123 | 	acpi_gbl_FACS->firmware_waking_vector = 0; | 
 | 124 | 	acpi_gbl_FACS->xfirmware_waking_vector = physical_address; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 125 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 126 | 	return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 127 | } | 
| Bob Moore | 8313524 | 2006-10-03 00:00:00 -0400 | [diff] [blame] | 128 |  | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 129 | ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) | 
| Bob Moore | 4f70e37 | 2009-02-18 14:52:43 +0800 | [diff] [blame] | 130 | #endif | 
| Bob Moore | d85988f | 2008-11-12 14:54:05 +0800 | [diff] [blame] | 131 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 132 | /******************************************************************************* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 133 |  * | 
 | 134 |  * FUNCTION:    acpi_enter_sleep_state_prep | 
 | 135 |  * | 
 | 136 |  * PARAMETERS:  sleep_state         - Which sleep state to enter | 
 | 137 |  * | 
 | 138 |  * RETURN:      Status | 
 | 139 |  * | 
 | 140 |  * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) | 
 | 141 |  *              This function must execute with interrupts enabled. | 
 | 142 |  *              We break sleeping into 2 stages so that OSPM can handle | 
 | 143 |  *              various OS-specific tasks between the two steps. | 
 | 144 |  * | 
 | 145 |  ******************************************************************************/ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 146 | acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 147 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 148 | 	acpi_status status; | 
 | 149 | 	struct acpi_object_list arg_list; | 
 | 150 | 	union acpi_object arg; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 151 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 152 | 	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 153 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 154 | 	/* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ | 
 | 155 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 156 | 	status = acpi_get_sleep_type_data(sleep_state, | 
 | 157 | 					  &acpi_gbl_sleep_type_a, | 
 | 158 | 					  &acpi_gbl_sleep_type_b); | 
 | 159 | 	if (ACPI_FAILURE(status)) { | 
 | 160 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 161 | 	} | 
 | 162 |  | 
 | 163 | 	/* Setup parameter object */ | 
 | 164 |  | 
 | 165 | 	arg_list.count = 1; | 
 | 166 | 	arg_list.pointer = &arg; | 
 | 167 |  | 
 | 168 | 	arg.type = ACPI_TYPE_INTEGER; | 
 | 169 | 	arg.integer.value = sleep_state; | 
 | 170 |  | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 171 | 	/* Run the _PTS method */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 172 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 173 | 	status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); | 
 | 174 | 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 
 | 175 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 176 | 	} | 
 | 177 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 178 | 	/* Setup the argument to _SST */ | 
 | 179 |  | 
 | 180 | 	switch (sleep_state) { | 
 | 181 | 	case ACPI_STATE_S0: | 
 | 182 | 		arg.integer.value = ACPI_SST_WORKING; | 
 | 183 | 		break; | 
 | 184 |  | 
 | 185 | 	case ACPI_STATE_S1: | 
 | 186 | 	case ACPI_STATE_S2: | 
 | 187 | 	case ACPI_STATE_S3: | 
 | 188 | 		arg.integer.value = ACPI_SST_SLEEPING; | 
 | 189 | 		break; | 
 | 190 |  | 
 | 191 | 	case ACPI_STATE_S4: | 
 | 192 | 		arg.integer.value = ACPI_SST_SLEEP_CONTEXT; | 
 | 193 | 		break; | 
 | 194 |  | 
 | 195 | 	default: | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 196 | 		arg.integer.value = ACPI_SST_INDICATOR_OFF;	/* Default is off */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 197 | 		break; | 
 | 198 | 	} | 
 | 199 |  | 
| Bob Moore | d52c79a | 2008-06-10 14:26:57 +0800 | [diff] [blame] | 200 | 	/* | 
 | 201 | 	 * Set the system indicators to show the desired sleep state. | 
 | 202 | 	 * _SST is an optional method (return no error if not found) | 
 | 203 | 	 */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 204 | 	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); | 
 | 205 | 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 206 | 		ACPI_EXCEPTION((AE_INFO, status, | 
 | 207 | 				"While executing method _SST")); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 208 | 	} | 
 | 209 |  | 
| Bob Moore | d52c79a | 2008-06-10 14:26:57 +0800 | [diff] [blame] | 210 | 	return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 211 | } | 
 | 212 |  | 
| Bob Moore | 8313524 | 2006-10-03 00:00:00 -0400 | [diff] [blame] | 213 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) | 
 | 214 |  | 
| Len Brown | 96f15ef | 2009-04-17 23:32:20 -0400 | [diff] [blame] | 215 | static unsigned int gts, bfs; | 
 | 216 | module_param(gts, uint, 0644); | 
 | 217 | module_param(bfs, uint, 0644); | 
 | 218 | MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); | 
 | 219 | MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); | 
 | 220 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 221 | /******************************************************************************* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 222 |  * | 
 | 223 |  * FUNCTION:    acpi_enter_sleep_state | 
 | 224 |  * | 
 | 225 |  * PARAMETERS:  sleep_state         - Which sleep state to enter | 
 | 226 |  * | 
 | 227 |  * RETURN:      Status | 
 | 228 |  * | 
 | 229 |  * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) | 
 | 230 |  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED | 
 | 231 |  * | 
 | 232 |  ******************************************************************************/ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 233 | acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 234 | { | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 235 | 	u32 pm1a_control; | 
 | 236 | 	u32 pm1b_control; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 237 | 	struct acpi_bit_register_info *sleep_type_reg_info; | 
 | 238 | 	struct acpi_bit_register_info *sleep_enable_reg_info; | 
 | 239 | 	u32 in_value; | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 240 | 	struct acpi_object_list arg_list; | 
 | 241 | 	union acpi_object arg; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 242 | 	acpi_status status; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 243 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 244 | 	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 245 |  | 
 | 246 | 	if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 247 | 	    (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { | 
| Bob Moore | f6a22b0 | 2010-03-05 17:56:40 +0800 | [diff] [blame] | 248 | 		ACPI_ERROR((AE_INFO, "Sleep values out of range: A=0x%X B=0x%X", | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 249 | 			    acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 250 | 		return_ACPI_STATUS(AE_AML_OPERAND_VALUE); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 251 | 	} | 
 | 252 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 253 | 	sleep_type_reg_info = | 
| Bob Moore | 82d79b8 | 2009-02-18 14:31:05 +0800 | [diff] [blame] | 254 | 	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 255 | 	sleep_enable_reg_info = | 
 | 256 | 	    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 257 |  | 
 | 258 | 	/* Clear wake status */ | 
 | 259 |  | 
| Bob Moore | 768aaaf | 2009-03-06 09:49:25 +0800 | [diff] [blame] | 260 | 	status = | 
 | 261 | 	    acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 262 | 	if (ACPI_FAILURE(status)) { | 
 | 263 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 264 | 	} | 
 | 265 |  | 
 | 266 | 	/* Clear all fixed and general purpose status bits */ | 
 | 267 |  | 
| Bob Moore | d8c71b6 | 2007-02-02 19:48:21 +0300 | [diff] [blame] | 268 | 	status = acpi_hw_clear_acpi_status(); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 269 | 	if (ACPI_FAILURE(status)) { | 
 | 270 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 271 | 	} | 
 | 272 |  | 
 | 273 | 	/* | 
| Pavel Machek | 23b168d | 2008-02-05 19:27:12 +0100 | [diff] [blame] | 274 | 	 * 1) Disable/Clear all GPEs | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 275 | 	 * 2) Enable all wakeup GPEs | 
 | 276 | 	 */ | 
| Alexey Starikovskiy | 1d99967 | 2007-03-12 14:49:26 -0400 | [diff] [blame] | 277 | 	status = acpi_hw_disable_all_gpes(); | 
 | 278 | 	if (ACPI_FAILURE(status)) { | 
 | 279 | 		return_ACPI_STATUS(status); | 
 | 280 | 	} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 281 | 	acpi_gbl_system_awake_and_running = FALSE; | 
 | 282 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 283 | 	status = acpi_hw_enable_all_wakeup_gpes(); | 
 | 284 | 	if (ACPI_FAILURE(status)) { | 
 | 285 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 286 | 	} | 
 | 287 |  | 
| Len Brown | 96f15ef | 2009-04-17 23:32:20 -0400 | [diff] [blame] | 288 | 	if (gts) { | 
 | 289 | 		/* Execute the _GTS method */ | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 290 |  | 
| Len Brown | 96f15ef | 2009-04-17 23:32:20 -0400 | [diff] [blame] | 291 | 		arg_list.count = 1; | 
 | 292 | 		arg_list.pointer = &arg; | 
 | 293 | 		arg.type = ACPI_TYPE_INTEGER; | 
 | 294 | 		arg.integer.value = sleep_state; | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 295 |  | 
| Len Brown | 96f15ef | 2009-04-17 23:32:20 -0400 | [diff] [blame] | 296 | 		status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); | 
 | 297 | 		if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 
 | 298 | 			return_ACPI_STATUS(status); | 
 | 299 | 		} | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 300 | 	} | 
 | 301 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 302 | 	/* Get current value of PM1A control */ | 
 | 303 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 304 | 	status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, | 
 | 305 | 				       &pm1a_control); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 306 | 	if (ACPI_FAILURE(status)) { | 
 | 307 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 308 | 	} | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 309 | 	ACPI_DEBUG_PRINT((ACPI_DB_INIT, | 
| Bob Moore | b27d659 | 2010-05-26 11:47:13 +0800 | [diff] [blame] | 310 | 			  "Entering sleep state [S%u]\n", sleep_state)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 311 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 312 | 	/* Clear the SLP_EN and SLP_TYP fields */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 313 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 314 | 	pm1a_control &= ~(sleep_type_reg_info->access_bit_mask | | 
 | 315 | 			  sleep_enable_reg_info->access_bit_mask); | 
 | 316 | 	pm1b_control = pm1a_control; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 317 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 318 | 	/* Insert the SLP_TYP bits */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 319 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 320 | 	pm1a_control |= | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 321 | 	    (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 322 | 	pm1b_control |= | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 323 | 	    (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 324 |  | 
 | 325 | 	/* | 
 | 326 | 	 * We split the writes of SLP_TYP and SLP_EN to workaround | 
 | 327 | 	 * poorly implemented hardware. | 
 | 328 | 	 */ | 
 | 329 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 330 | 	/* Write #1: write the SLP_TYP data to the PM1 Control registers */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 331 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 332 | 	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 333 | 	if (ACPI_FAILURE(status)) { | 
 | 334 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 335 | 	} | 
 | 336 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 337 | 	/* Insert the sleep enable (SLP_EN) bit */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 338 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 339 | 	pm1a_control |= sleep_enable_reg_info->access_bit_mask; | 
 | 340 | 	pm1b_control |= sleep_enable_reg_info->access_bit_mask; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 341 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 342 | 	/* Flush caches, as per ACPI specification */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 343 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 344 | 	ACPI_FLUSH_CPU_CACHE(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 345 |  | 
| Joseph Cihula | 86886e5 | 2009-06-30 19:31:07 -0700 | [diff] [blame] | 346 | 	tboot_sleep(sleep_state, pm1a_control, pm1b_control); | 
 | 347 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 348 | 	/* Write #2: Write both SLP_TYP + SLP_EN */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 349 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 350 | 	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 351 | 	if (ACPI_FAILURE(status)) { | 
 | 352 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 353 | 	} | 
 | 354 |  | 
 | 355 | 	if (sleep_state > ACPI_STATE_S3) { | 
 | 356 | 		/* | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 357 | 		 * We wanted to sleep > S3, but it didn't happen (by virtue of the | 
 | 358 | 		 * fact that we are still executing!) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 359 | 		 * | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 360 | 		 * Wait ten seconds, then try again. This is to get S4/S5 to work on | 
 | 361 | 		 * all machines. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 362 | 		 * | 
| Bob Moore | d4913dc | 2009-03-06 10:05:18 +0800 | [diff] [blame] | 363 | 		 * We wait so long to allow chipsets that poll this reg very slowly | 
 | 364 | 		 * to still read the right value. Ideally, this block would go | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 365 | 		 * away entirely. | 
 | 366 | 		 */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 367 | 		acpi_os_stall(10000000); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 368 |  | 
| Alexey Starikovskiy | d30dc9ab | 2007-09-30 22:39:36 +0400 | [diff] [blame] | 369 | 		status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 370 | 						sleep_enable_reg_info-> | 
 | 371 | 						access_bit_mask); | 
 | 372 | 		if (ACPI_FAILURE(status)) { | 
 | 373 | 			return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 374 | 		} | 
 | 375 | 	} | 
 | 376 |  | 
 | 377 | 	/* Wait until we enter sleep state */ | 
 | 378 |  | 
 | 379 | 	do { | 
| Bob Moore | 50ffba1 | 2009-02-23 15:02:07 +0800 | [diff] [blame] | 380 | 		status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, | 
| Alexey Starikovskiy | 2d571b3 | 2007-09-30 22:39:42 +0400 | [diff] [blame] | 381 | 						    &in_value); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 382 | 		if (ACPI_FAILURE(status)) { | 
 | 383 | 			return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 384 | 		} | 
 | 385 |  | 
 | 386 | 		/* Spin until we wake */ | 
 | 387 |  | 
 | 388 | 	} while (!in_value); | 
 | 389 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 390 | 	return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 391 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 392 |  | 
| Bob Moore | 8313524 | 2006-10-03 00:00:00 -0400 | [diff] [blame] | 393 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 394 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 395 | /******************************************************************************* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 396 |  * | 
 | 397 |  * FUNCTION:    acpi_enter_sleep_state_s4bios | 
 | 398 |  * | 
 | 399 |  * PARAMETERS:  None | 
 | 400 |  * | 
 | 401 |  * RETURN:      Status | 
 | 402 |  * | 
 | 403 |  * DESCRIPTION: Perform a S4 bios request. | 
 | 404 |  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED | 
 | 405 |  * | 
 | 406 |  ******************************************************************************/ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 407 | acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 408 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 409 | 	u32 in_value; | 
 | 410 | 	acpi_status status; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 411 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 412 | 	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 413 |  | 
| Bob Moore | 768aaaf | 2009-03-06 09:49:25 +0800 | [diff] [blame] | 414 | 	/* Clear the wake status bit (PM1) */ | 
 | 415 |  | 
 | 416 | 	status = | 
 | 417 | 	    acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 418 | 	if (ACPI_FAILURE(status)) { | 
 | 419 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 420 | 	} | 
 | 421 |  | 
| Bob Moore | d8c71b6 | 2007-02-02 19:48:21 +0300 | [diff] [blame] | 422 | 	status = acpi_hw_clear_acpi_status(); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 423 | 	if (ACPI_FAILURE(status)) { | 
 | 424 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 425 | 	} | 
 | 426 |  | 
 | 427 | 	/* | 
 | 428 | 	 * 1) Disable/Clear all GPEs | 
 | 429 | 	 * 2) Enable all wakeup GPEs | 
 | 430 | 	 */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 431 | 	status = acpi_hw_disable_all_gpes(); | 
 | 432 | 	if (ACPI_FAILURE(status)) { | 
 | 433 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 434 | 	} | 
 | 435 | 	acpi_gbl_system_awake_and_running = FALSE; | 
 | 436 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 437 | 	status = acpi_hw_enable_all_wakeup_gpes(); | 
 | 438 | 	if (ACPI_FAILURE(status)) { | 
 | 439 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 440 | 	} | 
 | 441 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 442 | 	ACPI_FLUSH_CPU_CACHE(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 443 |  | 
| Bob Moore | 7f07190 | 2009-03-19 09:37:47 +0800 | [diff] [blame] | 444 | 	status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, | 
| Bob Moore | f3d2e78 | 2007-02-02 19:48:18 +0300 | [diff] [blame] | 445 | 				    (u32) acpi_gbl_FADT.S4bios_request, 8); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 446 |  | 
 | 447 | 	do { | 
 | 448 | 		acpi_os_stall(1000); | 
| Bob Moore | 50ffba1 | 2009-02-23 15:02:07 +0800 | [diff] [blame] | 449 | 		status = | 
 | 450 | 		    acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 451 | 		if (ACPI_FAILURE(status)) { | 
 | 452 | 			return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 453 | 		} | 
 | 454 | 	} while (!in_value); | 
 | 455 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 456 | 	return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 457 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 458 |  | 
| Bob Moore | 8313524 | 2006-10-03 00:00:00 -0400 | [diff] [blame] | 459 | ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 460 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 461 | /******************************************************************************* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 462 |  * | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 463 |  * FUNCTION:    acpi_leave_sleep_state_prep | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 464 |  * | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 465 |  * PARAMETERS:  sleep_state         - Which sleep state we are exiting | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 466 |  * | 
 | 467 |  * RETURN:      Status | 
 | 468 |  * | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 469 |  * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a | 
 | 470 |  *              sleep. | 
 | 471 |  *              Called with interrupts DISABLED. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 472 |  * | 
 | 473 |  ******************************************************************************/ | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 474 | acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 475 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 476 | 	struct acpi_object_list arg_list; | 
 | 477 | 	union acpi_object arg; | 
 | 478 | 	acpi_status status; | 
 | 479 | 	struct acpi_bit_register_info *sleep_type_reg_info; | 
 | 480 | 	struct acpi_bit_register_info *sleep_enable_reg_info; | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 481 | 	u32 pm1a_control; | 
 | 482 | 	u32 pm1b_control; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 483 |  | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 484 | 	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 485 |  | 
 | 486 | 	/* | 
 | 487 | 	 * Set SLP_TYPE and SLP_EN to state S0. | 
 | 488 | 	 * This is unclear from the ACPI Spec, but it is required | 
 | 489 | 	 * by some machines. | 
 | 490 | 	 */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 491 | 	status = acpi_get_sleep_type_data(ACPI_STATE_S0, | 
 | 492 | 					  &acpi_gbl_sleep_type_a, | 
 | 493 | 					  &acpi_gbl_sleep_type_b); | 
 | 494 | 	if (ACPI_SUCCESS(status)) { | 
 | 495 | 		sleep_type_reg_info = | 
| Bob Moore | 82d79b8 | 2009-02-18 14:31:05 +0800 | [diff] [blame] | 496 | 		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 497 | 		sleep_enable_reg_info = | 
 | 498 | 		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 499 |  | 
 | 500 | 		/* Get current value of PM1A control */ | 
 | 501 |  | 
| Alexey Starikovskiy | d30dc9ab | 2007-09-30 22:39:36 +0400 | [diff] [blame] | 502 | 		status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 503 | 					       &pm1a_control); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 504 | 		if (ACPI_SUCCESS(status)) { | 
| Bob Moore | 52fc0b0 | 2006-10-02 00:00:00 -0400 | [diff] [blame] | 505 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 506 | 			/* Clear the SLP_EN and SLP_TYP fields */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 507 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 508 | 			pm1a_control &= ~(sleep_type_reg_info->access_bit_mask | | 
 | 509 | 					  sleep_enable_reg_info-> | 
 | 510 | 					  access_bit_mask); | 
 | 511 | 			pm1b_control = pm1a_control; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 512 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 513 | 			/* Insert the SLP_TYP bits */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 514 |  | 
| Bob Moore | d4913dc | 2009-03-06 10:05:18 +0800 | [diff] [blame] | 515 | 			pm1a_control |= (acpi_gbl_sleep_type_a << | 
 | 516 | 					 sleep_type_reg_info->bit_position); | 
 | 517 | 			pm1b_control |= (acpi_gbl_sleep_type_b << | 
 | 518 | 					 sleep_type_reg_info->bit_position); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 519 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 520 | 			/* Write the control registers and ignore any errors */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 521 |  | 
| Bob Moore | 32c9ef9 | 2009-02-18 14:36:05 +0800 | [diff] [blame] | 522 | 			(void)acpi_hw_write_pm1_control(pm1a_control, | 
 | 523 | 							pm1b_control); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 524 | 		} | 
 | 525 | 	} | 
 | 526 |  | 
| Len Brown | 96f15ef | 2009-04-17 23:32:20 -0400 | [diff] [blame] | 527 | 	if (bfs) { | 
 | 528 | 		/* Execute the _BFS method */ | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 529 |  | 
| Len Brown | 96f15ef | 2009-04-17 23:32:20 -0400 | [diff] [blame] | 530 | 		arg_list.count = 1; | 
 | 531 | 		arg_list.pointer = &arg; | 
 | 532 | 		arg.type = ACPI_TYPE_INTEGER; | 
 | 533 | 		arg.integer.value = sleep_state; | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 534 |  | 
| Len Brown | 96f15ef | 2009-04-17 23:32:20 -0400 | [diff] [blame] | 535 | 		status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); | 
 | 536 | 		if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 
 | 537 | 			ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); | 
 | 538 | 		} | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 539 | 	} | 
| Rafael J. Wysocki | c95d47a | 2008-01-08 00:05:21 +0100 | [diff] [blame] | 540 | 	return_ACPI_STATUS(status); | 
 | 541 | } | 
 | 542 |  | 
 | 543 | /******************************************************************************* | 
 | 544 |  * | 
 | 545 |  * FUNCTION:    acpi_leave_sleep_state | 
 | 546 |  * | 
 | 547 |  * PARAMETERS:  sleep_state         - Which sleep state we just exited | 
 | 548 |  * | 
 | 549 |  * RETURN:      Status | 
 | 550 |  * | 
 | 551 |  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep | 
 | 552 |  *              Called with interrupts ENABLED. | 
 | 553 |  * | 
 | 554 |  ******************************************************************************/ | 
 | 555 | acpi_status acpi_leave_sleep_state(u8 sleep_state) | 
 | 556 | { | 
 | 557 | 	struct acpi_object_list arg_list; | 
 | 558 | 	union acpi_object arg; | 
 | 559 | 	acpi_status status; | 
 | 560 |  | 
 | 561 | 	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); | 
 | 562 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 563 | 	/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ | 
 | 564 |  | 
 | 565 | 	acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; | 
 | 566 |  | 
 | 567 | 	/* Setup parameter object */ | 
 | 568 |  | 
 | 569 | 	arg_list.count = 1; | 
 | 570 | 	arg_list.pointer = &arg; | 
 | 571 | 	arg.type = ACPI_TYPE_INTEGER; | 
 | 572 |  | 
 | 573 | 	/* Ignore any errors from these methods */ | 
 | 574 |  | 
 | 575 | 	arg.integer.value = ACPI_SST_WAKING; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 576 | 	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); | 
 | 577 | 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 578 | 		ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 579 | 	} | 
 | 580 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 581 | 	/* | 
| Thomas Renninger | 79d2dfa | 2007-08-24 01:24:47 -0400 | [diff] [blame] | 582 | 	 * GPEs must be enabled before _WAK is called as GPEs | 
 | 583 | 	 * might get fired there | 
 | 584 | 	 * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 585 | 	 * Restore the GPEs: | 
 | 586 | 	 * 1) Disable/Clear all GPEs | 
 | 587 | 	 * 2) Enable all runtime GPEs | 
 | 588 | 	 */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 589 | 	status = acpi_hw_disable_all_gpes(); | 
 | 590 | 	if (ACPI_FAILURE(status)) { | 
 | 591 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 592 | 	} | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 593 | 	status = acpi_hw_enable_all_runtime_gpes(); | 
 | 594 | 	if (ACPI_FAILURE(status)) { | 
 | 595 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 596 | 	} | 
 | 597 |  | 
| Rafael J. Wysocki | 314ccd6 | 2008-02-13 00:32:16 +0100 | [diff] [blame] | 598 | 	arg.integer.value = sleep_state; | 
| Thomas Renninger | 79d2dfa | 2007-08-24 01:24:47 -0400 | [diff] [blame] | 599 | 	status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); | 
 | 600 | 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 
 | 601 | 		ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); | 
 | 602 | 	} | 
 | 603 | 	/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ | 
 | 604 |  | 
| Matthew Garrett | a68823e | 2008-08-06 19:12:04 +0100 | [diff] [blame] | 605 | 	/* | 
 | 606 | 	 * Some BIOSes assume that WAK_STS will be cleared on resume and use | 
 | 607 | 	 * it to determine whether the system is rebooting or resuming. Clear | 
 | 608 | 	 * it for compatibility. | 
 | 609 | 	 */ | 
| Bob Moore | 50ffba1 | 2009-02-23 15:02:07 +0800 | [diff] [blame] | 610 | 	acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); | 
| Matthew Garrett | a68823e | 2008-08-06 19:12:04 +0100 | [diff] [blame] | 611 |  | 
| Thomas Renninger | 79d2dfa | 2007-08-24 01:24:47 -0400 | [diff] [blame] | 612 | 	acpi_gbl_system_awake_and_running = TRUE; | 
 | 613 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 614 | 	/* Enable power button */ | 
 | 615 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 616 | 	(void) | 
| Bob Moore | 50ffba1 | 2009-02-23 15:02:07 +0800 | [diff] [blame] | 617 | 	    acpi_write_bit_register(acpi_gbl_fixed_event_info | 
| Bob Moore | 768aaaf | 2009-03-06 09:49:25 +0800 | [diff] [blame] | 618 | 			      [ACPI_EVENT_POWER_BUTTON]. | 
 | 619 | 			      enable_register_id, ACPI_ENABLE_EVENT); | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 620 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 621 | 	(void) | 
| Bob Moore | 50ffba1 | 2009-02-23 15:02:07 +0800 | [diff] [blame] | 622 | 	    acpi_write_bit_register(acpi_gbl_fixed_event_info | 
| Bob Moore | 768aaaf | 2009-03-06 09:49:25 +0800 | [diff] [blame] | 623 | 			      [ACPI_EVENT_POWER_BUTTON]. | 
 | 624 | 			      status_register_id, ACPI_CLEAR_STATUS); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 625 |  | 
 | 626 | 	arg.integer.value = ACPI_SST_WORKING; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 627 | 	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); | 
 | 628 | 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 629 | 		ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 630 | 	} | 
 | 631 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 632 | 	return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 633 | } | 
| Bob Moore | 8313524 | 2006-10-03 00:00:00 -0400 | [diff] [blame] | 634 |  | 
 | 635 | ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) |