Skip to content

Commit

Permalink
Merge branch 'for-linus-3.6' of git://dev.laptop.org/users/dilinger/l…
Browse files Browse the repository at this point in the history
…inux-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
  • Loading branch information
torvalds committed Aug 2, 2012
2 parents 44d82e2 + 1fcfd08 commit fc6bdb5
Show file tree
Hide file tree
Showing 13 changed files with 451 additions and 164 deletions.
19 changes: 0 additions & 19 deletions arch/x86/include/asm/olpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,25 +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(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

/* SCI source values */

#define EC_SCI_SRC_EMPTY 0x00
Expand Down
16 changes: 1 addition & 15 deletions arch/x86/platform/olpc/olpc-xo1-pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/pm.h>
#include <linux/mfd/core.h>
#include <linux/suspend.h>
#include <linux/olpc-ec.h>

#include <asm/io.h>
#include <asm/olpc.h>
Expand Down Expand Up @@ -51,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)
Expand All @@ -76,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;
}

Expand Down
1 change: 1 addition & 0 deletions arch/x86/platform/olpc/olpc-xo1-sci.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/power_supply.h>
#include <linux/suspend.h>
#include <linux/workqueue.h>
#include <linux/olpc-ec.h>

#include <asm/io.h>
#include <asm/msr.h>
Expand Down
1 change: 1 addition & 0 deletions arch/x86/platform/olpc/olpc-xo15-sci.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/power_supply.h>
#include <linux/olpc-ec.h>

#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
Expand Down
190 changes: 62 additions & 128 deletions arch/x86/platform/olpc/olpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/syscore_ops.h>
#include <linux/debugfs.h>
#include <linux/mutex.h>
#include <linux/olpc-ec.h>

#include <asm/geode.h>
#include <asm/setup.h>
Expand All @@ -31,17 +30,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)

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;

Expand Down Expand Up @@ -125,16 +113,13 @@ static int __wait_on_obf(unsigned int line, unsigned int port, int desired)
* <http://wiki.laptop.org/go/Ec_specification>. 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,
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);
Expand Down Expand Up @@ -198,10 +183,8 @@ int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,

ret = 0;
err:
spin_unlock_irqrestore(&ec_lock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(olpc_ec_cmd);

void olpc_ec_wakeup_set(u16 value)
{
Expand Down Expand Up @@ -280,96 +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(void)
{
return olpc_ec_mask_write(ec_wakeup_mask);
}

static bool __init check_ofw_architecture(struct device_node *root)
{
const char *olpc_arch;
Expand Down Expand Up @@ -424,8 +317,59 @@ static int __init add_xo1_platform_devices(void)
return 0;
}

static struct syscore_ops olpc_syscore_ops = {
.suspend = olpc_ec_suspend,
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 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
* <http://dev.laptop.org/ticket/1835>.
*/
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 = {
.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,
};

static int __init olpc_init(void)
Expand All @@ -435,41 +379,31 @@ 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 */
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 */
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. */
if (olpc_platform_info.boardrev < olpc_board_pre(0xd0) &&
!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();
if (r)
return r;
}

register_syscore_ops(&olpc_syscore_ops);
setup_debugfs();

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/libertas/if_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/olpc-ec.h>

#ifdef CONFIG_OLPC
#include <asm/olpc.h>
Expand Down
1 change: 1 addition & 0 deletions drivers/platform/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
#

obj-$(CONFIG_X86) += x86/
obj-$(CONFIG_OLPC) += olpc/
4 changes: 4 additions & 0 deletions drivers/platform/olpc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#
# OLPC XO platform-specific drivers
#
obj-$(CONFIG_OLPC) += olpc-ec.o
Loading

0 comments on commit fc6bdb5

Please sign in to comment.