8bb43cae60c2e160037b31559270d1922d61ed99
[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 - 2006, 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
47 #define _COMPONENT          ACPI_HARDWARE
48 ACPI_MODULE_NAME("hwsleep")
49
50 /*******************************************************************************
51  *
52  * FUNCTION:    acpi_set_firmware_waking_vector
53  *
54  * PARAMETERS:  physical_address    - Physical address of ACPI real mode
55  *                                    entry point.
56  *
57  * RETURN:      Status
58  *
59  * DESCRIPTION: Access function for the firmware_waking_vector field in FACS
60  *
61  ******************************************************************************/
62 acpi_status
63 acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
64 {
65
66         ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
67
68         /* Set the vector */
69
70         if (acpi_gbl_common_fACS.vector_width == 32) {
71                 *(ACPI_CAST_PTR
72                   (u32, acpi_gbl_common_fACS.firmware_waking_vector))
73                     = (u32) physical_address;
74         } else {
75                 *acpi_gbl_common_fACS.firmware_waking_vector = physical_address;
76         }
77
78         return_ACPI_STATUS(AE_OK);
79 }
80
81 ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
82
83 /*******************************************************************************
84  *
85  * FUNCTION:    acpi_get_firmware_waking_vector
86  *
87  * PARAMETERS:  *physical_address   - Where the contents of
88  *                                    the firmware_waking_vector field of
89  *                                    the FACS will be returned.
90  *
91  * RETURN:      Status, vector
92  *
93  * DESCRIPTION: Access function for the firmware_waking_vector field in FACS
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
122 ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector)
123 #endif
124
125 /*******************************************************************************
126  *
127  * FUNCTION:    acpi_enter_sleep_state_prep
128  *
129  * PARAMETERS:  sleep_state         - Which sleep state to enter
130  *
131  * RETURN:      Status
132  *
133  * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
134  *              This function must execute with interrupts enabled.
135  *              We break sleeping into 2 stages so that OSPM can handle
136  *              various OS-specific tasks between the two steps.
137  *
138  ******************************************************************************/
139 acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
140 {
141         acpi_status status;
142         struct acpi_object_list arg_list;
143         union acpi_object arg;
144
145         ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);
146
147         /*
148          * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
149          */
150         status = acpi_get_sleep_type_data(sleep_state,
151                                           &acpi_gbl_sleep_type_a,
152                                           &acpi_gbl_sleep_type_b);
153         if (ACPI_FAILURE(status)) {
154                 return_ACPI_STATUS(status);
155         }
156
157         /* Setup parameter object */
158
159         arg_list.count = 1;
160         arg_list.pointer = &arg;
161
162         arg.type = ACPI_TYPE_INTEGER;
163         arg.integer.value = sleep_state;
164
165         /* Run the _PTS and _GTS methods */
166
167         status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL);
168         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
169                 return_ACPI_STATUS(status);
170         }
171
172         status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
173         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
174                 return_ACPI_STATUS(status);
175         }
176
177         /* Setup the argument to _SST */
178
179         switch (sleep_state) {
180         case ACPI_STATE_S0:
181                 arg.integer.value = ACPI_SST_WORKING;
182                 break;
183
184         case ACPI_STATE_S1:
185         case ACPI_STATE_S2:
186         case ACPI_STATE_S3:
187                 arg.integer.value = ACPI_SST_SLEEPING;
188                 break;
189
190         case ACPI_STATE_S4:
191                 arg.integer.value = ACPI_SST_SLEEP_CONTEXT;
192                 break;
193
194         default:
195                 arg.integer.value = ACPI_SST_INDICATOR_OFF;     /* Default is off */
196                 break;
197         }
198
199         /* Set the system indicators to show the desired sleep state. */
200
201         status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
202         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
203                 ACPI_EXCEPTION((AE_INFO, status,
204                                 "While executing method _SST"));
205         }
206
207         return_ACPI_STATUS(AE_OK);
208 }
209
210 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
211
212 /*******************************************************************************
213  *
214  * FUNCTION:    acpi_enter_sleep_state
215  *
216  * PARAMETERS:  sleep_state         - Which sleep state to enter
217  *
218  * RETURN:      Status
219  *
220  * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
221  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
222  *
223  ******************************************************************************/
224 acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
225 {
226         u32 PM1Acontrol;
227         u32 PM1Bcontrol;
228         struct acpi_bit_register_info *sleep_type_reg_info;
229         struct acpi_bit_register_info *sleep_enable_reg_info;
230         u32 in_value;
231         acpi_status status;
232
233         ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
234
235         if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
236             (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
237                 ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X",
238                             acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
239                 return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
240         }
241
242         sleep_type_reg_info =
243             acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
244         sleep_enable_reg_info =
245             acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
246
247         /* Clear wake status */
248
249         status =
250             acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
251         if (ACPI_FAILURE(status)) {
252                 return_ACPI_STATUS(status);
253         }
254
255         /* Clear all fixed and general purpose status bits */
256
257         status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK);
258         if (ACPI_FAILURE(status)) {
259                 return_ACPI_STATUS(status);
260         }
261
262         /*
263          * 1) Disable/Clear all GPEs
264          * 2) Enable all wakeup GPEs
265          */
266         status = acpi_hw_disable_all_gpes();
267         if (ACPI_FAILURE(status)) {
268                 return_ACPI_STATUS(status);
269         }
270         acpi_gbl_system_awake_and_running = FALSE;
271
272         status = acpi_hw_enable_all_wakeup_gpes();
273         if (ACPI_FAILURE(status)) {
274                 return_ACPI_STATUS(status);
275         }
276
277         /* Get current value of PM1A control */
278
279         status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
280                                        ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
281         if (ACPI_FAILURE(status)) {
282                 return_ACPI_STATUS(status);
283         }
284         ACPI_DEBUG_PRINT((ACPI_DB_INIT,
285                           "Entering sleep state [S%d]\n", sleep_state));
286
287         /* Clear SLP_EN and SLP_TYP fields */
288
289         PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
290                          sleep_enable_reg_info->access_bit_mask);
291         PM1Bcontrol = PM1Acontrol;
292
293         /* Insert SLP_TYP bits */
294
295         PM1Acontrol |=
296             (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
297         PM1Bcontrol |=
298             (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
299
300         /*
301          * We split the writes of SLP_TYP and SLP_EN to workaround
302          * poorly implemented hardware.
303          */
304
305         /* Write #1: fill in SLP_TYP data */
306
307         status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
308                                         ACPI_REGISTER_PM1A_CONTROL,
309                                         PM1Acontrol);
310         if (ACPI_FAILURE(status)) {
311                 return_ACPI_STATUS(status);
312         }
313
314         status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
315                                         ACPI_REGISTER_PM1B_CONTROL,
316                                         PM1Bcontrol);
317         if (ACPI_FAILURE(status)) {
318                 return_ACPI_STATUS(status);
319         }
320
321         /* Insert SLP_ENABLE bit */
322
323         PM1Acontrol |= sleep_enable_reg_info->access_bit_mask;
324         PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask;
325
326         /* Write #2: SLP_TYP + SLP_EN */
327
328         ACPI_FLUSH_CPU_CACHE();
329
330         status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
331                                         ACPI_REGISTER_PM1A_CONTROL,
332                                         PM1Acontrol);
333         if (ACPI_FAILURE(status)) {
334                 return_ACPI_STATUS(status);
335         }
336
337         status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
338                                         ACPI_REGISTER_PM1B_CONTROL,
339                                         PM1Bcontrol);
340         if (ACPI_FAILURE(status)) {
341                 return_ACPI_STATUS(status);
342         }
343
344         if (sleep_state > ACPI_STATE_S3) {
345                 /*
346                  * We wanted to sleep > S3, but it didn't happen (by virtue of the
347                  * fact that we are still executing!)
348                  *
349                  * Wait ten seconds, then try again. This is to get S4/S5 to work on
350                  * all machines.
351                  *
352                  * We wait so long to allow chipsets that poll this reg very slowly to
353                  * still read the right value. Ideally, this block would go
354                  * away entirely.
355                  */
356                 acpi_os_stall(10000000);
357
358                 status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
359                                                 ACPI_REGISTER_PM1_CONTROL,
360                                                 sleep_enable_reg_info->
361                                                 access_bit_mask);
362                 if (ACPI_FAILURE(status)) {
363                         return_ACPI_STATUS(status);
364                 }
365         }
366
367         /* Wait until we enter sleep state */
368
369         do {
370                 status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value,
371                                            ACPI_MTX_DO_NOT_LOCK);
372                 if (ACPI_FAILURE(status)) {
373                         return_ACPI_STATUS(status);
374                 }
375
376                 /* Spin until we wake */
377
378         } while (!in_value);
379
380         return_ACPI_STATUS(AE_OK);
381 }
382
383 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
384
385 /*******************************************************************************
386  *
387  * FUNCTION:    acpi_enter_sleep_state_s4bios
388  *
389  * PARAMETERS:  None
390  *
391  * RETURN:      Status
392  *
393  * DESCRIPTION: Perform a S4 bios request.
394  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
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 ACPI_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 acpi_status acpi_leave_sleep_state(u8 sleep_state)
462 {
463         struct acpi_object_list arg_list;
464         union acpi_object arg;
465         acpi_status status;
466         struct acpi_bit_register_info *sleep_type_reg_info;
467         struct acpi_bit_register_info *sleep_enable_reg_info;
468         u32 PM1Acontrol;
469         u32 PM1Bcontrol;
470
471         ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
472
473         /*
474          * Set SLP_TYPE and SLP_EN to state S0.
475          * This is unclear from the ACPI Spec, but it is required
476          * by some machines.
477          */
478         status = acpi_get_sleep_type_data(ACPI_STATE_S0,
479                                           &acpi_gbl_sleep_type_a,
480                                           &acpi_gbl_sleep_type_b);
481         if (ACPI_SUCCESS(status)) {
482                 sleep_type_reg_info =
483                     acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
484                 sleep_enable_reg_info =
485                     acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
486
487                 /* Get current value of PM1A control */
488
489                 status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
490                                                ACPI_REGISTER_PM1_CONTROL,
491                                                &PM1Acontrol);
492                 if (ACPI_SUCCESS(status)) {
493
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_EXCEPTION((AE_INFO, status, "During Method _SST"));
537         }
538
539         arg.integer.value = sleep_state;
540         status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
541         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
542                 ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
543         }
544
545         status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
546         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
547                 ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK"));
548         }
549         /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
550
551         /*
552          * Restore the GPEs:
553          * 1) Disable/Clear all GPEs
554          * 2) Enable all runtime GPEs
555          */
556         status = acpi_hw_disable_all_gpes();
557         if (ACPI_FAILURE(status)) {
558                 return_ACPI_STATUS(status);
559         }
560         acpi_gbl_system_awake_and_running = TRUE;
561
562         status = acpi_hw_enable_all_runtime_gpes();
563         if (ACPI_FAILURE(status)) {
564                 return_ACPI_STATUS(status);
565         }
566
567         /* Enable power button */
568
569         (void)
570             acpi_set_register(acpi_gbl_fixed_event_info
571                               [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1,
572                               ACPI_MTX_DO_NOT_LOCK);
573
574         (void)
575             acpi_set_register(acpi_gbl_fixed_event_info
576                               [ACPI_EVENT_POWER_BUTTON].status_register_id, 1,
577                               ACPI_MTX_DO_NOT_LOCK);
578
579         arg.integer.value = ACPI_SST_WORKING;
580         status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
581         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
582                 ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
583         }
584
585         return_ACPI_STATUS(status);
586 }
587
588 ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)