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