Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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