aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/platform
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/platform
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/platform')
-rw-r--r--arch/x86/platform/olpc/olpc.c86
1 files changed, 86 insertions, 0 deletions
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