1 2/****************************************************************************** 3 * 4 * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2007, R. Byron Moore 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/acpi.h> 46#include <acpi/actables.h> 47 48#define _COMPONENT ACPI_HARDWARE 49ACPI_MODULE_NAME("hwsleep") 50 51/******************************************************************************* 52 * 53 * FUNCTION: acpi_set_firmware_waking_vector 54 * 55 * PARAMETERS: physical_address - Physical address of ACPI real mode 56 * entry point. 57 * 58 * RETURN: Status 59 * 60 * DESCRIPTION: Access function for the firmware_waking_vector field in FACS 61 * 62 ******************************************************************************/ 63acpi_status 64acpi_set_firmware_waking_vector(acpi_physical_address physical_address) 65{ 66 struct acpi_table_facs *facs; 67 acpi_status status; 68 69 ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); 70 71 /* Get the FACS */ 72 73 status = 74 acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, 75 (struct acpi_table_header **)&facs); 76 if (ACPI_FAILURE(status)) { 77 return_ACPI_STATUS(status); 78 } 79 80 /* Set the vector */ 81 82 if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { 83 /* 84 * ACPI 1.0 FACS or short table or optional X_ field is zero 85 */ 86 facs->firmware_waking_vector = (u32) physical_address; 87 } else { 88 /* 89 * ACPI 2.0 FACS with valid X_ field 90 */ 91 facs->xfirmware_waking_vector = physical_address; 92 } 93 94 return_ACPI_STATUS(AE_OK); 95} 96 97ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) 98 99/******************************************************************************* 100 * 101 * FUNCTION: acpi_get_firmware_waking_vector 102 * 103 * PARAMETERS: *physical_address - Where the contents of 104 * the firmware_waking_vector field of 105 * the FACS will be returned. 106 * 107 * RETURN: Status, vector 108 * 109 * DESCRIPTION: Access function for the firmware_waking_vector field in FACS 110 * 111 ******************************************************************************/ 112#ifdef ACPI_FUTURE_USAGE 113acpi_status 114acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) 115{ 116 struct acpi_table_facs *facs; 117 acpi_status status; 118 119 ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector); 120 121 if (!physical_address) { 122 return_ACPI_STATUS(AE_BAD_PARAMETER); 123 } 124 125 /* Get the FACS */ 126 127 status = 128 acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, 129 (struct acpi_table_header **)&facs); 130 if (ACPI_FAILURE(status)) { 131 return_ACPI_STATUS(status); 132 } 133 134 /* Get the vector */ 135 136 if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { 137 /* 138 * ACPI 1.0 FACS or short table or optional X_ field is zero 139 */ 140 *physical_address = 141 (acpi_physical_address) facs->firmware_waking_vector; 142 } else { 143 /* 144 * ACPI 2.0 FACS with valid X_ field 145 */ 146 *physical_address = 147 (acpi_physical_address) facs->xfirmware_waking_vector; 148 } 149 150 return_ACPI_STATUS(AE_OK); 151} 152 153ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector) 154#endif 155/******************************************************************************* 156 * 157 * FUNCTION: acpi_enter_sleep_state_prep 158 * 159 * PARAMETERS: sleep_state - Which sleep state to enter 160 * 161 * RETURN: Status 162 * 163 * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) 164 * This function must execute with interrupts enabled. 165 * We break sleeping into 2 stages so that OSPM can handle 166 * various OS-specific tasks between the two steps. 167 * 168 ******************************************************************************/ 169acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) 170{ 171 acpi_status status; 172 struct acpi_object_list arg_list; 173 union acpi_object arg; 174 175 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); 176 177 /* 178 * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. 179 */ 180 status = acpi_get_sleep_type_data(sleep_state, 181 &acpi_gbl_sleep_type_a, 182 &acpi_gbl_sleep_type_b); 183 if (ACPI_FAILURE(status)) { 184 return_ACPI_STATUS(status); 185 } 186 187 /* Setup parameter object */ 188 189 arg_list.count = 1; 190 arg_list.pointer = &arg; 191 192 arg.type = ACPI_TYPE_INTEGER; 193 arg.integer.value = sleep_state; 194 195 /* Run the _PTS and _GTS methods */ 196 197 status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); 198 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 199 return_ACPI_STATUS(status); 200 } 201 202 status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); 203 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 204 return_ACPI_STATUS(status); 205 } 206 207 /* Setup the argument to _SST */ 208 209 switch (sleep_state) { 210 case ACPI_STATE_S0: 211 arg.integer.value = ACPI_SST_WORKING; 212 break; 213 214 case ACPI_STATE_S1: 215 case ACPI_STATE_S2: 216 case ACPI_STATE_S3: 217 arg.integer.value = ACPI_SST_SLEEPING; 218 break; 219 220 case ACPI_STATE_S4: 221 arg.integer.value = ACPI_SST_SLEEP_CONTEXT; 222 break; 223 224 default: 225 arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */ 226 break; 227 } 228 229 /* Set the system indicators to show the desired sleep state. */ 230 231 status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); 232 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 233 ACPI_EXCEPTION((AE_INFO, status, 234 "While executing method _SST")); 235 } 236 237 /* 238 * 1) Disable/Clear all GPEs 239 */ 240 status = acpi_hw_disable_all_gpes(); 241 if (ACPI_FAILURE(status)) { 242 return_ACPI_STATUS(status); 243 } 244 245 return_ACPI_STATUS(AE_OK); 246} 247 248ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) 249 250/******************************************************************************* 251 * 252 * FUNCTION: acpi_enter_sleep_state 253 * 254 * PARAMETERS: sleep_state - Which sleep state to enter 255 * 256 * RETURN: Status 257 * 258 * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) 259 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 260 * 261 ******************************************************************************/ 262acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) 263{ 264 u32 PM1Acontrol; 265 u32 PM1Bcontrol; 266 struct acpi_bit_register_info *sleep_type_reg_info; 267 struct acpi_bit_register_info *sleep_enable_reg_info; 268 u32 in_value; 269 acpi_status status; 270 271 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); 272 273 if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || 274 (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { 275 ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X", 276 acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); 277 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 278 } 279 280 sleep_type_reg_info = 281 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); 282 sleep_enable_reg_info = 283 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); 284 285 /* Clear wake status */ 286 287 status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); 288 if (ACPI_FAILURE(status)) { 289 return_ACPI_STATUS(status); 290 } 291 292 /* Clear all fixed and general purpose status bits */ 293 294 status = acpi_hw_clear_acpi_status(); 295 if (ACPI_FAILURE(status)) { 296 return_ACPI_STATUS(status); 297 } 298 299 /* 300 * 2) Enable all wakeup GPEs 301 */ 302 status = acpi_hw_disable_all_gpes(); 303 if (ACPI_FAILURE(status)) { 304 return_ACPI_STATUS(status); 305 } 306 307 acpi_gbl_system_awake_and_running = FALSE; 308 309 status = acpi_hw_enable_all_wakeup_gpes(); 310 if (ACPI_FAILURE(status)) { 311 return_ACPI_STATUS(status); 312 } 313 314 /* Get current value of PM1A control */ 315 316 status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, 317 ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); 318 if (ACPI_FAILURE(status)) { 319 return_ACPI_STATUS(status); 320 } 321 ACPI_DEBUG_PRINT((ACPI_DB_INIT, 322 "Entering sleep state [S%d]\n", sleep_state)); 323 324 /* Clear SLP_EN and SLP_TYP fields */ 325 326 PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | 327 sleep_enable_reg_info->access_bit_mask); 328 PM1Bcontrol = PM1Acontrol; 329 330 /* Insert SLP_TYP bits */ 331 332 PM1Acontrol |= 333 (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); 334 PM1Bcontrol |= 335 (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); 336 337 338 /* Write #1: fill in SLP_TYP data */ 339 340 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, 341 ACPI_REGISTER_PM1A_CONTROL, 342 PM1Acontrol); 343 if (ACPI_FAILURE(status)) { 344 return_ACPI_STATUS(status); 345 } 346 347 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, 348 ACPI_REGISTER_PM1B_CONTROL, 349 PM1Bcontrol); 350 if (ACPI_FAILURE(status)) { 351 return_ACPI_STATUS(status); 352 } 353 354 /* Insert SLP_ENABLE bit */ 355 356 PM1Acontrol |= sleep_enable_reg_info->access_bit_mask; 357 PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; 358 359 /* Write #2: SLP_TYP + SLP_EN */ 360 361 ACPI_FLUSH_CPU_CACHE(); 362 363 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, 364 ACPI_REGISTER_PM1A_CONTROL, 365 PM1Acontrol); 366 if (ACPI_FAILURE(status)) { 367 return_ACPI_STATUS(status); 368 } 369 370 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, 371 ACPI_REGISTER_PM1B_CONTROL, 372 PM1Bcontrol); 373 if (ACPI_FAILURE(status)) { 374 return_ACPI_STATUS(status); 375 } 376 377 if (sleep_state > ACPI_STATE_S3) { 378 /* 379 * We wanted to sleep > S3, but it didn't happen (by virtue of the 380 * fact that we are still executing!) 381 * 382 * Wait ten seconds, then try again. This is to get S4/S5 to work on 383 * all machines. 384 * 385 * We wait so long to allow chipsets that poll this reg very slowly to 386 * still read the right value. Ideally, this block would go 387 * away entirely. 388 */ 389 acpi_os_stall(10000000); 390 391 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, 392 ACPI_REGISTER_PM1_CONTROL, 393 sleep_enable_reg_info-> 394 access_bit_mask); 395 if (ACPI_FAILURE(status)) { 396 return_ACPI_STATUS(status); 397 } 398 } 399 400 /* Wait until we enter sleep state */ 401 402 do { 403 status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); 404 if (ACPI_FAILURE(status)) { 405 return_ACPI_STATUS(status); 406 } 407 408 /* Spin until we wake */ 409 410 } while (!in_value); 411 412 return_ACPI_STATUS(AE_OK); 413} 414 415ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) 416 417/******************************************************************************* 418 * 419 * FUNCTION: acpi_enter_sleep_state_s4bios 420 * 421 * PARAMETERS: None 422 * 423 * RETURN: Status 424 * 425 * DESCRIPTION: Perform a S4 bios request. 426 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED 427 * 428 ******************************************************************************/ 429acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) 430{ 431 u32 in_value; 432 acpi_status status; 433 434 ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); 435 436 status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); 437 if (ACPI_FAILURE(status)) { 438 return_ACPI_STATUS(status); 439 } 440 441 status = acpi_hw_clear_acpi_status(); 442 if (ACPI_FAILURE(status)) { 443 return_ACPI_STATUS(status); 444 } 445 446 /* 447 * 1) Disable/Clear all GPEs 448 * 2) Enable all wakeup GPEs 449 */ 450 status = acpi_hw_disable_all_gpes(); 451 if (ACPI_FAILURE(status)) { 452 return_ACPI_STATUS(status); 453 } 454 acpi_gbl_system_awake_and_running = FALSE; 455 456 status = acpi_hw_enable_all_wakeup_gpes(); 457 if (ACPI_FAILURE(status)) { 458 return_ACPI_STATUS(status); 459 } 460 461 ACPI_FLUSH_CPU_CACHE(); 462 463 status = acpi_os_write_port(acpi_gbl_FADT.smi_command, 464 (u32) acpi_gbl_FADT.S4bios_request, 8); 465 466 do { 467 acpi_os_stall(1000); 468 status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); 469 if (ACPI_FAILURE(status)) { 470 return_ACPI_STATUS(status); 471 } 472 } while (!in_value); 473 474 return_ACPI_STATUS(AE_OK); 475} 476 477ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) 478 479/******************************************************************************* 480 * 481 * FUNCTION: acpi_leave_sleep_state 482 * 483 * PARAMETERS: sleep_state - Which sleep state we just exited 484 * 485 * RETURN: Status 486 * 487 * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep 488 * Called with interrupts ENABLED. 489 * 490 ******************************************************************************/ 491acpi_status acpi_leave_sleep_state(u8 sleep_state) 492{ 493 struct acpi_object_list arg_list; 494 union acpi_object arg; 495 acpi_status status; 496 struct acpi_bit_register_info *sleep_type_reg_info; 497 struct acpi_bit_register_info *sleep_enable_reg_info; 498 u32 PM1Acontrol; 499 u32 PM1Bcontrol; 500 501 ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); 502 503 /* 504 * Set SLP_TYPE and SLP_EN to state S0. 505 * This is unclear from the ACPI Spec, but it is required 506 * by some machines. 507 */ 508 status = acpi_get_sleep_type_data(ACPI_STATE_S0, 509 &acpi_gbl_sleep_type_a, 510 &acpi_gbl_sleep_type_b); 511 if (ACPI_SUCCESS(status)) { 512 sleep_type_reg_info = 513 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); 514 sleep_enable_reg_info = 515 acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); 516 517 /* Get current value of PM1A control */ 518 519 status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, 520 ACPI_REGISTER_PM1_CONTROL, 521 &PM1Acontrol); 522 if (ACPI_SUCCESS(status)) { 523 524 /* Clear SLP_EN and SLP_TYP fields */ 525 526 PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | 527 sleep_enable_reg_info-> 528 access_bit_mask); 529 PM1Bcontrol = PM1Acontrol; 530 531 /* Insert SLP_TYP bits */ 532 533 PM1Acontrol |= 534 (acpi_gbl_sleep_type_a << sleep_type_reg_info-> 535 bit_position); 536 PM1Bcontrol |= 537 (acpi_gbl_sleep_type_b << sleep_type_reg_info-> 538 bit_position); 539 540 /* Just ignore any errors */ 541 542 (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, 543 ACPI_REGISTER_PM1A_CONTROL, 544 PM1Acontrol); 545 (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, 546 ACPI_REGISTER_PM1B_CONTROL, 547 PM1Bcontrol); 548 } 549 } 550 551 /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ 552 553 acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; 554 555 /* Setup parameter object */ 556 557 arg_list.count = 1; 558 arg_list.pointer = &arg; 559 arg.type = ACPI_TYPE_INTEGER; 560 561 /* Ignore any errors from these methods */ 562 563 arg.integer.value = ACPI_SST_WAKING; 564 status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); 565 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 566 ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); 567 } 568 569 arg.integer.value = sleep_state; 570 status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); 571 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 572 ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); 573 } 574 575 status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); 576 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 577 ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); 578 } 579 /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ 580 581 /* 582 * Restore the GPEs: 583 * 1) Disable/Clear all GPEs 584 * 2) Enable all runtime GPEs 585 */ 586 status = acpi_hw_disable_all_gpes(); 587 if (ACPI_FAILURE(status)) { 588 return_ACPI_STATUS(status); 589 } 590 acpi_gbl_system_awake_and_running = TRUE; 591 592 status = acpi_hw_enable_all_runtime_gpes(); 593 if (ACPI_FAILURE(status)) { 594 return_ACPI_STATUS(status); 595 } 596 597 /* Enable power button */ 598 599 (void) 600 acpi_set_register(acpi_gbl_fixed_event_info 601 [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1); 602 603 (void) 604 acpi_set_register(acpi_gbl_fixed_event_info 605 [ACPI_EVENT_POWER_BUTTON].status_register_id, 1); 606 607 arg.integer.value = ACPI_SST_WORKING; 608 status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); 609 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 610 ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); 611 } 612 613 return_ACPI_STATUS(status); 614} 615 616ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) 617