Linux-2.6.12-rc2
[pandora-kernel.git] / drivers / acpi / sleep / wakeup.c
1 /*
2  * wakeup.c - support wakeup devices
3  * Copyright (C) 2004 Li Shaohua <shaohua.li@intel.com>
4  */
5
6 #include <linux/init.h>
7 #include <linux/acpi.h>
8 #include <acpi/acpi_drivers.h>
9 #include <linux/kernel.h>
10 #include <linux/types.h>
11 #include <acpi/acevents.h>
12 #include "sleep.h"
13
14 #define _COMPONENT              ACPI_SYSTEM_COMPONENT
15 ACPI_MODULE_NAME                ("wakeup_devices")
16
17 extern struct list_head acpi_wakeup_device_list;
18 extern spinlock_t acpi_device_lock;
19
20 #ifdef CONFIG_ACPI_SLEEP
21 /**
22  * acpi_enable_wakeup_device_prep - prepare wakeup devices
23  *      @sleep_state:   ACPI state
24  * Enable all wakup devices power if the devices' wakeup level
25  * is higher than requested sleep level
26  */
27
28 void
29 acpi_enable_wakeup_device_prep(
30         u8              sleep_state)
31 {
32         struct list_head * node, * next;
33
34         ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
35
36         spin_lock(&acpi_device_lock);
37         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
38                 struct acpi_device * dev = container_of(node, 
39                         struct acpi_device, wakeup_list);
40                 
41                 if (!dev->wakeup.flags.valid || 
42                         !dev->wakeup.state.enabled ||
43                         (sleep_state > (u32) dev->wakeup.sleep_state))
44                         continue;
45
46                 spin_unlock(&acpi_device_lock);
47                 acpi_enable_wakeup_device_power(dev);
48                 spin_lock(&acpi_device_lock);
49         }
50         spin_unlock(&acpi_device_lock);
51 }
52
53 /**
54  * acpi_enable_wakeup_device - enable wakeup devices
55  *      @sleep_state:   ACPI state
56  * Enable all wakup devices's GPE
57  */
58 void
59 acpi_enable_wakeup_device(
60         u8              sleep_state)
61 {
62         struct list_head * node, * next;
63
64         /* 
65          * Caution: this routine must be invoked when interrupt is disabled 
66          * Refer ACPI2.0: P212
67          */
68         ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
69         spin_lock(&acpi_device_lock);
70         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
71                 struct acpi_device * dev = container_of(node, 
72                         struct acpi_device, wakeup_list);
73
74                 /* If users want to disable run-wake GPE,
75                  * we only disable it for wake and leave it for runtime
76                  */
77                 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
78                         spin_unlock(&acpi_device_lock);
79                         acpi_set_gpe_type(dev->wakeup.gpe_device, 
80                                 dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
81                         /* Re-enable it, since set_gpe_type will disable it */
82                         acpi_enable_gpe(dev->wakeup.gpe_device, 
83                                 dev->wakeup.gpe_number, ACPI_ISR);
84                         spin_lock(&acpi_device_lock);
85                         continue;
86                 }
87
88                 if (!dev->wakeup.flags.valid ||
89                         !dev->wakeup.state.enabled ||
90                         (sleep_state > (u32) dev->wakeup.sleep_state))
91                         continue;
92
93                 spin_unlock(&acpi_device_lock);
94                 /* run-wake GPE has been enabled */
95                 if (!dev->wakeup.flags.run_wake)
96                         acpi_enable_gpe(dev->wakeup.gpe_device, 
97                                 dev->wakeup.gpe_number, ACPI_ISR);
98                 dev->wakeup.state.active = 1;
99                 spin_lock(&acpi_device_lock);
100         }
101         spin_unlock(&acpi_device_lock);
102 }
103
104 /**
105  * acpi_disable_wakeup_device - disable devices' wakeup capability
106  *      @sleep_state:   ACPI state
107  * Disable all wakup devices's GPE and wakeup capability
108  */
109 void
110 acpi_disable_wakeup_device (
111         u8              sleep_state)
112 {
113         struct list_head * node, * next;
114
115         ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
116
117         spin_lock(&acpi_device_lock);
118         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
119                 struct acpi_device * dev = container_of(node, 
120                         struct acpi_device, wakeup_list);
121
122                 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
123                         spin_unlock(&acpi_device_lock);
124                         acpi_set_gpe_type(dev->wakeup.gpe_device, 
125                                 dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
126                         /* Re-enable it, since set_gpe_type will disable it */
127                         acpi_enable_gpe(dev->wakeup.gpe_device, 
128                                 dev->wakeup.gpe_number, ACPI_NOT_ISR);
129                         spin_lock(&acpi_device_lock);
130                         continue;
131                 }
132
133                 if (!dev->wakeup.flags.valid || 
134                         !dev->wakeup.state.active ||
135                         (sleep_state > (u32) dev->wakeup.sleep_state))
136                         continue;
137
138                 spin_unlock(&acpi_device_lock);
139                 acpi_disable_wakeup_device_power(dev);
140                 /* Never disable run-wake GPE */
141                 if (!dev->wakeup.flags.run_wake) {
142                         acpi_disable_gpe(dev->wakeup.gpe_device, 
143                                 dev->wakeup.gpe_number, ACPI_NOT_ISR);
144                         acpi_clear_gpe(dev->wakeup.gpe_device, 
145                                 dev->wakeup.gpe_number, ACPI_NOT_ISR);
146                 }
147                 dev->wakeup.state.active = 0;
148                 spin_lock(&acpi_device_lock);
149         }
150         spin_unlock(&acpi_device_lock);
151 }
152
153 static int __init acpi_wakeup_device_init(void)
154 {
155         struct list_head * node, * next;
156
157         if (acpi_disabled)
158                 return 0;
159         printk("ACPI wakeup devices: \n");
160
161         spin_lock(&acpi_device_lock);
162         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
163                 struct acpi_device * dev = container_of(node, 
164                         struct acpi_device, wakeup_list);
165                 
166                 /* In case user doesn't load button driver */
167                 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
168                         spin_unlock(&acpi_device_lock);
169                         acpi_set_gpe_type(dev->wakeup.gpe_device, 
170                                 dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
171                         acpi_enable_gpe(dev->wakeup.gpe_device, 
172                                 dev->wakeup.gpe_number, ACPI_NOT_ISR);
173                         dev->wakeup.state.enabled = 1;
174                         spin_lock(&acpi_device_lock);
175                 }
176                 printk("%4s ", dev->pnp.bus_id);
177         }
178         spin_unlock(&acpi_device_lock);
179         printk("\n");
180
181         return 0;
182 }
183
184 late_initcall(acpi_wakeup_device_init);
185 #endif
186
187 /*
188  * Disable all wakeup GPEs before power off.
189  * 
190  * Since acpi_enter_sleep_state() will disable all
191  * RUNTIME GPEs, we simply mark all GPES that
192  * are not enabled for wakeup from S5 as RUNTIME.
193  */
194 void acpi_wakeup_gpe_poweroff_prepare(void)
195 {
196         struct list_head * node, * next;
197
198         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
199                 struct acpi_device * dev = container_of(node,
200                         struct acpi_device, wakeup_list);
201
202                 /* The GPE can wakeup system from S5, don't touch it */
203                 if ((u32)dev->wakeup.sleep_state == ACPI_STATE_S5)
204                         continue;
205                 /* acpi_set_gpe_type will automatically disable GPE */
206                 acpi_set_gpe_type(dev->wakeup.gpe_device,
207                         dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
208         }
209 }