]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * wakeup.c - support wakeup devices | |
3 | * Copyright (C) 2004 Li Shaohua <[email protected]> | |
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> | |
e60cc7a6 BH |
11 | |
12 | #include "internal.h" | |
1da177e4 LT |
13 | #include "sleep.h" |
14 | ||
9090589d SL |
15 | /* |
16 | * We didn't lock acpi_device_lock in the file, because it invokes oops in | |
17 | * suspend/resume and isn't really required as this is called in S-state. At | |
18 | * that time, there is no device hotplug | |
19 | **/ | |
1da177e4 | 20 | #define _COMPONENT ACPI_SYSTEM_COMPONENT |
4be44fcd | 21 | ACPI_MODULE_NAME("wakeup_devices") |
1da177e4 | 22 | |
1da177e4 | 23 | /** |
78f5f023 | 24 | * acpi_enable_wakeup_devices - Enable wake-up device GPEs. |
9630bdd9 RW |
25 | * @sleep_state: ACPI system sleep state. |
26 | * | |
78f5f023 RW |
27 | * Enable wakeup device power of devices with the state.enable flag set and set |
28 | * the wakeup enable mask bits in the GPE registers that correspond to wakeup | |
29 | * devices. | |
1da177e4 | 30 | */ |
78f5f023 | 31 | void acpi_enable_wakeup_devices(u8 sleep_state) |
1da177e4 | 32 | { |
4be44fcd | 33 | struct list_head *node, *next; |
1da177e4 | 34 | |
1da177e4 | 35 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
9b039330 AS |
36 | struct acpi_device *dev = |
37 | container_of(node, struct acpi_device, wakeup_list); | |
eb9d0fe4 | 38 | |
e8b6f970 | 39 | if (!dev->wakeup.flags.valid |
f2b56bc8 RW |
40 | || sleep_state > (u32) dev->wakeup.sleep_state |
41 | || !(device_may_wakeup(&dev->dev) | |
42 | || dev->wakeup.prepare_count)) | |
1da177e4 | 43 | continue; |
9630bdd9 | 44 | |
f2b56bc8 | 45 | if (device_may_wakeup(&dev->dev)) |
78f5f023 RW |
46 | acpi_enable_wakeup_device_power(dev, sleep_state); |
47 | ||
9630bdd9 | 48 | /* The wake-up power should have been enabled already. */ |
3a37898d | 49 | acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
e8b6f970 | 50 | ACPI_GPE_ENABLE); |
1da177e4 | 51 | } |
1da177e4 LT |
52 | } |
53 | ||
54 | /** | |
78f5f023 | 55 | * acpi_disable_wakeup_devices - Disable devices' wakeup capability. |
9630bdd9 | 56 | * @sleep_state: ACPI system sleep state. |
1da177e4 | 57 | */ |
78f5f023 | 58 | void acpi_disable_wakeup_devices(u8 sleep_state) |
1da177e4 | 59 | { |
4be44fcd | 60 | struct list_head *node, *next; |
1da177e4 | 61 | |
1da177e4 | 62 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
9b039330 AS |
63 | struct acpi_device *dev = |
64 | container_of(node, struct acpi_device, wakeup_list); | |
1da177e4 | 65 | |
e8b6f970 | 66 | if (!dev->wakeup.flags.valid |
f2b56bc8 RW |
67 | || sleep_state > (u32) dev->wakeup.sleep_state |
68 | || !(device_may_wakeup(&dev->dev) | |
69 | || dev->wakeup.prepare_count)) | |
1da177e4 LT |
70 | continue; |
71 | ||
3a37898d | 72 | acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
e8b6f970 RW |
73 | ACPI_GPE_DISABLE); |
74 | ||
f2b56bc8 | 75 | if (device_may_wakeup(&dev->dev)) |
e8b6f970 | 76 | acpi_disable_wakeup_device_power(dev); |
1da177e4 | 77 | } |
1da177e4 LT |
78 | } |
79 | ||
201b8c65 | 80 | int __init acpi_wakeup_device_init(void) |
1da177e4 | 81 | { |
4be44fcd | 82 | struct list_head *node, *next; |
1da177e4 | 83 | |
9090589d | 84 | mutex_lock(&acpi_device_lock); |
1da177e4 | 85 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
4be44fcd LB |
86 | struct acpi_device *dev = container_of(node, |
87 | struct acpi_device, | |
88 | wakeup_list); | |
2a5d2428 RW |
89 | if (device_can_wakeup(&dev->dev)) { |
90 | /* Button GPEs are supposed to be always enabled. */ | |
91 | acpi_enable_gpe(dev->wakeup.gpe_device, | |
92 | dev->wakeup.gpe_number); | |
f2b56bc8 | 93 | device_set_wakeup_enable(&dev->dev, true); |
2a5d2428 | 94 | } |
1da177e4 | 95 | } |
9090589d | 96 | mutex_unlock(&acpi_device_lock); |
1da177e4 LT |
97 | return 0; |
98 | } |