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>
3130struct olpc_platform_t olpc_platform_info ;
3231EXPORT_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). */
4634static 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 ;
200185err :
201- spin_unlock_irqrestore (& ec_lock , flags );
202186 return ret ;
203187}
204- EXPORT_SYMBOL_GPL (olpc_ec_cmd );
205188
206189void olpc_ec_wakeup_set (u16 value )
207190{
@@ -280,96 +263,6 @@ int olpc_ec_sci_query(u16 *sci_value)
280263}
281264EXPORT_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-
373266static 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
431375static 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
0 commit comments