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