14
14
#include <linux/init.h>
15
15
#include <linux/module.h>
16
16
#include <linux/delay.h>
17
- #include <linux/spinlock.h>
18
17
#include <linux/io.h>
19
18
#include <linux/string.h>
20
19
#include <linux/platform_device.h>
21
20
#include <linux/of.h>
22
21
#include <linux/syscore_ops.h>
23
- #include <linux/debugfs.h>
24
22
#include <linux/mutex.h>
23
+ #include <linux/olpc-ec.h>
25
24
26
25
#include <asm/geode.h>
27
26
#include <asm/setup.h>
31
30
struct olpc_platform_t olpc_platform_info ;
32
31
EXPORT_SYMBOL_GPL (olpc_platform_info );
33
32
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
-
45
33
/* EC event mask to be applied during suspend (defining wakeup sources). */
46
34
static u16 ec_wakeup_mask ;
47
35
@@ -125,16 +113,13 @@ static int __wait_on_obf(unsigned int line, unsigned int port, int desired)
125
113
* <http://wiki.laptop.org/go/Ec_specification>. Unfortunately, while
126
114
* OpenFirmware's source is available, the EC's is not.
127
115
*/
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 )
130
118
{
131
- unsigned long flags ;
132
119
int ret = - EIO ;
133
120
int i ;
134
121
int restarts = 0 ;
135
122
136
- spin_lock_irqsave (& ec_lock , flags );
137
-
138
123
/* Clear OBF */
139
124
for (i = 0 ; i < 10 && (obf_status (0x6c ) == 1 ); i ++ )
140
125
inb (0x68 );
@@ -198,10 +183,8 @@ int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
198
183
199
184
ret = 0 ;
200
185
err :
201
- spin_unlock_irqrestore (& ec_lock , flags );
202
186
return ret ;
203
187
}
204
- EXPORT_SYMBOL_GPL (olpc_ec_cmd );
205
188
206
189
void olpc_ec_wakeup_set (u16 value )
207
190
{
@@ -280,96 +263,6 @@ int olpc_ec_sci_query(u16 *sci_value)
280
263
}
281
264
EXPORT_SYMBOL_GPL (olpc_ec_sci_query );
282
265
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
-
373
266
static bool __init check_ofw_architecture (struct device_node * root )
374
267
{
375
268
const char * olpc_arch ;
@@ -424,8 +317,59 @@ static int __init add_xo1_platform_devices(void)
424
317
return 0 ;
425
318
}
426
319
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 ,
429
373
};
430
374
431
375
static int __init olpc_init (void )
@@ -435,41 +379,31 @@ static int __init olpc_init(void)
435
379
if (!olpc_ofw_present () || !platform_detect ())
436
380
return 0 ;
437
381
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 );
439
388
440
389
/* assume B1 and above models always have a DCON */
441
390
if (olpc_board_at_least (olpc_board (0xb1 )))
442
391
olpc_platform_info .flags |= OLPC_F_DCON ;
443
392
444
- /* get the EC revision */
445
- olpc_ec_cmd (EC_FIRMWARE_REV , NULL , 0 ,
446
- (unsigned char * ) & olpc_platform_info .ecver , 1 );
447
-
448
393
#ifdef CONFIG_PCI_OLPC
449
394
/* If the VSA exists let it emulate PCI, if not emulate in kernel.
450
395
* XO-1 only. */
451
396
if (olpc_platform_info .boardrev < olpc_board_pre (0xd0 ) &&
452
397
!cs5535_has_vsa2 ())
453
398
x86_init .pci .arch_init = pci_olpc_init ;
454
399
#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 );
463
400
464
401
if (olpc_platform_info .boardrev < olpc_board_pre (0xd0 )) { /* XO-1 */
465
402
r = add_xo1_platform_devices ();
466
403
if (r )
467
404
return r ;
468
405
}
469
406
470
- register_syscore_ops (& olpc_syscore_ops );
471
- setup_debugfs ();
472
-
473
407
return 0 ;
474
408
}
475
409
0 commit comments