1
2
3
4
5
6
7
8
9
10
11
12#include <linux/completion.h>
13#include <linux/ctype.h>
14#include <linux/delay.h>
15#include <linux/gpio/consumer.h>
16#include <linux/input.h>
17#include <linux/kfifo.h>
18#include <linux/module.h>
19#include <linux/olpc-ec.h>
20#include <linux/platform_device.h>
21#include <linux/power_supply.h>
22#include <linux/reboot.h>
23#include <linux/slab.h>
24#include <linux/spinlock.h>
25#include <linux/spi/spi.h>
26
27struct ec_cmd_t {
28 u8 cmd;
29 u8 bytes_returned;
30};
31
32enum ec_chan_t {
33 CHAN_NONE = 0,
34 CHAN_SWITCH,
35 CHAN_CMD_RESP,
36 CHAN_KEYBOARD,
37 CHAN_TOUCHPAD,
38 CHAN_EVENT,
39 CHAN_DEBUG,
40 CHAN_CMD_ERROR,
41};
42
43
44
45
46#define EVENT_AC_CHANGE 1
47#define EVENT_BATTERY_STATUS 2
48#define EVENT_BATTERY_CRITICAL 3
49#define EVENT_BATTERY_SOC_CHANGE 4
50#define EVENT_BATTERY_ERROR 5
51#define EVENT_POWER_PRESSED 6
52#define EVENT_POWER_PRESS_WAKE 7
53#define EVENT_TIMED_HOST_WAKE 8
54#define EVENT_OLS_HIGH_LIMIT 9
55#define EVENT_OLS_LOW_LIMIT 10
56
57
58
59
60
61#define CMD_GET_API_VERSION 0x08
62#define CMD_READ_VOLTAGE 0x10
63#define CMD_READ_CURRENT 0x11
64#define CMD_READ_ACR 0x12
65#define CMD_READ_BATT_TEMPERATURE 0x13
66#define CMD_READ_AMBIENT_TEMPERATURE 0x14
67#define CMD_READ_BATTERY_STATUS 0x15
68#define CMD_READ_SOC 0x16
69#define CMD_READ_GAUGE_ID 0x17
70#define CMD_READ_GAUGE_DATA 0x18
71#define CMD_READ_BOARD_ID 0x19
72#define CMD_READ_BATT_ERR_CODE 0x1f
73#define CMD_SET_DCON_POWER 0x26
74#define CMD_RESET_EC 0x28
75#define CMD_READ_BATTERY_TYPE 0x2c
76#define CMD_SET_AUTOWAK 0x33
77#define CMD_SET_EC_WAKEUP_TIMER 0x36
78#define CMD_READ_EXT_SCI_MASK 0x37
79#define CMD_WRITE_EXT_SCI_MASK 0x38
80#define CMD_CLEAR_EC_WAKEUP_TIMER 0x39
81#define CMD_ENABLE_RUNIN_DISCHARGE 0x3B
82#define CMD_DISABLE_RUNIN_DISCHARGE 0x3C
83#define CMD_READ_MPPT_ACTIVE 0x3d
84#define CMD_READ_MPPT_LIMIT 0x3e
85#define CMD_SET_MPPT_LIMIT 0x3f
86#define CMD_DISABLE_MPPT 0x40
87#define CMD_ENABLE_MPPT 0x41
88#define CMD_READ_VIN 0x42
89#define CMD_EXT_SCI_QUERY 0x43
90#define RSP_KEYBOARD_DATA 0x48
91#define RSP_TOUCHPAD_DATA 0x49
92#define CMD_GET_FW_VERSION 0x4a
93#define CMD_POWER_CYCLE 0x4b
94#define CMD_POWER_OFF 0x4c
95#define CMD_RESET_EC_SOFT 0x4d
96#define CMD_READ_GAUGE_U16 0x4e
97#define CMD_ENABLE_MOUSE 0x4f
98#define CMD_ECHO 0x52
99#define CMD_GET_FW_DATE 0x53
100#define CMD_GET_FW_USER 0x54
101#define CMD_TURN_OFF_POWER 0x55
102#define CMD_READ_OLS 0x56
103#define CMD_OLS_SMT_LEDON 0x57
104#define CMD_OLS_SMT_LEDOFF 0x58
105#define CMD_START_OLS_ASSY 0x59
106#define CMD_STOP_OLS_ASSY 0x5a
107#define CMD_OLS_SMTTEST_STOP 0x5b
108#define CMD_READ_VIN_SCALED 0x5c
109#define CMD_READ_BAT_MIN_W 0x5d
110#define CMD_READ_BAR_MAX_W 0x5e
111#define CMD_RESET_BAT_MINMAX_W 0x5f
112#define CMD_READ_LOCATION 0x60
113#define CMD_WRITE_LOCATION 0x61
114#define CMD_KEYBOARD_CMD 0x62
115#define CMD_TOUCHPAD_CMD 0x63
116#define CMD_GET_FW_HASH 0x64
117#define CMD_SUSPEND_HINT 0x65
118#define CMD_ENABLE_WAKE_TIMER 0x66
119#define CMD_SET_WAKE_TIMER 0x67
120#define CMD_ENABLE_WAKE_AUTORESET 0x68
121#define CMD_OLS_SET_LIMITS 0x69
122#define CMD_OLS_GET_LIMITS 0x6a
123#define CMD_OLS_SET_CEILING 0x6b
124#define CMD_OLS_GET_CEILING 0x6c
125
126
127
128
129
130
131static const struct ec_cmd_t olpc_xo175_ec_cmds[] = {
132 { CMD_GET_API_VERSION, 1 },
133 { CMD_READ_VOLTAGE, 2 },
134 { CMD_READ_CURRENT, 2 },
135 { CMD_READ_ACR, 2 },
136 { CMD_READ_BATT_TEMPERATURE, 2 },
137 { CMD_READ_BATTERY_STATUS, 1 },
138 { CMD_READ_SOC, 1 },
139 { CMD_READ_GAUGE_ID, 8 },
140 { CMD_READ_GAUGE_DATA, 1 },
141 { CMD_READ_BOARD_ID, 2 },
142 { CMD_READ_BATT_ERR_CODE, 1 },
143 { CMD_SET_DCON_POWER, 0 },
144 { CMD_RESET_EC, 0 },
145 { CMD_READ_BATTERY_TYPE, 1 },
146 { CMD_ENABLE_RUNIN_DISCHARGE, 0 },
147 { CMD_DISABLE_RUNIN_DISCHARGE, 0 },
148 { CMD_READ_MPPT_ACTIVE, 1 },
149 { CMD_READ_MPPT_LIMIT, 1 },
150 { CMD_SET_MPPT_LIMIT, 0 },
151 { CMD_DISABLE_MPPT, 0 },
152 { CMD_ENABLE_MPPT, 0 },
153 { CMD_READ_VIN, 2 },
154 { CMD_GET_FW_VERSION, 16 },
155 { CMD_POWER_CYCLE, 0 },
156 { CMD_POWER_OFF, 0 },
157 { CMD_RESET_EC_SOFT, 0 },
158 { CMD_ECHO, 5 },
159 { CMD_GET_FW_DATE, 16 },
160 { CMD_GET_FW_USER, 16 },
161 { CMD_TURN_OFF_POWER, 0 },
162 { CMD_READ_OLS, 2 },
163 { CMD_OLS_SMT_LEDON, 0 },
164 { CMD_OLS_SMT_LEDOFF, 0 },
165 { CMD_START_OLS_ASSY, 0 },
166 { CMD_STOP_OLS_ASSY, 0 },
167 { CMD_OLS_SMTTEST_STOP, 0 },
168 { CMD_READ_VIN_SCALED, 2 },
169 { CMD_READ_BAT_MIN_W, 2 },
170 { CMD_READ_BAR_MAX_W, 2 },
171 { CMD_RESET_BAT_MINMAX_W, 0 },
172 { CMD_READ_LOCATION, 1 },
173 { CMD_WRITE_LOCATION, 0 },
174 { CMD_GET_FW_HASH, 16 },
175 { CMD_SUSPEND_HINT, 0 },
176 { CMD_ENABLE_WAKE_TIMER, 0 },
177 { CMD_SET_WAKE_TIMER, 0 },
178 { CMD_ENABLE_WAKE_AUTORESET, 0 },
179 { CMD_OLS_SET_LIMITS, 0 },
180 { CMD_OLS_GET_LIMITS, 4 },
181 { CMD_OLS_SET_CEILING, 0 },
182 { CMD_OLS_GET_CEILING, 2 },
183 { CMD_READ_EXT_SCI_MASK, 2 },
184 { CMD_WRITE_EXT_SCI_MASK, 0 },
185
186 { }
187};
188
189#define EC_MAX_CMD_DATA_LEN 5
190#define EC_MAX_RESP_LEN 16
191
192#define LOG_BUF_SIZE 128
193
194#define PM_WAKEUP_TIME 1000
195
196#define EC_ALL_EVENTS GENMASK(15, 0)
197
198enum ec_state_t {
199 CMD_STATE_IDLE = 0,
200 CMD_STATE_WAITING_FOR_SWITCH,
201 CMD_STATE_CMD_IN_TX_FIFO,
202 CMD_STATE_CMD_SENT,
203 CMD_STATE_RESP_RECEIVED,
204 CMD_STATE_ERROR_RECEIVED,
205};
206
207struct olpc_xo175_ec_cmd {
208 u8 command;
209 u8 nr_args;
210 u8 data_len;
211 u8 args[EC_MAX_CMD_DATA_LEN];
212};
213
214struct olpc_xo175_ec_resp {
215 u8 channel;
216 u8 byte;
217};
218
219struct olpc_xo175_ec {
220 bool suspended;
221
222
223 struct spi_device *spi;
224 struct spi_transfer xfer;
225 struct spi_message msg;
226 union {
227 struct olpc_xo175_ec_cmd cmd;
228 struct olpc_xo175_ec_resp resp;
229 } tx_buf, rx_buf;
230
231
232 struct gpio_desc *gpio_cmd;
233
234
235 spinlock_t cmd_state_lock;
236 int cmd_state;
237 bool cmd_running;
238 struct completion cmd_done;
239 struct olpc_xo175_ec_cmd cmd;
240 u8 resp_data[EC_MAX_RESP_LEN];
241 int expected_resp_len;
242 int resp_len;
243
244
245 struct input_dev *pwrbtn;
246
247
248 char logbuf[LOG_BUF_SIZE];
249 int logbuf_len;
250};
251
252static struct platform_device *olpc_ec;
253
254static int olpc_xo175_ec_resp_len(u8 cmd)
255{
256 const struct ec_cmd_t *p;
257
258 for (p = olpc_xo175_ec_cmds; p->cmd; p++) {
259 if (p->cmd == cmd)
260 return p->bytes_returned;
261 }
262
263 return -EINVAL;
264}
265
266static void olpc_xo175_ec_flush_logbuf(struct olpc_xo175_ec *priv)
267{
268 dev_dbg(&priv->spi->dev, "got debug string [%*pE]\n",
269 priv->logbuf_len, priv->logbuf);
270 priv->logbuf_len = 0;
271}
272
273static void olpc_xo175_ec_complete(void *arg);
274
275static void olpc_xo175_ec_send_command(struct olpc_xo175_ec *priv, void *cmd,
276 size_t cmdlen)
277{
278 int ret;
279
280 memcpy(&priv->tx_buf, cmd, cmdlen);
281 priv->xfer.len = cmdlen;
282
283 spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1);
284
285 priv->msg.complete = olpc_xo175_ec_complete;
286 priv->msg.context = priv;
287
288 ret = spi_async(priv->spi, &priv->msg);
289 if (ret)
290 dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret);
291}
292
293static void olpc_xo175_ec_read_packet(struct olpc_xo175_ec *priv)
294{
295 u8 nonce[] = {0xA5, 0x5A};
296
297 olpc_xo175_ec_send_command(priv, nonce, sizeof(nonce));
298}
299
300static void olpc_xo175_ec_complete(void *arg)
301{
302 struct olpc_xo175_ec *priv = arg;
303 struct device *dev = &priv->spi->dev;
304 struct power_supply *psy;
305 unsigned long flags;
306 u8 channel;
307 u8 byte;
308 int ret;
309
310 ret = priv->msg.status;
311 if (ret) {
312 dev_err(dev, "SPI transfer failed: %d\n", ret);
313
314 spin_lock_irqsave(&priv->cmd_state_lock, flags);
315 if (priv->cmd_running) {
316 priv->resp_len = 0;
317 priv->cmd_state = CMD_STATE_ERROR_RECEIVED;
318 complete(&priv->cmd_done);
319 }
320 spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
321
322 if (ret != -EINTR)
323 olpc_xo175_ec_read_packet(priv);
324
325 return;
326 }
327
328 channel = priv->rx_buf.resp.channel;
329 byte = priv->rx_buf.resp.byte;
330
331 switch (channel) {
332 case CHAN_NONE:
333 spin_lock_irqsave(&priv->cmd_state_lock, flags);
334
335 if (!priv->cmd_running) {
336
337 dev_err(dev, "spurious FIFO read packet\n");
338 spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
339 return;
340 }
341
342 priv->cmd_state = CMD_STATE_CMD_SENT;
343 if (!priv->expected_resp_len)
344 complete(&priv->cmd_done);
345 olpc_xo175_ec_read_packet(priv);
346
347 spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
348 return;
349
350 case CHAN_SWITCH:
351 spin_lock_irqsave(&priv->cmd_state_lock, flags);
352
353 if (!priv->cmd_running) {
354
355 dev_err(dev, "spurious SWITCH packet\n");
356 memset(&priv->cmd, 0, sizeof(priv->cmd));
357 priv->cmd.command = CMD_ECHO;
358 }
359
360 priv->cmd_state = CMD_STATE_CMD_IN_TX_FIFO;
361
362
363 gpiod_set_value_cansleep(priv->gpio_cmd, 0);
364 olpc_xo175_ec_send_command(priv, &priv->cmd, sizeof(priv->cmd));
365
366 spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
367 return;
368
369 case CHAN_CMD_RESP:
370 spin_lock_irqsave(&priv->cmd_state_lock, flags);
371
372 if (!priv->cmd_running) {
373 dev_err(dev, "spurious response packet\n");
374 } else if (priv->resp_len >= priv->expected_resp_len) {
375 dev_err(dev, "too many response packets\n");
376 } else {
377 priv->resp_data[priv->resp_len++] = byte;
378 if (priv->resp_len == priv->expected_resp_len) {
379 priv->cmd_state = CMD_STATE_RESP_RECEIVED;
380 complete(&priv->cmd_done);
381 }
382 }
383
384 spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
385 break;
386
387 case CHAN_CMD_ERROR:
388 spin_lock_irqsave(&priv->cmd_state_lock, flags);
389
390 if (!priv->cmd_running) {
391 dev_err(dev, "spurious cmd error packet\n");
392 } else {
393 priv->resp_data[0] = byte;
394 priv->resp_len = 1;
395 priv->cmd_state = CMD_STATE_ERROR_RECEIVED;
396 complete(&priv->cmd_done);
397 }
398 spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
399 break;
400
401 case CHAN_KEYBOARD:
402 dev_warn(dev, "keyboard is not supported\n");
403 break;
404
405 case CHAN_TOUCHPAD:
406 dev_warn(dev, "touchpad is not supported\n");
407 break;
408
409 case CHAN_EVENT:
410 dev_dbg(dev, "got event %.2x\n", byte);
411 switch (byte) {
412 case EVENT_AC_CHANGE:
413 psy = power_supply_get_by_name("olpc-ac");
414 if (psy) {
415 power_supply_changed(psy);
416 power_supply_put(psy);
417 }
418 break;
419 case EVENT_BATTERY_STATUS:
420 case EVENT_BATTERY_CRITICAL:
421 case EVENT_BATTERY_SOC_CHANGE:
422 case EVENT_BATTERY_ERROR:
423 psy = power_supply_get_by_name("olpc-battery");
424 if (psy) {
425 power_supply_changed(psy);
426 power_supply_put(psy);
427 }
428 break;
429 case EVENT_POWER_PRESSED:
430 input_report_key(priv->pwrbtn, KEY_POWER, 1);
431 input_sync(priv->pwrbtn);
432 input_report_key(priv->pwrbtn, KEY_POWER, 0);
433 input_sync(priv->pwrbtn);
434
435 case EVENT_POWER_PRESS_WAKE:
436 case EVENT_TIMED_HOST_WAKE:
437 pm_wakeup_event(priv->pwrbtn->dev.parent,
438 PM_WAKEUP_TIME);
439 break;
440 default:
441 dev_dbg(dev, "ignored unknown event %.2x\n", byte);
442 break;
443 }
444 break;
445
446 case CHAN_DEBUG:
447 if (byte == '\n') {
448 olpc_xo175_ec_flush_logbuf(priv);
449 } else if (isprint(byte)) {
450 priv->logbuf[priv->logbuf_len++] = byte;
451 if (priv->logbuf_len == LOG_BUF_SIZE)
452 olpc_xo175_ec_flush_logbuf(priv);
453 }
454 break;
455
456 default:
457 dev_warn(dev, "unknown channel: %d, %.2x\n", channel, byte);
458 break;
459 }
460
461
462 olpc_xo175_ec_read_packet(priv);
463}
464
465
466
467
468
469
470
471
472
473static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp,
474 size_t resp_len, void *ec_cb_arg)
475{
476 struct olpc_xo175_ec *priv = ec_cb_arg;
477 struct device *dev = &priv->spi->dev;
478 unsigned long flags;
479 size_t nr_bytes;
480 int ret = 0;
481
482 dev_dbg(dev, "CMD %x, %zd bytes expected\n", cmd, resp_len);
483
484 if (inlen > 5) {
485 dev_err(dev, "command len %zd too big!\n", resp_len);
486 return -EOVERFLOW;
487 }
488
489
490 if (WARN_ON(priv->suspended))
491 return -EBUSY;
492
493
494 ret = olpc_xo175_ec_resp_len(cmd);
495 if (ret < 0) {
496 dev_err_ratelimited(dev, "unknown command 0x%x\n", cmd);
497
498
499
500
501
502
503 if (resp_len > sizeof(priv->resp_data)) {
504 dev_err(dev, "response too big: %zd!\n", resp_len);
505 return -EOVERFLOW;
506 }
507 nr_bytes = resp_len;
508 } else {
509 nr_bytes = (size_t)ret;
510 ret = 0;
511 }
512 resp_len = min(resp_len, nr_bytes);
513
514 spin_lock_irqsave(&priv->cmd_state_lock, flags);
515
516
517 init_completion(&priv->cmd_done);
518 priv->cmd_running = true;
519 priv->cmd_state = CMD_STATE_WAITING_FOR_SWITCH;
520 memset(&priv->cmd, 0, sizeof(priv->cmd));
521 priv->cmd.command = cmd;
522 priv->cmd.nr_args = inlen;
523 priv->cmd.data_len = 0;
524 memcpy(priv->cmd.args, inbuf, inlen);
525 priv->expected_resp_len = nr_bytes;
526 priv->resp_len = 0;
527
528
529 gpiod_set_value_cansleep(priv->gpio_cmd, 1);
530
531 spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
532
533
534 if (!wait_for_completion_timeout(&priv->cmd_done,
535 msecs_to_jiffies(4000))) {
536 dev_err(dev, "EC cmd error: timeout in STATE %d\n",
537 priv->cmd_state);
538 gpiod_set_value_cansleep(priv->gpio_cmd, 0);
539 spi_slave_abort(priv->spi);
540 olpc_xo175_ec_read_packet(priv);
541 return -ETIMEDOUT;
542 }
543
544 spin_lock_irqsave(&priv->cmd_state_lock, flags);
545
546
547 if (priv->cmd_state == CMD_STATE_ERROR_RECEIVED) {
548
549 dev_err(dev, "command 0x%x returned error 0x%x\n",
550 cmd, priv->resp_data[0]);
551 ret = -EREMOTEIO;
552 } else if (priv->resp_len != nr_bytes) {
553 dev_err(dev, "command 0x%x returned %d bytes, expected %zd bytes\n",
554 cmd, priv->resp_len, nr_bytes);
555 ret = -EREMOTEIO;
556 } else {
557
558
559
560
561
562
563 memcpy(resp, priv->resp_data, resp_len);
564 }
565
566
567 gpiod_set_value_cansleep(priv->gpio_cmd, 0);
568 priv->cmd_running = false;
569
570 spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
571
572 return ret;
573}
574
575static int olpc_xo175_ec_set_event_mask(unsigned int mask)
576{
577 u8 args[2];
578
579 args[0] = mask >> 0;
580 args[1] = mask >> 8;
581 return olpc_ec_cmd(CMD_WRITE_EXT_SCI_MASK, args, 2, NULL, 0);
582}
583
584static void olpc_xo175_ec_power_off(void)
585{
586 while (1) {
587 olpc_ec_cmd(CMD_POWER_OFF, NULL, 0, NULL, 0);
588 mdelay(1000);
589 }
590}
591
592static int __maybe_unused olpc_xo175_ec_suspend(struct device *dev)
593{
594 struct olpc_xo175_ec *priv = dev_get_drvdata(dev);
595 static struct {
596 u8 suspend;
597 u32 suspend_count;
598 } __packed hintargs;
599 static unsigned int suspend_count;
600
601
602
603
604
605
606 hintargs.suspend = 1;
607 hintargs.suspend_count = suspend_count++;
608 olpc_ec_cmd(CMD_SUSPEND_HINT, (void *)&hintargs, sizeof(hintargs),
609 NULL, 0);
610
611
612
613
614
615
616 priv->suspended = true;
617
618 return 0;
619}
620
621static int __maybe_unused olpc_xo175_ec_resume_noirq(struct device *dev)
622{
623 struct olpc_xo175_ec *priv = dev_get_drvdata(dev);
624
625 priv->suspended = false;
626
627 return 0;
628}
629
630static int __maybe_unused olpc_xo175_ec_resume(struct device *dev)
631{
632 u8 x = 0;
633
634
635
636
637
638
639 olpc_ec_cmd(CMD_SUSPEND_HINT, &x, 1, NULL, 0);
640
641
642 olpc_xo175_ec_set_event_mask(EC_ALL_EVENTS);
643
644 return 0;
645}
646
647static struct olpc_ec_driver olpc_xo175_ec_driver = {
648 .ec_cmd = olpc_xo175_ec_cmd,
649};
650
651static int olpc_xo175_ec_remove(struct spi_device *spi)
652{
653 if (pm_power_off == olpc_xo175_ec_power_off)
654 pm_power_off = NULL;
655
656 spi_slave_abort(spi);
657
658 platform_device_unregister(olpc_ec);
659 olpc_ec = NULL;
660
661 return 0;
662}
663
664static int olpc_xo175_ec_probe(struct spi_device *spi)
665{
666 struct olpc_xo175_ec *priv;
667 int ret;
668
669 if (olpc_ec) {
670 dev_err(&spi->dev, "OLPC EC already registered.\n");
671 return -EBUSY;
672 }
673
674 priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
675 if (!priv)
676 return -ENOMEM;
677
678 priv->gpio_cmd = devm_gpiod_get(&spi->dev, "cmd", GPIOD_OUT_LOW);
679 if (IS_ERR(priv->gpio_cmd)) {
680 dev_err(&spi->dev, "failed to get cmd gpio: %ld\n",
681 PTR_ERR(priv->gpio_cmd));
682 return PTR_ERR(priv->gpio_cmd);
683 }
684
685 priv->spi = spi;
686
687 spin_lock_init(&priv->cmd_state_lock);
688 priv->cmd_state = CMD_STATE_IDLE;
689 init_completion(&priv->cmd_done);
690
691 priv->logbuf_len = 0;
692
693
694 priv->pwrbtn = devm_input_allocate_device(&spi->dev);
695 if (!priv->pwrbtn)
696 return -ENOMEM;
697 priv->pwrbtn->name = "Power Button";
698 priv->pwrbtn->dev.parent = &spi->dev;
699 input_set_capability(priv->pwrbtn, EV_KEY, KEY_POWER);
700 ret = input_register_device(priv->pwrbtn);
701 if (ret) {
702 dev_err(&spi->dev, "error registering input device: %d\n", ret);
703 return ret;
704 }
705
706 spi_set_drvdata(spi, priv);
707
708 priv->xfer.rx_buf = &priv->rx_buf;
709 priv->xfer.tx_buf = &priv->tx_buf;
710
711 olpc_xo175_ec_read_packet(priv);
712
713 olpc_ec_driver_register(&olpc_xo175_ec_driver, priv);
714 olpc_ec = platform_device_register_resndata(&spi->dev, "olpc-ec", -1,
715 NULL, 0, NULL, 0);
716
717
718 olpc_xo175_ec_set_event_mask(EC_ALL_EVENTS);
719
720 if (pm_power_off == NULL)
721 pm_power_off = olpc_xo175_ec_power_off;
722
723 dev_info(&spi->dev, "OLPC XO-1.75 Embedded Controller driver\n");
724
725 return 0;
726}
727
728static const struct dev_pm_ops olpc_xo175_ec_pm_ops = {
729 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, olpc_xo175_ec_resume_noirq)
730 SET_RUNTIME_PM_OPS(olpc_xo175_ec_suspend, olpc_xo175_ec_resume, NULL)
731};
732
733static const struct of_device_id olpc_xo175_ec_of_match[] = {
734 { .compatible = "olpc,xo1.75-ec" },
735 { }
736};
737MODULE_DEVICE_TABLE(of, olpc_xo175_ec_of_match);
738
739static const struct spi_device_id olpc_xo175_ec_id_table[] = {
740 { "xo1.75-ec", 0 },
741 {}
742};
743MODULE_DEVICE_TABLE(spi, olpc_xo175_ec_id_table);
744
745static struct spi_driver olpc_xo175_ec_spi_driver = {
746 .driver = {
747 .name = "olpc-xo175-ec",
748 .of_match_table = olpc_xo175_ec_of_match,
749 .pm = &olpc_xo175_ec_pm_ops,
750 },
751 .probe = olpc_xo175_ec_probe,
752 .remove = olpc_xo175_ec_remove,
753};
754module_spi_driver(olpc_xo175_ec_spi_driver);
755
756MODULE_DESCRIPTION("OLPC XO-1.75 Embedded Controller driver");
757MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
758MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
759MODULE_LICENSE("GPL");
760