Skip to content

Commit fc6bdb5

Browse files
committed
Merge branch 'for-linus-3.6' of git://dev.laptop.org/users/dilinger/linux-olpc
Pull OLPC platform updates from Andres Salomon: "These move the OLPC Embedded Controller driver out of arch/x86/platform and into drivers/platform/olpc. OLPC machines are now ARM-based (which means lots of x86 and ARM changes), but are typically pretty self-contained.. so it makes more sense to go through a separate OLPC tree after getting the appropriate review/ACKs." * 'for-linus-3.6' of git://dev.laptop.org/users/dilinger/linux-olpc: x86: OLPC: move s/r-related EC cmds to EC driver Platform: OLPC: move global variables into priv struct Platform: OLPC: move debugfs support from x86 EC driver x86: OLPC: switch over to using new EC driver on x86 Platform: OLPC: add a suspended flag to the EC driver Platform: OLPC: turn EC driver into a platform_driver Platform: OLPC: allow EC cmd to be overridden, and create a workqueue to call it drivers: OLPC: update various drivers to include olpc-ec.h Platform: OLPC: add a stub to drivers/platform/ for the OLPC EC driver
2 parents 44d82e2 + 1fcfd08 commit fc6bdb5

File tree

13 files changed

+451
-164
lines changed

13 files changed

+451
-164
lines changed

arch/x86/include/asm/olpc.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -100,25 +100,6 @@ extern void olpc_xo1_pm_wakeup_clear(u16 value);
100100

101101
extern int pci_olpc_init(void);
102102

103-
/* EC related functions */
104-
105-
extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
106-
unsigned char *outbuf, size_t outlen);
107-
108-
/* EC commands */
109-
110-
#define EC_FIRMWARE_REV 0x08
111-
#define EC_WRITE_SCI_MASK 0x1b
112-
#define EC_WAKE_UP_WLAN 0x24
113-
#define EC_WLAN_LEAVE_RESET 0x25
114-
#define EC_READ_EB_MODE 0x2a
115-
#define EC_SET_SCI_INHIBIT 0x32
116-
#define EC_SET_SCI_INHIBIT_RELEASE 0x34
117-
#define EC_WLAN_ENTER_RESET 0x35
118-
#define EC_WRITE_EXT_SCI_MASK 0x38
119-
#define EC_SCI_QUERY 0x84
120-
#define EC_EXT_SCI_QUERY 0x85
121-
122103
/* SCI source values */
123104

124105
#define EC_SCI_SRC_EMPTY 0x00

arch/x86/platform/olpc/olpc-xo1-pm.c

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/pm.h>
1919
#include <linux/mfd/core.h>
2020
#include <linux/suspend.h>
21+
#include <linux/olpc-ec.h>
2122

2223
#include <asm/io.h>
2324
#include <asm/olpc.h>
@@ -51,16 +52,11 @@ EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_clear);
5152
static int xo1_power_state_enter(suspend_state_t pm_state)
5253
{
5354
unsigned long saved_sci_mask;
54-
int r;
5555

5656
/* Only STR is supported */
5757
if (pm_state != PM_SUSPEND_MEM)
5858
return -EINVAL;
5959

60-
r = olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0);
61-
if (r)
62-
return r;
63-
6460
/*
6561
* Save SCI mask (this gets lost since PM1_EN is used as a mask for
6662
* wakeup events, which is not necessarily the same event set)
@@ -76,16 +72,6 @@ static int xo1_power_state_enter(suspend_state_t pm_state)
7672
/* Restore SCI mask (using dword access to CS5536_PM1_EN) */
7773
outl(saved_sci_mask, acpi_base + CS5536_PM1_STS);
7874

79-
/* Tell the EC to stop inhibiting SCIs */
80-
olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0);
81-
82-
/*
83-
* Tell the wireless module to restart USB communication.
84-
* Must be done twice.
85-
*/
86-
olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
87-
olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
88-
8975
return 0;
9076
}
9177

arch/x86/platform/olpc/olpc-xo1-sci.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <linux/power_supply.h>
2424
#include <linux/suspend.h>
2525
#include <linux/workqueue.h>
26+
#include <linux/olpc-ec.h>
2627

2728
#include <asm/io.h>
2829
#include <asm/msr.h>

arch/x86/platform/olpc/olpc-xo15-sci.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/slab.h>
1414
#include <linux/workqueue.h>
1515
#include <linux/power_supply.h>
16+
#include <linux/olpc-ec.h>
1617

1718
#include <acpi/acpi_bus.h>
1819
#include <acpi/acpi_drivers.h>

arch/x86/platform/olpc/olpc.c

Lines changed: 62 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@
1414
#include <linux/init.h>
1515
#include <linux/module.h>
1616
#include <linux/delay.h>
17-
#include <linux/spinlock.h>
1817
#include <linux/io.h>
1918
#include <linux/string.h>
2019
#include <linux/platform_device.h>
2120
#include <linux/of.h>
2221
#include <linux/syscore_ops.h>
23-
#include <linux/debugfs.h>
2422
#include <linux/mutex.h>
23+
#include <linux/olpc-ec.h>
2524

2625
#include <asm/geode.h>
2726
#include <asm/setup.h>
@@ -31,17 +30,6 @@
3130
struct olpc_platform_t olpc_platform_info;
3231
EXPORT_SYMBOL_GPL(olpc_platform_info);
3332

34-
static DEFINE_SPINLOCK(ec_lock);
35-
36-
/* debugfs interface to EC commands */
37-
#define EC_MAX_CMD_ARGS (5 + 1) /* cmd byte + 5 args */
38-
#define EC_MAX_CMD_REPLY (8)
39-
40-
static struct dentry *ec_debugfs_dir;
41-
static DEFINE_MUTEX(ec_debugfs_cmd_lock);
42-
static unsigned char ec_debugfs_resp[EC_MAX_CMD_REPLY];
43-
static unsigned int ec_debugfs_resp_bytes;
44-
4533
/* EC event mask to be applied during suspend (defining wakeup sources). */
4634
static u16 ec_wakeup_mask;
4735

@@ -125,16 +113,13 @@ static int __wait_on_obf(unsigned int line, unsigned int port, int desired)
125113
* <http://wiki.laptop.org/go/Ec_specification>. Unfortunately, while
126114
* OpenFirmware's source is available, the EC's is not.
127115
*/
128-
int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
129-
unsigned char *outbuf, size_t outlen)
116+
static int olpc_xo1_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf,
117+
size_t outlen, void *arg)
130118
{
131-
unsigned long flags;
132119
int ret = -EIO;
133120
int i;
134121
int restarts = 0;
135122

136-
spin_lock_irqsave(&ec_lock, flags);
137-
138123
/* Clear OBF */
139124
for (i = 0; i < 10 && (obf_status(0x6c) == 1); i++)
140125
inb(0x68);
@@ -198,10 +183,8 @@ int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
198183

199184
ret = 0;
200185
err:
201-
spin_unlock_irqrestore(&ec_lock, flags);
202186
return ret;
203187
}
204-
EXPORT_SYMBOL_GPL(olpc_ec_cmd);
205188

206189
void olpc_ec_wakeup_set(u16 value)
207190
{
@@ -280,96 +263,6 @@ int olpc_ec_sci_query(u16 *sci_value)
280263
}
281264
EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
282265

283-
static ssize_t ec_debugfs_cmd_write(struct file *file, const char __user *buf,
284-
size_t size, loff_t *ppos)
285-
{
286-
int i, m;
287-
unsigned char ec_cmd[EC_MAX_CMD_ARGS];
288-
unsigned int ec_cmd_int[EC_MAX_CMD_ARGS];
289-
char cmdbuf[64];
290-
int ec_cmd_bytes;
291-
292-
mutex_lock(&ec_debugfs_cmd_lock);
293-
294-
size = simple_write_to_buffer(cmdbuf, sizeof(cmdbuf), ppos, buf, size);
295-
296-
m = sscanf(cmdbuf, "%x:%u %x %x %x %x %x", &ec_cmd_int[0],
297-
&ec_debugfs_resp_bytes,
298-
&ec_cmd_int[1], &ec_cmd_int[2], &ec_cmd_int[3],
299-
&ec_cmd_int[4], &ec_cmd_int[5]);
300-
if (m < 2 || ec_debugfs_resp_bytes > EC_MAX_CMD_REPLY) {
301-
/* reset to prevent overflow on read */
302-
ec_debugfs_resp_bytes = 0;
303-
304-
printk(KERN_DEBUG "olpc-ec: bad ec cmd: "
305-
"cmd:response-count [arg1 [arg2 ...]]\n");
306-
size = -EINVAL;
307-
goto out;
308-
}
309-
310-
/* convert scanf'd ints to char */
311-
ec_cmd_bytes = m - 2;
312-
for (i = 0; i <= ec_cmd_bytes; i++)
313-
ec_cmd[i] = ec_cmd_int[i];
314-
315-
printk(KERN_DEBUG "olpc-ec: debugfs cmd 0x%02x with %d args "
316-
"%02x %02x %02x %02x %02x, want %d returns\n",
317-
ec_cmd[0], ec_cmd_bytes, ec_cmd[1], ec_cmd[2], ec_cmd[3],
318-
ec_cmd[4], ec_cmd[5], ec_debugfs_resp_bytes);
319-
320-
olpc_ec_cmd(ec_cmd[0], (ec_cmd_bytes == 0) ? NULL : &ec_cmd[1],
321-
ec_cmd_bytes, ec_debugfs_resp, ec_debugfs_resp_bytes);
322-
323-
printk(KERN_DEBUG "olpc-ec: response "
324-
"%02x %02x %02x %02x %02x %02x %02x %02x (%d bytes expected)\n",
325-
ec_debugfs_resp[0], ec_debugfs_resp[1], ec_debugfs_resp[2],
326-
ec_debugfs_resp[3], ec_debugfs_resp[4], ec_debugfs_resp[5],
327-
ec_debugfs_resp[6], ec_debugfs_resp[7], ec_debugfs_resp_bytes);
328-
329-
out:
330-
mutex_unlock(&ec_debugfs_cmd_lock);
331-
return size;
332-
}
333-
334-
static ssize_t ec_debugfs_cmd_read(struct file *file, char __user *buf,
335-
size_t size, loff_t *ppos)
336-
{
337-
unsigned int i, r;
338-
char *rp;
339-
char respbuf[64];
340-
341-
mutex_lock(&ec_debugfs_cmd_lock);
342-
rp = respbuf;
343-
rp += sprintf(rp, "%02x", ec_debugfs_resp[0]);
344-
for (i = 1; i < ec_debugfs_resp_bytes; i++)
345-
rp += sprintf(rp, ", %02x", ec_debugfs_resp[i]);
346-
mutex_unlock(&ec_debugfs_cmd_lock);
347-
rp += sprintf(rp, "\n");
348-
349-
r = rp - respbuf;
350-
return simple_read_from_buffer(buf, size, ppos, respbuf, r);
351-
}
352-
353-
static const struct file_operations ec_debugfs_genops = {
354-
.write = ec_debugfs_cmd_write,
355-
.read = ec_debugfs_cmd_read,
356-
};
357-
358-
static void setup_debugfs(void)
359-
{
360-
ec_debugfs_dir = debugfs_create_dir("olpc-ec", 0);
361-
if (ec_debugfs_dir == ERR_PTR(-ENODEV))
362-
return;
363-
364-
debugfs_create_file("cmd", 0600, ec_debugfs_dir, NULL,
365-
&ec_debugfs_genops);
366-
}
367-
368-
static int olpc_ec_suspend(void)
369-
{
370-
return olpc_ec_mask_write(ec_wakeup_mask);
371-
}
372-
373266
static bool __init check_ofw_architecture(struct device_node *root)
374267
{
375268
const char *olpc_arch;
@@ -424,8 +317,59 @@ static int __init add_xo1_platform_devices(void)
424317
return 0;
425318
}
426319

427-
static struct syscore_ops olpc_syscore_ops = {
428-
.suspend = olpc_ec_suspend,
320+
static int olpc_xo1_ec_probe(struct platform_device *pdev)
321+
{
322+
/* get the EC revision */
323+
olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0,
324+
(unsigned char *) &olpc_platform_info.ecver, 1);
325+
326+
/* EC version 0x5f adds support for wide SCI mask */
327+
if (olpc_platform_info.ecver >= 0x5f)
328+
olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
329+
330+
pr_info("OLPC board revision %s%X (EC=%x)\n",
331+
((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
332+
olpc_platform_info.boardrev >> 4,
333+
olpc_platform_info.ecver);
334+
335+
return 0;
336+
}
337+
static int olpc_xo1_ec_suspend(struct platform_device *pdev)
338+
{
339+
olpc_ec_mask_write(ec_wakeup_mask);
340+
341+
/*
342+
* Squelch SCIs while suspended. This is a fix for
343+
* <http://dev.laptop.org/ticket/1835>.
344+
*/
345+
return olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0);
346+
}
347+
348+
static int olpc_xo1_ec_resume(struct platform_device *pdev)
349+
{
350+
/* Tell the EC to stop inhibiting SCIs */
351+
olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0);
352+
353+
/*
354+
* Tell the wireless module to restart USB communication.
355+
* Must be done twice.
356+
*/
357+
olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
358+
olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
359+
360+
return 0;
361+
}
362+
363+
static struct olpc_ec_driver ec_xo1_driver = {
364+
.probe = olpc_xo1_ec_probe,
365+
.suspend = olpc_xo1_ec_suspend,
366+
.resume = olpc_xo1_ec_resume,
367+
.ec_cmd = olpc_xo1_ec_cmd,
368+
};
369+
370+
static struct olpc_ec_driver ec_xo1_5_driver = {
371+
.probe = olpc_xo1_ec_probe,
372+
.ec_cmd = olpc_xo1_ec_cmd,
429373
};
430374

431375
static int __init olpc_init(void)
@@ -435,41 +379,31 @@ static int __init olpc_init(void)
435379
if (!olpc_ofw_present() || !platform_detect())
436380
return 0;
437381

438-
spin_lock_init(&ec_lock);
382+
/* register the XO-1 and 1.5-specific EC handler */
383+
if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */
384+
olpc_ec_driver_register(&ec_xo1_driver, NULL);
385+
else
386+
olpc_ec_driver_register(&ec_xo1_5_driver, NULL);
387+
platform_device_register_simple("olpc-ec", -1, NULL, 0);
439388

440389
/* assume B1 and above models always have a DCON */
441390
if (olpc_board_at_least(olpc_board(0xb1)))
442391
olpc_platform_info.flags |= OLPC_F_DCON;
443392

444-
/* get the EC revision */
445-
olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0,
446-
(unsigned char *) &olpc_platform_info.ecver, 1);
447-
448393
#ifdef CONFIG_PCI_OLPC
449394
/* If the VSA exists let it emulate PCI, if not emulate in kernel.
450395
* XO-1 only. */
451396
if (olpc_platform_info.boardrev < olpc_board_pre(0xd0) &&
452397
!cs5535_has_vsa2())
453398
x86_init.pci.arch_init = pci_olpc_init;
454399
#endif
455-
/* EC version 0x5f adds support for wide SCI mask */
456-
if (olpc_platform_info.ecver >= 0x5f)
457-
olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
458-
459-
printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
460-
((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
461-
olpc_platform_info.boardrev >> 4,
462-
olpc_platform_info.ecver);
463400

464401
if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) { /* XO-1 */
465402
r = add_xo1_platform_devices();
466403
if (r)
467404
return r;
468405
}
469406

470-
register_syscore_ops(&olpc_syscore_ops);
471-
setup_debugfs();
472-
473407
return 0;
474408
}
475409

drivers/net/wireless/libertas/if_usb.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/netdevice.h>
1111
#include <linux/slab.h>
1212
#include <linux/usb.h>
13+
#include <linux/olpc-ec.h>
1314

1415
#ifdef CONFIG_OLPC
1516
#include <asm/olpc.h>

drivers/platform/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
#
44

55
obj-$(CONFIG_X86) += x86/
6+
obj-$(CONFIG_OLPC) += olpc/

drivers/platform/olpc/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#
2+
# OLPC XO platform-specific drivers
3+
#
4+
obj-$(CONFIG_OLPC) += olpc-ec.o

0 commit comments

Comments
 (0)