• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
acpi_enable_wakeup_device_prep(u8 sleep_state)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  */
acpi_enable_wakeup_device(u8 sleep_state)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  */
acpi_disable_wakeup_device(u8 sleep_state)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 
acpi_wakeup_device_init(void)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);
168