Merge branch 'topic/asoc' into for-linus
[linux-2.6] / drivers / acpi / 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 "sleep.h"
12
13 #define _COMPONENT              ACPI_SYSTEM_COMPONENT
14 ACPI_MODULE_NAME("wakeup_devices")
15
16 extern struct list_head acpi_wakeup_device_list;
17 extern spinlock_t acpi_device_lock;
18
19 /**
20  * acpi_enable_wakeup_device_prep - prepare wakeup devices
21  *      @sleep_state:   ACPI state
22  * Enable all wakup devices power if the devices' wakeup level
23  * is higher than requested sleep level
24  */
25
26 void acpi_enable_wakeup_device_prep(u8 sleep_state)
27 {
28         struct list_head *node, *next;
29
30         spin_lock(&acpi_device_lock);
31         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
32                 struct acpi_device *dev = container_of(node,
33                                                        struct acpi_device,
34                                                        wakeup_list);
35
36                 if (!dev->wakeup.flags.valid ||
37                     !dev->wakeup.state.enabled ||
38                     (sleep_state > (u32) dev->wakeup.sleep_state))
39                         continue;
40
41                 spin_unlock(&acpi_device_lock);
42                 acpi_enable_wakeup_device_power(dev, sleep_state);
43                 spin_lock(&acpi_device_lock);
44         }
45         spin_unlock(&acpi_device_lock);
46 }
47
48 /**
49  * acpi_enable_wakeup_device - enable wakeup devices
50  *      @sleep_state:   ACPI state
51  * Enable all wakup devices's GPE
52  */
53 void acpi_enable_wakeup_device(u8 sleep_state)
54 {
55         struct list_head *node, *next;
56
57         /* 
58          * Caution: this routine must be invoked when interrupt is disabled 
59          * Refer ACPI2.0: P212
60          */
61         spin_lock(&acpi_device_lock);
62         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
63                 struct acpi_device *dev =
64                         container_of(node, struct acpi_device, wakeup_list);
65
66                 if (!dev->wakeup.flags.valid)
67                         continue;
68
69                 /* If users want to disable run-wake GPE,
70                  * we only disable it for wake and leave it for runtime
71                  */
72                 if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
73                     || sleep_state > (u32) dev->wakeup.sleep_state) {
74                         if (dev->wakeup.flags.run_wake) {
75                                 spin_unlock(&acpi_device_lock);
76                                 /* set_gpe_type will disable GPE, leave it like that */
77                                 acpi_set_gpe_type(dev->wakeup.gpe_device,
78                                                   dev->wakeup.gpe_number,
79                                                   ACPI_GPE_TYPE_RUNTIME);
80                                 spin_lock(&acpi_device_lock);
81                         }
82                         continue;
83                 }
84                 spin_unlock(&acpi_device_lock);
85                 if (!dev->wakeup.flags.run_wake)
86                         acpi_enable_gpe(dev->wakeup.gpe_device,
87                                         dev->wakeup.gpe_number);
88                 spin_lock(&acpi_device_lock);
89         }
90         spin_unlock(&acpi_device_lock);
91 }
92
93 /**
94  * acpi_disable_wakeup_device - disable devices' wakeup capability
95  *      @sleep_state:   ACPI state
96  * Disable all wakup devices's GPE and wakeup capability
97  */
98 void acpi_disable_wakeup_device(u8 sleep_state)
99 {
100         struct list_head *node, *next;
101
102         spin_lock(&acpi_device_lock);
103         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
104                 struct acpi_device *dev =
105                         container_of(node, struct acpi_device, wakeup_list);
106
107                 if (!dev->wakeup.flags.valid)
108                         continue;
109
110                 if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
111                     || sleep_state > (u32) dev->wakeup.sleep_state) {
112                         if (dev->wakeup.flags.run_wake) {
113                                 spin_unlock(&acpi_device_lock);
114                                 acpi_set_gpe_type(dev->wakeup.gpe_device,
115                                                   dev->wakeup.gpe_number,
116                                                   ACPI_GPE_TYPE_WAKE_RUN);
117                                 /* Re-enable it, since set_gpe_type will disable it */
118                                 acpi_enable_gpe(dev->wakeup.gpe_device,
119                                                 dev->wakeup.gpe_number);
120                                 spin_lock(&acpi_device_lock);
121                         }
122                         continue;
123                 }
124
125                 spin_unlock(&acpi_device_lock);
126                 acpi_disable_wakeup_device_power(dev);
127                 /* Never disable run-wake GPE */
128                 if (!dev->wakeup.flags.run_wake) {
129                         acpi_disable_gpe(dev->wakeup.gpe_device,
130                                          dev->wakeup.gpe_number);
131                         acpi_clear_gpe(dev->wakeup.gpe_device,
132                                        dev->wakeup.gpe_number, ACPI_NOT_ISR);
133                 }
134                 spin_lock(&acpi_device_lock);
135         }
136         spin_unlock(&acpi_device_lock);
137 }
138
139 static int __init acpi_wakeup_device_init(void)
140 {
141         struct list_head *node, *next;
142
143         if (acpi_disabled)
144                 return 0;
145
146         spin_lock(&acpi_device_lock);
147         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
148                 struct acpi_device *dev = container_of(node,
149                                                        struct acpi_device,
150                                                        wakeup_list);
151                 /* In case user doesn't load button driver */
152                 if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
153                         continue;
154                 spin_unlock(&acpi_device_lock);
155                 acpi_set_gpe_type(dev->wakeup.gpe_device,
156                                   dev->wakeup.gpe_number,
157                                   ACPI_GPE_TYPE_WAKE_RUN);
158                 acpi_enable_gpe(dev->wakeup.gpe_device,
159                                 dev->wakeup.gpe_number);
160                 dev->wakeup.state.enabled = 1;
161                 spin_lock(&acpi_device_lock);
162         }
163         spin_unlock(&acpi_device_lock);
164         return 0;
165 }
166
167 late_initcall(acpi_wakeup_device_init);