From 392a325c4351339cfbf182bb5a1444df1cf65dbb Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Tue, 10 Jul 2012 19:31:51 -0700 Subject: Platform: OLPC: add a stub to drivers/platform/ for the OLPC EC driver The OLPC EC driver has outgrown arch/x86/platform/. It's time to both share common code amongst different architectures, as well as move it out of arch/x86/. The XO-1.75 is ARM-based, and the EC driver shares a lot of code with the x86 code. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/include/asm/olpc.h | 19 +++---------------- arch/x86/platform/olpc/olpc.c | 4 ++-- 2 files changed, 5 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h index 87bdbca72f94..513e9992771d 100644 --- a/arch/x86/include/asm/olpc.h +++ b/arch/x86/include/asm/olpc.h @@ -4,6 +4,7 @@ #define _ASM_X86_OLPC_H #include +#include struct olpc_platform_t { int flags; @@ -102,22 +103,8 @@ extern int pci_olpc_init(void); /* EC related functions */ -extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen, - unsigned char *outbuf, size_t outlen); - -/* EC commands */ - -#define EC_FIRMWARE_REV 0x08 -#define EC_WRITE_SCI_MASK 0x1b -#define EC_WAKE_UP_WLAN 0x24 -#define EC_WLAN_LEAVE_RESET 0x25 -#define EC_READ_EB_MODE 0x2a -#define EC_SET_SCI_INHIBIT 0x32 -#define EC_SET_SCI_INHIBIT_RELEASE 0x34 -#define EC_WLAN_ENTER_RESET 0x35 -#define EC_WRITE_EXT_SCI_MASK 0x38 -#define EC_SCI_QUERY 0x84 -#define EC_EXT_SCI_QUERY 0x85 +extern int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, + size_t inlen, unsigned char *outbuf, size_t outlen); /* SCI source values */ diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index a4bee53c2e54..796e199ac77a 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -125,7 +125,7 @@ static int __wait_on_obf(unsigned int line, unsigned int port, int desired) * . Unfortunately, while * OpenFirmware's source is available, the EC's is not. */ -int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen, +int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, size_t inlen, unsigned char *outbuf, size_t outlen) { unsigned long flags; @@ -201,7 +201,7 @@ err: spin_unlock_irqrestore(&ec_lock, flags); return ret; } -EXPORT_SYMBOL_GPL(olpc_ec_cmd); +EXPORT_SYMBOL_GPL(olpc_ec_cmd_x86); void olpc_ec_wakeup_set(u16 value) { -- cgit v1.2.2 From 3bf9428f220911795edde453a95f9509945004e5 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Wed, 11 Jul 2012 01:16:29 -0700 Subject: drivers: OLPC: update various drivers to include olpc-ec.h Switch over to using olpc-ec.h in multiple steps, so as not to break builds. This covers every driver that calls olpc_ec_cmd(). Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/include/asm/olpc.h | 1 - arch/x86/platform/olpc/olpc-xo1-pm.c | 1 + arch/x86/platform/olpc/olpc-xo1-sci.c | 1 + arch/x86/platform/olpc/olpc-xo15-sci.c | 1 + arch/x86/platform/olpc/olpc.c | 1 + 5 files changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h index 513e9992771d..5b28f3e69758 100644 --- a/arch/x86/include/asm/olpc.h +++ b/arch/x86/include/asm/olpc.h @@ -4,7 +4,6 @@ #define _ASM_X86_OLPC_H #include -#include struct olpc_platform_t { int flags; diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c index 0ce8616c88ae..8054b64ec4ce 100644 --- a/arch/x86/platform/olpc/olpc-xo1-pm.c +++ b/arch/x86/platform/olpc/olpc-xo1-pm.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c index 04b8c73659c5..63d4aa40956e 100644 --- a/arch/x86/platform/olpc/olpc-xo1-sci.c +++ b/arch/x86/platform/olpc/olpc-xo1-sci.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c index 599be499fdf7..2fdca25905ae 100644 --- a/arch/x86/platform/olpc/olpc-xo15-sci.c +++ b/arch/x86/platform/olpc/olpc-xo15-sci.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index 796e199ac77a..a3fa180c15c8 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include -- cgit v1.2.2 From 85f90cf6ca569b19cee212844b543a7355b77163 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Thu, 12 Jul 2012 17:57:28 -0700 Subject: x86: OLPC: switch over to using new EC driver on x86 This uses the new EC driver framework in drivers/platform/olpc. The XO-1 and XO-1.5-specific code is still in arch/x86, but the generic stuff (including a new workqueue; no more running EC commands with IRQs disabled!) can be shared with other architectures. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/include/asm/olpc.h | 5 ---- arch/x86/platform/olpc/olpc.c | 53 ++++++++++++++++++++++--------------------- 2 files changed, 27 insertions(+), 31 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h index 5b28f3e69758..72f9adf6eca4 100644 --- a/arch/x86/include/asm/olpc.h +++ b/arch/x86/include/asm/olpc.h @@ -100,11 +100,6 @@ extern void olpc_xo1_pm_wakeup_clear(u16 value); extern int pci_olpc_init(void); -/* EC related functions */ - -extern int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, - size_t inlen, unsigned char *outbuf, size_t outlen); - /* SCI source values */ #define EC_SCI_SRC_EMPTY 0x00 diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index a3fa180c15c8..45900968fb89 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -32,8 +31,6 @@ struct olpc_platform_t olpc_platform_info; EXPORT_SYMBOL_GPL(olpc_platform_info); -static DEFINE_SPINLOCK(ec_lock); - /* debugfs interface to EC commands */ #define EC_MAX_CMD_ARGS (5 + 1) /* cmd byte + 5 args */ #define EC_MAX_CMD_REPLY (8) @@ -126,16 +123,13 @@ static int __wait_on_obf(unsigned int line, unsigned int port, int desired) * . Unfortunately, while * OpenFirmware's source is available, the EC's is not. */ -int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, size_t inlen, - unsigned char *outbuf, size_t outlen) +static int olpc_xo1_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, + size_t outlen, void *arg) { - unsigned long flags; int ret = -EIO; int i; int restarts = 0; - spin_lock_irqsave(&ec_lock, flags); - /* Clear OBF */ for (i = 0; i < 10 && (obf_status(0x6c) == 1); i++) inb(0x68); @@ -199,10 +193,8 @@ restart: ret = 0; err: - spin_unlock_irqrestore(&ec_lock, flags); return ret; } -EXPORT_SYMBOL_GPL(olpc_ec_cmd_x86); void olpc_ec_wakeup_set(u16 value) { @@ -366,7 +358,7 @@ static void setup_debugfs(void) &ec_debugfs_genops); } -static int olpc_ec_suspend(void) +static int olpc_ec_suspend(struct platform_device *pdev) { return olpc_ec_mask_write(ec_wakeup_mask); } @@ -425,8 +417,28 @@ static int __init add_xo1_platform_devices(void) return 0; } -static struct syscore_ops olpc_syscore_ops = { +static int olpc_xo1_ec_probe(struct platform_device *pdev) +{ + /* get the EC revision */ + olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, + (unsigned char *) &olpc_platform_info.ecver, 1); + + /* EC version 0x5f adds support for wide SCI mask */ + if (olpc_platform_info.ecver >= 0x5f) + olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI; + + pr_info("OLPC board revision %s%X (EC=%x)\n", + ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", + olpc_platform_info.boardrev >> 4, + olpc_platform_info.ecver); + + return 0; +} + +static struct olpc_ec_driver ec_xo1_driver = { .suspend = olpc_ec_suspend, + .probe = olpc_xo1_ec_probe, + .ec_cmd = olpc_xo1_ec_cmd, }; static int __init olpc_init(void) @@ -436,16 +448,14 @@ static int __init olpc_init(void) if (!olpc_ofw_present() || !platform_detect()) return 0; - spin_lock_init(&ec_lock); + /* register the XO-1 and 1.5-specific EC handler */ + olpc_ec_driver_register(&ec_xo1_driver, NULL); + platform_device_register_simple("olpc-ec", -1, NULL, 0); /* assume B1 and above models always have a DCON */ if (olpc_board_at_least(olpc_board(0xb1))) olpc_platform_info.flags |= OLPC_F_DCON; - /* get the EC revision */ - olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, - (unsigned char *) &olpc_platform_info.ecver, 1); - #ifdef CONFIG_PCI_OLPC /* If the VSA exists let it emulate PCI, if not emulate in kernel. * XO-1 only. */ @@ -453,14 +463,6 @@ static int __init olpc_init(void) !cs5535_has_vsa2()) x86_init.pci.arch_init = pci_olpc_init; #endif - /* EC version 0x5f adds support for wide SCI mask */ - if (olpc_platform_info.ecver >= 0x5f) - olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI; - - printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n", - ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", - olpc_platform_info.boardrev >> 4, - olpc_platform_info.ecver); if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) { /* XO-1 */ r = add_xo1_platform_devices(); @@ -468,7 +470,6 @@ static int __init olpc_init(void) return r; } - register_syscore_ops(&olpc_syscore_ops); setup_debugfs(); return 0; -- cgit v1.2.2 From 6cca83d498bda0999302079bd59786370590c5c2 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Thu, 12 Jul 2012 20:45:14 -0700 Subject: Platform: OLPC: move debugfs support from x86 EC driver There's nothing about the debugfs interface for the EC driver that is architecture-specific, so move it into the arch-independent driver. The code is mostly unchanged with the exception of renamed variables, coding style changes, and API updates. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/platform/olpc/olpc.c | 97 ------------------------------------------- 1 file changed, 97 deletions(-) (limited to 'arch') diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index 45900968fb89..ed41b437b37b 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -31,15 +30,6 @@ struct olpc_platform_t olpc_platform_info; EXPORT_SYMBOL_GPL(olpc_platform_info); -/* debugfs interface to EC commands */ -#define EC_MAX_CMD_ARGS (5 + 1) /* cmd byte + 5 args */ -#define EC_MAX_CMD_REPLY (8) - -static struct dentry *ec_debugfs_dir; -static DEFINE_MUTEX(ec_debugfs_cmd_lock); -static unsigned char ec_debugfs_resp[EC_MAX_CMD_REPLY]; -static unsigned int ec_debugfs_resp_bytes; - /* EC event mask to be applied during suspend (defining wakeup sources). */ static u16 ec_wakeup_mask; @@ -273,91 +263,6 @@ int olpc_ec_sci_query(u16 *sci_value) } EXPORT_SYMBOL_GPL(olpc_ec_sci_query); -static ssize_t ec_debugfs_cmd_write(struct file *file, const char __user *buf, - size_t size, loff_t *ppos) -{ - int i, m; - unsigned char ec_cmd[EC_MAX_CMD_ARGS]; - unsigned int ec_cmd_int[EC_MAX_CMD_ARGS]; - char cmdbuf[64]; - int ec_cmd_bytes; - - mutex_lock(&ec_debugfs_cmd_lock); - - size = simple_write_to_buffer(cmdbuf, sizeof(cmdbuf), ppos, buf, size); - - m = sscanf(cmdbuf, "%x:%u %x %x %x %x %x", &ec_cmd_int[0], - &ec_debugfs_resp_bytes, - &ec_cmd_int[1], &ec_cmd_int[2], &ec_cmd_int[3], - &ec_cmd_int[4], &ec_cmd_int[5]); - if (m < 2 || ec_debugfs_resp_bytes > EC_MAX_CMD_REPLY) { - /* reset to prevent overflow on read */ - ec_debugfs_resp_bytes = 0; - - printk(KERN_DEBUG "olpc-ec: bad ec cmd: " - "cmd:response-count [arg1 [arg2 ...]]\n"); - size = -EINVAL; - goto out; - } - - /* convert scanf'd ints to char */ - ec_cmd_bytes = m - 2; - for (i = 0; i <= ec_cmd_bytes; i++) - ec_cmd[i] = ec_cmd_int[i]; - - printk(KERN_DEBUG "olpc-ec: debugfs cmd 0x%02x with %d args " - "%02x %02x %02x %02x %02x, want %d returns\n", - ec_cmd[0], ec_cmd_bytes, ec_cmd[1], ec_cmd[2], ec_cmd[3], - ec_cmd[4], ec_cmd[5], ec_debugfs_resp_bytes); - - olpc_ec_cmd(ec_cmd[0], (ec_cmd_bytes == 0) ? NULL : &ec_cmd[1], - ec_cmd_bytes, ec_debugfs_resp, ec_debugfs_resp_bytes); - - printk(KERN_DEBUG "olpc-ec: response " - "%02x %02x %02x %02x %02x %02x %02x %02x (%d bytes expected)\n", - ec_debugfs_resp[0], ec_debugfs_resp[1], ec_debugfs_resp[2], - ec_debugfs_resp[3], ec_debugfs_resp[4], ec_debugfs_resp[5], - ec_debugfs_resp[6], ec_debugfs_resp[7], ec_debugfs_resp_bytes); - -out: - mutex_unlock(&ec_debugfs_cmd_lock); - return size; -} - -static ssize_t ec_debugfs_cmd_read(struct file *file, char __user *buf, - size_t size, loff_t *ppos) -{ - unsigned int i, r; - char *rp; - char respbuf[64]; - - mutex_lock(&ec_debugfs_cmd_lock); - rp = respbuf; - rp += sprintf(rp, "%02x", ec_debugfs_resp[0]); - for (i = 1; i < ec_debugfs_resp_bytes; i++) - rp += sprintf(rp, ", %02x", ec_debugfs_resp[i]); - mutex_unlock(&ec_debugfs_cmd_lock); - rp += sprintf(rp, "\n"); - - r = rp - respbuf; - return simple_read_from_buffer(buf, size, ppos, respbuf, r); -} - -static const struct file_operations ec_debugfs_genops = { - .write = ec_debugfs_cmd_write, - .read = ec_debugfs_cmd_read, -}; - -static void setup_debugfs(void) -{ - ec_debugfs_dir = debugfs_create_dir("olpc-ec", 0); - if (ec_debugfs_dir == ERR_PTR(-ENODEV)) - return; - - debugfs_create_file("cmd", 0600, ec_debugfs_dir, NULL, - &ec_debugfs_genops); -} - static int olpc_ec_suspend(struct platform_device *pdev) { return olpc_ec_mask_write(ec_wakeup_mask); @@ -470,8 +375,6 @@ static int __init olpc_init(void) return r; } - setup_debugfs(); - return 0; } -- cgit v1.2.2 From 1fcfd08bd0704e1888bd73153e8d2ca3640e22f2 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Tue, 17 Jul 2012 01:26:10 -0700 Subject: x86: OLPC: move s/r-related EC cmds to EC driver The new EC driver calls platform-specific suspend and resume hooks; run XO-1-specific EC commands from there, rather than deep in s/r code. If we attempt to run EC commands after the new EC driver has suspended, it is refused by the ec->suspended checks. Signed-off-by: Andres Salomon Acked-by: Paul Fox Reviewed-by: Thomas Gleixner --- arch/x86/platform/olpc/olpc-xo1-pm.c | 15 ------------- arch/x86/platform/olpc/olpc.c | 43 ++++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c index 8054b64ec4ce..d75582d1aa55 100644 --- a/arch/x86/platform/olpc/olpc-xo1-pm.c +++ b/arch/x86/platform/olpc/olpc-xo1-pm.c @@ -52,16 +52,11 @@ EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_clear); static int xo1_power_state_enter(suspend_state_t pm_state) { unsigned long saved_sci_mask; - int r; /* Only STR is supported */ if (pm_state != PM_SUSPEND_MEM) return -EINVAL; - r = olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0); - if (r) - return r; - /* * Save SCI mask (this gets lost since PM1_EN is used as a mask for * wakeup events, which is not necessarily the same event set) @@ -77,16 +72,6 @@ static int xo1_power_state_enter(suspend_state_t pm_state) /* Restore SCI mask (using dword access to CS5536_PM1_EN) */ outl(saved_sci_mask, acpi_base + CS5536_PM1_STS); - /* Tell the EC to stop inhibiting SCIs */ - olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0); - - /* - * Tell the wireless module to restart USB communication. - * Must be done twice. - */ - olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0); - olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0); - return 0; } diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c index ed41b437b37b..27376081ddec 100644 --- a/arch/x86/platform/olpc/olpc.c +++ b/arch/x86/platform/olpc/olpc.c @@ -263,11 +263,6 @@ int olpc_ec_sci_query(u16 *sci_value) } EXPORT_SYMBOL_GPL(olpc_ec_sci_query); -static int olpc_ec_suspend(struct platform_device *pdev) -{ - return olpc_ec_mask_write(ec_wakeup_mask); -} - static bool __init check_ofw_architecture(struct device_node *root) { const char *olpc_arch; @@ -339,9 +334,40 @@ static int olpc_xo1_ec_probe(struct platform_device *pdev) return 0; } +static int olpc_xo1_ec_suspend(struct platform_device *pdev) +{ + olpc_ec_mask_write(ec_wakeup_mask); + + /* + * Squelch SCIs while suspended. This is a fix for + * . + */ + return olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0); +} + +static int olpc_xo1_ec_resume(struct platform_device *pdev) +{ + /* Tell the EC to stop inhibiting SCIs */ + olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0); + + /* + * Tell the wireless module to restart USB communication. + * Must be done twice. + */ + olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0); + olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0); + + return 0; +} static struct olpc_ec_driver ec_xo1_driver = { - .suspend = olpc_ec_suspend, + .probe = olpc_xo1_ec_probe, + .suspend = olpc_xo1_ec_suspend, + .resume = olpc_xo1_ec_resume, + .ec_cmd = olpc_xo1_ec_cmd, +}; + +static struct olpc_ec_driver ec_xo1_5_driver = { .probe = olpc_xo1_ec_probe, .ec_cmd = olpc_xo1_ec_cmd, }; @@ -354,7 +380,10 @@ static int __init olpc_init(void) return 0; /* register the XO-1 and 1.5-specific EC handler */ - olpc_ec_driver_register(&ec_xo1_driver, NULL); + if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */ + olpc_ec_driver_register(&ec_xo1_driver, NULL); + else + olpc_ec_driver_register(&ec_xo1_5_driver, NULL); platform_device_register_simple("olpc-ec", -1, NULL, 0); /* assume B1 and above models always have a DCON */ -- cgit v1.2.2