xref: /openbmc/linux/drivers/acpi/wakeup.c (revision e8e0929d)
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 
12 #include "internal.h"
13 #include "sleep.h"
14 
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  **/
20 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
21 ACPI_MODULE_NAME("wakeup_devices")
22 
23 /**
24  * acpi_enable_wakeup_device_prep - prepare wakeup devices
25  *	@sleep_state:	ACPI state
26  * Enable all wakup devices power if the devices' wakeup level
27  * is higher than requested sleep level
28  */
29 
30 void acpi_enable_wakeup_device_prep(u8 sleep_state)
31 {
32 	struct list_head *node, *next;
33 
34 	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
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))
42 			continue;
43 
44 		acpi_enable_wakeup_device_power(dev, sleep_state);
45 	}
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 	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
62 		struct acpi_device *dev =
63 			container_of(node, struct acpi_device, wakeup_list);
64 
65 		if (!dev->wakeup.flags.valid)
66 			continue;
67 
68 		/* If users want to disable run-wake GPE,
69 		 * we only disable it for wake and leave it for runtime
70 		 */
71 		if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
72 		    || sleep_state > (u32) dev->wakeup.sleep_state) {
73 			if (dev->wakeup.flags.run_wake) {
74 				/* set_gpe_type will disable GPE, leave it like that */
75 				acpi_set_gpe_type(dev->wakeup.gpe_device,
76 						  dev->wakeup.gpe_number,
77 						  ACPI_GPE_TYPE_RUNTIME);
78 			}
79 			continue;
80 		}
81 		if (!dev->wakeup.flags.run_wake)
82 			acpi_enable_gpe(dev->wakeup.gpe_device,
83 					dev->wakeup.gpe_number);
84 	}
85 }
86 
87 /**
88  * acpi_disable_wakeup_device - disable devices' wakeup capability
89  *	@sleep_state:	ACPI state
90  * Disable all wakup devices's GPE and wakeup capability
91  */
92 void acpi_disable_wakeup_device(u8 sleep_state)
93 {
94 	struct list_head *node, *next;
95 
96 	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
97 		struct acpi_device *dev =
98 			container_of(node, struct acpi_device, wakeup_list);
99 
100 		if (!dev->wakeup.flags.valid)
101 			continue;
102 
103 		if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
104 		    || sleep_state > (u32) dev->wakeup.sleep_state) {
105 			if (dev->wakeup.flags.run_wake) {
106 				acpi_set_gpe_type(dev->wakeup.gpe_device,
107 						  dev->wakeup.gpe_number,
108 						  ACPI_GPE_TYPE_WAKE_RUN);
109 				/* Re-enable it, since set_gpe_type will disable it */
110 				acpi_enable_gpe(dev->wakeup.gpe_device,
111 						dev->wakeup.gpe_number);
112 			}
113 			continue;
114 		}
115 
116 		acpi_disable_wakeup_device_power(dev);
117 		/* Never disable run-wake GPE */
118 		if (!dev->wakeup.flags.run_wake) {
119 			acpi_disable_gpe(dev->wakeup.gpe_device,
120 					 dev->wakeup.gpe_number);
121 			acpi_clear_gpe(dev->wakeup.gpe_device,
122 				       dev->wakeup.gpe_number, ACPI_NOT_ISR);
123 		}
124 	}
125 }
126 
127 int __init acpi_wakeup_device_init(void)
128 {
129 	struct list_head *node, *next;
130 
131 	mutex_lock(&acpi_device_lock);
132 	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
133 		struct acpi_device *dev = container_of(node,
134 						       struct acpi_device,
135 						       wakeup_list);
136 		/* In case user doesn't load button driver */
137 		if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
138 			continue;
139 		acpi_set_gpe_type(dev->wakeup.gpe_device,
140 				  dev->wakeup.gpe_number,
141 				  ACPI_GPE_TYPE_WAKE_RUN);
142 		acpi_enable_gpe(dev->wakeup.gpe_device,
143 				dev->wakeup.gpe_number);
144 		dev->wakeup.state.enabled = 1;
145 	}
146 	mutex_unlock(&acpi_device_lock);
147 	return 0;
148 }
149