aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorDaniel Drake <dsd@laptop.org>2011-06-25 12:34:13 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2011-07-06 17:44:36 -0400
commitbc4ecd5a5efc2435e6debfb7b279a15ae96697fd (patch)
treebad8e400657beb73a1be8f2c61aba62560e55839 /arch/x86
parent7feda8e9f35ebb0e9f90e03acb02280bc137f784 (diff)
x86, olpc: EC SCI wakeup mask functionality
Update the EC SCI masks with recent additions. Add functions to query SCI events and set the wakeup mask, to be used by followup patches. Add functions to tweak an event mask used to select certain EC events as a system wakeup source. Also add a function to determine if EC wakeup functionality is available, as this depends on child drivers (different for each laptop model) to configure the SCI interrupt. Signed-off-by: Daniel Drake <dsd@laptop.org> Link: http://lkml.kernel.org/r/1309019658-1712-7-git-send-email-dsd@laptop.org Acked-by: Andres Salomon <dilinger@queued.net> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/olpc.h31
-rw-r--r--arch/x86/platform/olpc/olpc.c86
2 files changed, 111 insertions, 6 deletions
diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index 10ea59594b71..0e56d01907fe 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -13,6 +13,7 @@ struct olpc_platform_t {
13 13
14#define OLPC_F_PRESENT 0x01 14#define OLPC_F_PRESENT 0x01
15#define OLPC_F_DCON 0x02 15#define OLPC_F_DCON 0x02
16#define OLPC_F_EC_WIDE_SCI 0x04
16 17
17#ifdef CONFIG_OLPC 18#ifdef CONFIG_OLPC
18 19
@@ -62,6 +63,13 @@ static inline int olpc_board_at_least(uint32_t rev)
62 return olpc_platform_info.boardrev >= rev; 63 return olpc_platform_info.boardrev >= rev;
63} 64}
64 65
66extern void olpc_ec_wakeup_set(u16 value);
67extern void olpc_ec_wakeup_clear(u16 value);
68extern bool olpc_ec_wakeup_available(void);
69
70extern int olpc_ec_mask_write(u16 bits);
71extern int olpc_ec_sci_query(u16 *sci_value);
72
65#else 73#else
66 74
67static inline int machine_is_olpc(void) 75static inline int machine_is_olpc(void)
@@ -74,6 +82,14 @@ static inline int olpc_has_dcon(void)
74 return 0; 82 return 0;
75} 83}
76 84
85static inline void olpc_ec_wakeup_set(u16 value) { }
86static inline void olpc_ec_wakeup_clear(u16 value) { }
87
88static inline bool olpc_ec_wakeup_available(void)
89{
90 return false;
91}
92
77#endif 93#endif
78 94
79#ifdef CONFIG_OLPC_XO1_PM 95#ifdef CONFIG_OLPC_XO1_PM
@@ -89,17 +105,18 @@ extern int pci_olpc_init(void);
89extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen, 105extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
90 unsigned char *outbuf, size_t outlen); 106 unsigned char *outbuf, size_t outlen);
91 107
92extern int olpc_ec_mask_set(uint8_t bits);
93extern int olpc_ec_mask_unset(uint8_t bits);
94
95/* EC commands */ 108/* EC commands */
96 109
97#define EC_FIRMWARE_REV 0x08 110#define EC_FIRMWARE_REV 0x08
111#define EC_WRITE_SCI_MASK 0x1b
98#define EC_WAKE_UP_WLAN 0x24 112#define EC_WAKE_UP_WLAN 0x24
99#define EC_WLAN_LEAVE_RESET 0x25 113#define EC_WLAN_LEAVE_RESET 0x25
100#define EC_SET_SCI_INHIBIT 0x32 114#define EC_SET_SCI_INHIBIT 0x32
101#define EC_SET_SCI_INHIBIT_RELEASE 0x34 115#define EC_SET_SCI_INHIBIT_RELEASE 0x34
102#define EC_WLAN_ENTER_RESET 0x35 116#define EC_WLAN_ENTER_RESET 0x35
117#define EC_WRITE_EXT_SCI_MASK 0x38
118#define EC_SCI_QUERY 0x84
119#define EC_EXT_SCI_QUERY 0x85
103 120
104/* SCI source values */ 121/* SCI source values */
105 122
@@ -108,10 +125,12 @@ extern int olpc_ec_mask_unset(uint8_t bits);
108#define EC_SCI_SRC_BATTERY 0x02 125#define EC_SCI_SRC_BATTERY 0x02
109#define EC_SCI_SRC_BATSOC 0x04 126#define EC_SCI_SRC_BATSOC 0x04
110#define EC_SCI_SRC_BATERR 0x08 127#define EC_SCI_SRC_BATERR 0x08
111#define EC_SCI_SRC_EBOOK 0x10 128#define EC_SCI_SRC_EBOOK 0x10 /* XO-1 only */
112#define EC_SCI_SRC_WLAN 0x20 129#define EC_SCI_SRC_WLAN 0x20 /* XO-1 only */
113#define EC_SCI_SRC_ACPWR 0x40 130#define EC_SCI_SRC_ACPWR 0x40
114#define EC_SCI_SRC_ALL 0x7F 131#define EC_SCI_SRC_BATCRIT 0x80
132#define EC_SCI_SRC_GPWAKE 0x100 /* XO-1.5 only */
133#define EC_SCI_SRC_ALL 0x1FF
115 134
116/* GPIO assignments */ 135/* GPIO assignments */
117 136
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index 0060fd59ea00..72fd041762fc 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -19,6 +19,7 @@
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/syscore_ops.h>
22 23
23#include <asm/geode.h> 24#include <asm/geode.h>
24#include <asm/setup.h> 25#include <asm/setup.h>
@@ -30,6 +31,9 @@ EXPORT_SYMBOL_GPL(olpc_platform_info);
30 31
31static DEFINE_SPINLOCK(ec_lock); 32static DEFINE_SPINLOCK(ec_lock);
32 33
34/* EC event mask to be applied during suspend (defining wakeup sources). */
35static u16 ec_wakeup_mask;
36
33/* what the timeout *should* be (in ms) */ 37/* what the timeout *should* be (in ms) */
34#define EC_BASE_TIMEOUT 20 38#define EC_BASE_TIMEOUT 20
35 39
@@ -188,6 +192,79 @@ err:
188} 192}
189EXPORT_SYMBOL_GPL(olpc_ec_cmd); 193EXPORT_SYMBOL_GPL(olpc_ec_cmd);
190 194
195void olpc_ec_wakeup_set(u16 value)
196{
197 ec_wakeup_mask |= value;
198}
199EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set);
200
201void olpc_ec_wakeup_clear(u16 value)
202{
203 ec_wakeup_mask &= ~value;
204}
205EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear);
206
207/*
208 * Returns true if the compile and runtime configurations allow for EC events
209 * to wake the system.
210 */
211bool olpc_ec_wakeup_available(void)
212{
213 if (!machine_is_olpc())
214 return false;
215
216 /*
217 * XO-1 EC wakeups are available when olpc-xo1-sci driver is
218 * compiled in
219 */
220#ifdef CONFIG_OLPC_XO1_SCI
221 if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */
222 return true;
223#endif
224
225 return false;
226}
227EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available);
228
229int olpc_ec_mask_write(u16 bits)
230{
231 if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
232 __be16 ec_word = cpu_to_be16(bits);
233 return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *) &ec_word, 2,
234 NULL, 0);
235 } else {
236 unsigned char ec_byte = bits & 0xff;
237 return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0);
238 }
239}
240EXPORT_SYMBOL_GPL(olpc_ec_mask_write);
241
242int olpc_ec_sci_query(u16 *sci_value)
243{
244 int ret;
245
246 if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
247 __be16 ec_word;
248 ret = olpc_ec_cmd(EC_EXT_SCI_QUERY,
249 NULL, 0, (void *) &ec_word, 2);
250 if (ret == 0)
251 *sci_value = be16_to_cpu(ec_word);
252 } else {
253 unsigned char ec_byte;
254 ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1);
255 if (ret == 0)
256 *sci_value = ec_byte;
257 }
258
259 return ret;
260}
261EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
262
263static int olpc_ec_suspend(void)
264{
265 return olpc_ec_mask_write(ec_wakeup_mask);
266}
267
191static bool __init check_ofw_architecture(struct device_node *root) 268static bool __init check_ofw_architecture(struct device_node *root)
192{ 269{
193 const char *olpc_arch; 270 const char *olpc_arch;
@@ -242,6 +319,10 @@ static int __init add_xo1_platform_devices(void)
242 return 0; 319 return 0;
243} 320}
244 321
322static struct syscore_ops olpc_syscore_ops = {
323 .suspend = olpc_ec_suspend,
324};
325
245static int __init olpc_init(void) 326static int __init olpc_init(void)
246{ 327{
247 int r = 0; 328 int r = 0;
@@ -266,6 +347,9 @@ static int __init olpc_init(void)
266 !cs5535_has_vsa2()) 347 !cs5535_has_vsa2())
267 x86_init.pci.arch_init = pci_olpc_init; 348 x86_init.pci.arch_init = pci_olpc_init;
268#endif 349#endif
350 /* EC version 0x5f adds support for wide SCI mask */
351 if (olpc_platform_info.ecver >= 0x5f)
352 olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
269 353
270 printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n", 354 printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
271 ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", 355 ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
@@ -278,6 +362,8 @@ static int __init olpc_init(void)
278 return r; 362 return r;
279 } 363 }
280 364
365 register_syscore_ops(&olpc_syscore_ops);
366
281 return 0; 367 return 0;
282} 368}
283 369