1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * wakeup.c - support wakeup devices |
4 | * Copyright (C) 2004 Li Shaohua <shaohua.li@intel.com> |
5 | */ |
6 | |
7 | #include <linux/init.h> |
8 | #include <linux/acpi.h> |
9 | #include <linux/kernel.h> |
10 | #include <linux/types.h> |
11 | |
12 | #include "internal.h" |
13 | #include "sleep.h" |
14 | |
15 | struct acpi_wakeup_handler { |
16 | struct list_head list_node; |
17 | bool (*wakeup)(void *context); |
18 | void *context; |
19 | }; |
20 | |
21 | static LIST_HEAD(acpi_wakeup_handler_head); |
22 | static DEFINE_MUTEX(acpi_wakeup_handler_mutex); |
23 | |
24 | /* |
25 | * We didn't lock acpi_device_lock in the file, because it invokes oops in |
26 | * suspend/resume and isn't really required as this is called in S-state. At |
27 | * that time, there is no device hotplug |
28 | **/ |
29 | |
30 | /** |
31 | * acpi_enable_wakeup_devices - Enable wake-up device GPEs. |
32 | * @sleep_state: ACPI system sleep state. |
33 | * |
34 | * Enable wakeup device power of devices with the state.enable flag set and set |
35 | * the wakeup enable mask bits in the GPE registers that correspond to wakeup |
36 | * devices. |
37 | */ |
38 | void acpi_enable_wakeup_devices(u8 sleep_state) |
39 | { |
40 | struct acpi_device *dev, *tmp; |
41 | |
42 | list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list, |
43 | wakeup_list) { |
44 | if (!dev->wakeup.flags.valid |
45 | || sleep_state > (u32) dev->wakeup.sleep_state |
46 | || !(device_may_wakeup(dev: &dev->dev) |
47 | || dev->wakeup.prepare_count)) |
48 | continue; |
49 | |
50 | if (device_may_wakeup(dev: &dev->dev)) |
51 | acpi_enable_wakeup_device_power(dev, state: sleep_state); |
52 | |
53 | /* The wake-up power should have been enabled already. */ |
54 | acpi_set_gpe_wake_mask(gpe_device: dev->wakeup.gpe_device, gpe_number: dev->wakeup.gpe_number, |
55 | ACPI_GPE_ENABLE); |
56 | } |
57 | } |
58 | |
59 | /** |
60 | * acpi_disable_wakeup_devices - Disable devices' wakeup capability. |
61 | * @sleep_state: ACPI system sleep state. |
62 | */ |
63 | void acpi_disable_wakeup_devices(u8 sleep_state) |
64 | { |
65 | struct acpi_device *dev, *tmp; |
66 | |
67 | list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list, |
68 | wakeup_list) { |
69 | if (!dev->wakeup.flags.valid |
70 | || sleep_state > (u32) dev->wakeup.sleep_state |
71 | || !(device_may_wakeup(dev: &dev->dev) |
72 | || dev->wakeup.prepare_count)) |
73 | continue; |
74 | |
75 | acpi_set_gpe_wake_mask(gpe_device: dev->wakeup.gpe_device, gpe_number: dev->wakeup.gpe_number, |
76 | ACPI_GPE_DISABLE); |
77 | |
78 | if (device_may_wakeup(dev: &dev->dev)) |
79 | acpi_disable_wakeup_device_power(dev); |
80 | } |
81 | } |
82 | |
83 | int __init acpi_wakeup_device_init(void) |
84 | { |
85 | struct acpi_device *dev, *tmp; |
86 | |
87 | mutex_lock(&acpi_device_lock); |
88 | list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list, |
89 | wakeup_list) { |
90 | if (device_can_wakeup(dev: &dev->dev)) { |
91 | /* Button GPEs are supposed to be always enabled. */ |
92 | acpi_enable_gpe(gpe_device: dev->wakeup.gpe_device, |
93 | gpe_number: dev->wakeup.gpe_number); |
94 | device_set_wakeup_enable(dev: &dev->dev, enable: true); |
95 | } |
96 | } |
97 | mutex_unlock(lock: &acpi_device_lock); |
98 | return 0; |
99 | } |
100 | |
101 | /** |
102 | * acpi_register_wakeup_handler - Register wakeup handler |
103 | * @wake_irq: The IRQ through which the device may receive wakeups |
104 | * @wakeup: Wakeup-handler to call when the SCI has triggered a wakeup |
105 | * @context: Context to pass to the handler when calling it |
106 | * |
107 | * Drivers which may share an IRQ with the SCI can use this to register |
108 | * a handler which returns true when the device they are managing wants |
109 | * to trigger a wakeup. |
110 | */ |
111 | int acpi_register_wakeup_handler(int wake_irq, bool (*wakeup)(void *context), |
112 | void *context) |
113 | { |
114 | struct acpi_wakeup_handler *handler; |
115 | |
116 | /* |
117 | * If the device is not sharing its IRQ with the SCI, there is no |
118 | * need to register the handler. |
119 | */ |
120 | if (!acpi_sci_irq_valid() || wake_irq != acpi_sci_irq) |
121 | return 0; |
122 | |
123 | handler = kmalloc(size: sizeof(*handler), GFP_KERNEL); |
124 | if (!handler) |
125 | return -ENOMEM; |
126 | |
127 | handler->wakeup = wakeup; |
128 | handler->context = context; |
129 | |
130 | mutex_lock(&acpi_wakeup_handler_mutex); |
131 | list_add(new: &handler->list_node, head: &acpi_wakeup_handler_head); |
132 | mutex_unlock(lock: &acpi_wakeup_handler_mutex); |
133 | |
134 | return 0; |
135 | } |
136 | EXPORT_SYMBOL_GPL(acpi_register_wakeup_handler); |
137 | |
138 | /** |
139 | * acpi_unregister_wakeup_handler - Unregister wakeup handler |
140 | * @wakeup: Wakeup-handler passed to acpi_register_wakeup_handler() |
141 | * @context: Context passed to acpi_register_wakeup_handler() |
142 | */ |
143 | void acpi_unregister_wakeup_handler(bool (*wakeup)(void *context), |
144 | void *context) |
145 | { |
146 | struct acpi_wakeup_handler *handler; |
147 | |
148 | mutex_lock(&acpi_wakeup_handler_mutex); |
149 | list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) { |
150 | if (handler->wakeup == wakeup && handler->context == context) { |
151 | list_del(entry: &handler->list_node); |
152 | kfree(objp: handler); |
153 | break; |
154 | } |
155 | } |
156 | mutex_unlock(lock: &acpi_wakeup_handler_mutex); |
157 | } |
158 | EXPORT_SYMBOL_GPL(acpi_unregister_wakeup_handler); |
159 | |
160 | bool acpi_check_wakeup_handlers(void) |
161 | { |
162 | struct acpi_wakeup_handler *handler; |
163 | |
164 | /* No need to lock, nothing else is running when we're called. */ |
165 | list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) { |
166 | if (handler->wakeup(handler->context)) |
167 | return true; |
168 | } |
169 | |
170 | return false; |
171 | } |
172 | |