]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/macintosh/smu.c
[PATCH] sem2mutex: fs/
[mirror_ubuntu-artful-kernel.git] / drivers / macintosh / smu.c
CommitLineData
1da177e4
LT
1/*
2 * PowerMac G5 SMU driver
3 *
4 * Copyright 2004 J. Mayer <l_indien@magic.fr>
5 * Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
6 *
7 * Released under the term of the GNU GPL v2.
8 */
9
10/*
1da177e4 11 * TODO:
0365ba7f
BH
12 * - maybe add timeout to commands ?
13 * - blocking version of time functions
14 * - polling version of i2c commands (including timer that works with
15 * interrutps off)
16 * - maybe avoid some data copies with i2c by directly using the smu cmd
17 * buffer and a lower level internal interface
18 * - understand SMU -> CPU events and implement reception of them via
19 * the userland interface
1da177e4
LT
20 */
21
22#include <linux/config.h>
23#include <linux/types.h>
24#include <linux/kernel.h>
25#include <linux/device.h>
26#include <linux/dmapool.h>
27#include <linux/bootmem.h>
28#include <linux/vmalloc.h>
29#include <linux/highmem.h>
30#include <linux/jiffies.h>
31#include <linux/interrupt.h>
32#include <linux/rtc.h>
0365ba7f
BH
33#include <linux/completion.h>
34#include <linux/miscdevice.h>
35#include <linux/delay.h>
36#include <linux/sysdev.h>
37#include <linux/poll.h>
1da177e4
LT
38
39#include <asm/byteorder.h>
40#include <asm/io.h>
41#include <asm/prom.h>
42#include <asm/machdep.h>
43#include <asm/pmac_feature.h>
44#include <asm/smu.h>
45#include <asm/sections.h>
46#include <asm/abs_addr.h>
0365ba7f
BH
47#include <asm/uaccess.h>
48#include <asm/of_device.h>
49
183d0202 50#define VERSION "0.7"
0365ba7f 51#define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp."
1da177e4 52
0365ba7f 53#undef DEBUG_SMU
1da177e4
LT
54
55#ifdef DEBUG_SMU
1beb6a7d 56#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0)
1da177e4
LT
57#else
58#define DPRINTK(fmt, args...) do { } while (0)
59#endif
60
61/*
62 * This is the command buffer passed to the SMU hardware
63 */
0365ba7f
BH
64#define SMU_MAX_DATA 254
65
1da177e4
LT
66struct smu_cmd_buf {
67 u8 cmd;
68 u8 length;
0365ba7f 69 u8 data[SMU_MAX_DATA];
1da177e4
LT
70};
71
72struct smu_device {
73 spinlock_t lock;
74 struct device_node *of_node;
0365ba7f
BH
75 struct of_device *of_dev;
76 int doorbell; /* doorbell gpio */
1da177e4 77 u32 __iomem *db_buf; /* doorbell buffer */
0365ba7f
BH
78 int db_irq;
79 int msg;
80 int msg_irq;
1da177e4
LT
81 struct smu_cmd_buf *cmd_buf; /* command buffer virtual */
82 u32 cmd_buf_abs; /* command buffer absolute */
0365ba7f
BH
83 struct list_head cmd_list;
84 struct smu_cmd *cmd_cur; /* pending command */
85 struct list_head cmd_i2c_list;
86 struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */
87 struct timer_list i2c_timer;
1da177e4
LT
88};
89
90/*
91 * I don't think there will ever be more than one SMU, so
92 * for now, just hard code that
93 */
94static struct smu_device *smu;
183d0202 95static DECLARE_MUTEX(smu_part_access);
0365ba7f 96
730745a5
BH
97static void smu_i2c_retry(unsigned long data);
98
1da177e4 99/*
0365ba7f 100 * SMU driver low level stuff
1da177e4 101 */
1da177e4 102
0365ba7f 103static void smu_start_cmd(void)
1da177e4 104{
0365ba7f
BH
105 unsigned long faddr, fend;
106 struct smu_cmd *cmd;
1da177e4 107
0365ba7f
BH
108 if (list_empty(&smu->cmd_list))
109 return;
110
111 /* Fetch first command in queue */
112 cmd = list_entry(smu->cmd_list.next, struct smu_cmd, link);
113 smu->cmd_cur = cmd;
114 list_del(&cmd->link);
115
116 DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd,
117 cmd->data_len);
183d0202 118 DPRINTK("SMU: data buffer: %02x %02x %02x %02x %02x %02x %02x %02x\n",
0365ba7f 119 ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1],
183d0202
BH
120 ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3],
121 ((u8 *)cmd->data_buf)[4], ((u8 *)cmd->data_buf)[5],
122 ((u8 *)cmd->data_buf)[6], ((u8 *)cmd->data_buf)[7]);
0365ba7f
BH
123
124 /* Fill the SMU command buffer */
125 smu->cmd_buf->cmd = cmd->cmd;
126 smu->cmd_buf->length = cmd->data_len;
127 memcpy(smu->cmd_buf->data, cmd->data_buf, cmd->data_len);
128
129 /* Flush command and data to RAM */
130 faddr = (unsigned long)smu->cmd_buf;
131 fend = faddr + smu->cmd_buf->length + 2;
132 flush_inval_dcache_range(faddr, fend);
133
134 /* This isn't exactly a DMA mapping here, I suspect
1da177e4
LT
135 * the SMU is actually communicating with us via i2c to the
136 * northbridge or the CPU to access RAM.
137 */
0365ba7f 138 writel(smu->cmd_buf_abs, smu->db_buf);
1da177e4
LT
139
140 /* Ring the SMU doorbell */
0365ba7f 141 pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, smu->doorbell, 4);
1da177e4
LT
142}
143
0365ba7f
BH
144
145static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs)
1da177e4 146{
0365ba7f
BH
147 unsigned long flags;
148 struct smu_cmd *cmd;
149 void (*done)(struct smu_cmd *cmd, void *misc) = NULL;
150 void *misc = NULL;
151 u8 gpio;
152 int rc = 0;
1da177e4 153
0365ba7f
BH
154 /* SMU completed the command, well, we hope, let's make sure
155 * of it
156 */
157 spin_lock_irqsave(&smu->lock, flags);
1da177e4 158
0365ba7f 159 gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
a44fe13e
BH
160 if ((gpio & 7) != 7) {
161 spin_unlock_irqrestore(&smu->lock, flags);
0365ba7f 162 return IRQ_HANDLED;
a44fe13e 163 }
0365ba7f
BH
164
165 cmd = smu->cmd_cur;
166 smu->cmd_cur = NULL;
167 if (cmd == NULL)
168 goto bail;
169
170 if (rc == 0) {
171 unsigned long faddr;
172 int reply_len;
173 u8 ack;
174
175 /* CPU might have brought back the cache line, so we need
176 * to flush again before peeking at the SMU response. We
177 * flush the entire buffer for now as we haven't read the
178 * reply lenght (it's only 2 cache lines anyway)
179 */
180 faddr = (unsigned long)smu->cmd_buf;
181 flush_inval_dcache_range(faddr, faddr + 256);
182
183 /* Now check ack */
184 ack = (~cmd->cmd) & 0xff;
185 if (ack != smu->cmd_buf->cmd) {
186 DPRINTK("SMU: incorrect ack, want %x got %x\n",
187 ack, smu->cmd_buf->cmd);
188 rc = -EIO;
189 }
190 reply_len = rc == 0 ? smu->cmd_buf->length : 0;
191 DPRINTK("SMU: reply len: %d\n", reply_len);
192 if (reply_len > cmd->reply_len) {
193 printk(KERN_WARNING "SMU: reply buffer too small,"
194 "got %d bytes for a %d bytes buffer\n",
195 reply_len, cmd->reply_len);
196 reply_len = cmd->reply_len;
197 }
198 cmd->reply_len = reply_len;
199 if (cmd->reply_buf && reply_len)
200 memcpy(cmd->reply_buf, smu->cmd_buf->data, reply_len);
201 }
202
203 /* Now complete the command. Write status last in order as we lost
204 * ownership of the command structure as soon as it's no longer -1
205 */
206 done = cmd->done;
207 misc = cmd->misc;
208 mb();
209 cmd->status = rc;
210 bail:
211 /* Start next command if any */
212 smu_start_cmd();
213 spin_unlock_irqrestore(&smu->lock, flags);
214
215 /* Call command completion handler if any */
216 if (done)
217 done(cmd, misc);
218
219 /* It's an edge interrupt, nothing to do */
220 return IRQ_HANDLED;
1da177e4
LT
221}
222
0365ba7f
BH
223
224static irqreturn_t smu_msg_intr(int irq, void *arg, struct pt_regs *regs)
1da177e4 225{
0365ba7f
BH
226 /* I don't quite know what to do with this one, we seem to never
227 * receive it, so I suspect we have to arm it someway in the SMU
228 * to start getting events that way.
229 */
230
231 printk(KERN_INFO "SMU: message interrupt !\n");
1da177e4 232
0365ba7f
BH
233 /* It's an edge interrupt, nothing to do */
234 return IRQ_HANDLED;
235}
1da177e4 236
1da177e4 237
0365ba7f
BH
238/*
239 * Queued command management.
240 *
241 */
1da177e4 242
0365ba7f
BH
243int smu_queue_cmd(struct smu_cmd *cmd)
244{
245 unsigned long flags;
1da177e4 246
0365ba7f
BH
247 if (smu == NULL)
248 return -ENODEV;
249 if (cmd->data_len > SMU_MAX_DATA ||
250 cmd->reply_len > SMU_MAX_DATA)
251 return -EINVAL;
252
253 cmd->status = 1;
254 spin_lock_irqsave(&smu->lock, flags);
255 list_add_tail(&cmd->link, &smu->cmd_list);
256 if (smu->cmd_cur == NULL)
257 smu_start_cmd();
258 spin_unlock_irqrestore(&smu->lock, flags);
259
260 return 0;
1da177e4 261}
0365ba7f 262EXPORT_SYMBOL(smu_queue_cmd);
1da177e4 263
0365ba7f
BH
264
265int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command,
266 unsigned int data_len,
267 void (*done)(struct smu_cmd *cmd, void *misc),
268 void *misc, ...)
1da177e4 269{
0365ba7f
BH
270 struct smu_cmd *cmd = &scmd->cmd;
271 va_list list;
272 int i;
273
274 if (data_len > sizeof(scmd->buffer))
275 return -EINVAL;
276
277 memset(scmd, 0, sizeof(*scmd));
278 cmd->cmd = command;
279 cmd->data_len = data_len;
280 cmd->data_buf = scmd->buffer;
281 cmd->reply_len = sizeof(scmd->buffer);
282 cmd->reply_buf = scmd->buffer;
283 cmd->done = done;
284 cmd->misc = misc;
285
286 va_start(list, misc);
287 for (i = 0; i < data_len; ++i)
288 scmd->buffer[i] = (u8)va_arg(list, int);
289 va_end(list);
290
291 return smu_queue_cmd(cmd);
1da177e4 292}
0365ba7f 293EXPORT_SYMBOL(smu_queue_simple);
1da177e4 294
0365ba7f
BH
295
296void smu_poll(void)
1da177e4 297{
0365ba7f
BH
298 u8 gpio;
299
300 if (smu == NULL)
301 return;
302
303 gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
304 if ((gpio & 7) == 7)
305 smu_db_intr(smu->db_irq, smu, NULL);
1da177e4 306}
0365ba7f
BH
307EXPORT_SYMBOL(smu_poll);
308
1da177e4 309
0365ba7f 310void smu_done_complete(struct smu_cmd *cmd, void *misc)
1da177e4 311{
0365ba7f
BH
312 struct completion *comp = misc;
313
314 complete(comp);
1da177e4 315}
0365ba7f
BH
316EXPORT_SYMBOL(smu_done_complete);
317
1da177e4 318
0365ba7f 319void smu_spinwait_cmd(struct smu_cmd *cmd)
1da177e4 320{
0365ba7f
BH
321 while(cmd->status == 1)
322 smu_poll();
323}
324EXPORT_SYMBOL(smu_spinwait_cmd);
325
326
327/* RTC low level commands */
328static inline int bcd2hex (int n)
329{
330 return (((n & 0xf0) >> 4) * 10) + (n & 0xf);
1da177e4
LT
331}
332
0365ba7f
BH
333
334static inline int hex2bcd (int n)
1da177e4 335{
0365ba7f 336 return ((n / 10) << 4) + (n % 10);
1da177e4 337}
0365ba7f 338
1da177e4
LT
339
340static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf,
341 struct rtc_time *time)
342{
343 cmd_buf->cmd = 0x8e;
344 cmd_buf->length = 8;
345 cmd_buf->data[0] = 0x80;
346 cmd_buf->data[1] = hex2bcd(time->tm_sec);
347 cmd_buf->data[2] = hex2bcd(time->tm_min);
348 cmd_buf->data[3] = hex2bcd(time->tm_hour);
349 cmd_buf->data[4] = time->tm_wday;
350 cmd_buf->data[5] = hex2bcd(time->tm_mday);
351 cmd_buf->data[6] = hex2bcd(time->tm_mon) + 1;
352 cmd_buf->data[7] = hex2bcd(time->tm_year - 100);
353}
354
1da177e4 355
0365ba7f 356int smu_get_rtc_time(struct rtc_time *time, int spinwait)
1da177e4 357{
0365ba7f 358 struct smu_simple_cmd cmd;
1da177e4
LT
359 int rc;
360
361 if (smu == NULL)
362 return -ENODEV;
363
364 memset(time, 0, sizeof(struct rtc_time));
0365ba7f
BH
365 rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 1, NULL, NULL,
366 SMU_CMD_RTC_GET_DATETIME);
367 if (rc)
368 return rc;
369 smu_spinwait_simple(&cmd);
1da177e4 370
0365ba7f
BH
371 time->tm_sec = bcd2hex(cmd.buffer[0]);
372 time->tm_min = bcd2hex(cmd.buffer[1]);
373 time->tm_hour = bcd2hex(cmd.buffer[2]);
374 time->tm_wday = bcd2hex(cmd.buffer[3]);
375 time->tm_mday = bcd2hex(cmd.buffer[4]);
376 time->tm_mon = bcd2hex(cmd.buffer[5]) - 1;
377 time->tm_year = bcd2hex(cmd.buffer[6]) + 100;
378
379 return 0;
1da177e4
LT
380}
381
0365ba7f
BH
382
383int smu_set_rtc_time(struct rtc_time *time, int spinwait)
1da177e4 384{
0365ba7f 385 struct smu_simple_cmd cmd;
1da177e4
LT
386 int rc;
387
388 if (smu == NULL)
389 return -ENODEV;
390
0365ba7f
BH
391 rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 8, NULL, NULL,
392 SMU_CMD_RTC_SET_DATETIME,
393 hex2bcd(time->tm_sec),
394 hex2bcd(time->tm_min),
395 hex2bcd(time->tm_hour),
396 time->tm_wday,
397 hex2bcd(time->tm_mday),
398 hex2bcd(time->tm_mon) + 1,
399 hex2bcd(time->tm_year - 100));
400 if (rc)
401 return rc;
402 smu_spinwait_simple(&cmd);
1da177e4 403
0365ba7f 404 return 0;
1da177e4
LT
405}
406
0365ba7f 407
1da177e4
LT
408void smu_shutdown(void)
409{
0365ba7f 410 struct smu_simple_cmd cmd;
1da177e4
LT
411
412 if (smu == NULL)
413 return;
414
0365ba7f
BH
415 if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 9, NULL, NULL,
416 'S', 'H', 'U', 'T', 'D', 'O', 'W', 'N', 0))
417 return;
418 smu_spinwait_simple(&cmd);
1da177e4
LT
419 for (;;)
420 ;
1da177e4
LT
421}
422
0365ba7f 423
1da177e4
LT
424void smu_restart(void)
425{
0365ba7f 426 struct smu_simple_cmd cmd;
1da177e4
LT
427
428 if (smu == NULL)
429 return;
430
0365ba7f
BH
431 if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, NULL, NULL,
432 'R', 'E', 'S', 'T', 'A', 'R', 'T', 0))
433 return;
434 smu_spinwait_simple(&cmd);
1da177e4
LT
435 for (;;)
436 ;
1da177e4
LT
437}
438
0365ba7f 439
1da177e4
LT
440int smu_present(void)
441{
442 return smu != NULL;
443}
0365ba7f 444EXPORT_SYMBOL(smu_present);
1da177e4
LT
445
446
183d0202 447int __init smu_init (void)
1da177e4
LT
448{
449 struct device_node *np;
450 u32 *data;
451
452 np = of_find_node_by_type(NULL, "smu");
453 if (np == NULL)
454 return -ENODEV;
455
0365ba7f
BH
456 printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR);
457
1da177e4
LT
458 if (smu_cmdbuf_abs == 0) {
459 printk(KERN_ERR "SMU: Command buffer not allocated !\n");
460 return -EINVAL;
461 }
462
463 smu = alloc_bootmem(sizeof(struct smu_device));
464 if (smu == NULL)
465 return -ENOMEM;
466 memset(smu, 0, sizeof(*smu));
467
468 spin_lock_init(&smu->lock);
0365ba7f
BH
469 INIT_LIST_HEAD(&smu->cmd_list);
470 INIT_LIST_HEAD(&smu->cmd_i2c_list);
1da177e4 471 smu->of_node = np;
0365ba7f
BH
472 smu->db_irq = NO_IRQ;
473 smu->msg_irq = NO_IRQ;
0365ba7f 474
1da177e4
LT
475 /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a
476 * 32 bits value safely
477 */
478 smu->cmd_buf_abs = (u32)smu_cmdbuf_abs;
479 smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs);
480
481 np = of_find_node_by_name(NULL, "smu-doorbell");
482 if (np == NULL) {
483 printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n");
484 goto fail;
485 }
486 data = (u32 *)get_property(np, "reg", NULL);
1da177e4 487 if (data == NULL) {
0365ba7f 488 of_node_put(np);
1da177e4
LT
489 printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
490 goto fail;
491 }
492
493 /* Current setup has one doorbell GPIO that does both doorbell
494 * and ack. GPIOs are at 0x50, best would be to find that out
495 * in the device-tree though.
496 */
0365ba7f
BH
497 smu->doorbell = *data;
498 if (smu->doorbell < 0x50)
499 smu->doorbell += 0x50;
500 if (np->n_intrs > 0)
501 smu->db_irq = np->intrs[0].line;
502
503 of_node_put(np);
504
505 /* Now look for the smu-interrupt GPIO */
506 do {
507 np = of_find_node_by_name(NULL, "smu-interrupt");
508 if (np == NULL)
509 break;
510 data = (u32 *)get_property(np, "reg", NULL);
511 if (data == NULL) {
512 of_node_put(np);
513 break;
514 }
515 smu->msg = *data;
516 if (smu->msg < 0x50)
517 smu->msg += 0x50;
518 if (np->n_intrs > 0)
519 smu->msg_irq = np->intrs[0].line;
520 of_node_put(np);
521 } while(0);
1da177e4
LT
522
523 /* Doorbell buffer is currently hard-coded, I didn't find a proper
524 * device-tree entry giving the address. Best would probably to use
525 * an offset for K2 base though, but let's do it that way for now.
526 */
527 smu->db_buf = ioremap(0x8000860c, 0x1000);
528 if (smu->db_buf == NULL) {
529 printk(KERN_ERR "SMU: Can't map doorbell buffer pointer !\n");
530 goto fail;
531 }
532
533 sys_ctrler = SYS_CTRLER_SMU;
534 return 0;
535
536 fail:
537 smu = NULL;
538 return -ENXIO;
539
540}
0365ba7f
BH
541
542
543static int smu_late_init(void)
544{
545 if (!smu)
546 return 0;
547
730745a5
BH
548 init_timer(&smu->i2c_timer);
549 smu->i2c_timer.function = smu_i2c_retry;
550 smu->i2c_timer.data = (unsigned long)smu;
551
0365ba7f
BH
552 /*
553 * Try to request the interrupts
554 */
555
556 if (smu->db_irq != NO_IRQ) {
557 if (request_irq(smu->db_irq, smu_db_intr,
558 SA_SHIRQ, "SMU doorbell", smu) < 0) {
559 printk(KERN_WARNING "SMU: can't "
560 "request interrupt %d\n",
561 smu->db_irq);
562 smu->db_irq = NO_IRQ;
563 }
564 }
565
566 if (smu->msg_irq != NO_IRQ) {
567 if (request_irq(smu->msg_irq, smu_msg_intr,
568 SA_SHIRQ, "SMU message", smu) < 0) {
569 printk(KERN_WARNING "SMU: can't "
570 "request interrupt %d\n",
571 smu->msg_irq);
572 smu->msg_irq = NO_IRQ;
573 }
574 }
575
576 return 0;
577}
730745a5
BH
578/* This has to be before arch_initcall as the low i2c stuff relies on the
579 * above having been done before we reach arch_initcalls
580 */
581core_initcall(smu_late_init);
0365ba7f
BH
582
583/*
584 * sysfs visibility
585 */
586
587static void smu_expose_childs(void *unused)
588{
a28d3af2
BH
589 struct device_node *np;
590
591 for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;)
75722d39 592 if (device_is_compatible(np, "smu-sensors"))
730745a5
BH
593 of_platform_device_create(np, "smu-sensors",
594 &smu->of_dev->dev);
0365ba7f
BH
595}
596
597static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL);
598
599static int smu_platform_probe(struct of_device* dev,
600 const struct of_device_id *match)
601{
602 if (!smu)
603 return -ENODEV;
604 smu->of_dev = dev;
605
606 /*
607 * Ok, we are matched, now expose all i2c busses. We have to defer
608 * that unfortunately or it would deadlock inside the device model
609 */
610 schedule_work(&smu_expose_childs_work);
611
612 return 0;
613}
614
615static struct of_device_id smu_platform_match[] =
616{
617 {
618 .type = "smu",
619 },
620 {},
621};
622
623static struct of_platform_driver smu_of_platform_driver =
624{
625 .name = "smu",
626 .match_table = smu_platform_match,
627 .probe = smu_platform_probe,
628};
629
630static int __init smu_init_sysfs(void)
631{
0365ba7f
BH
632 /*
633 * Due to sysfs bogosity, a sysdev is not a real device, so
634 * we should in fact create both if we want sysdev semantics
635 * for power management.
636 * For now, we don't power manage machines with an SMU chip,
637 * I'm a bit too far from figuring out how that works with those
638 * new chipsets, but that will come back and bite us
639 */
6ea671a1 640 of_register_driver(&smu_of_platform_driver);
0365ba7f
BH
641 return 0;
642}
643
644device_initcall(smu_init_sysfs);
645
646struct of_device *smu_get_ofdev(void)
647{
648 if (!smu)
649 return NULL;
650 return smu->of_dev;
651}
652
653EXPORT_SYMBOL_GPL(smu_get_ofdev);
654
655/*
656 * i2c interface
657 */
658
659static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail)
660{
661 void (*done)(struct smu_i2c_cmd *cmd, void *misc) = cmd->done;
662 void *misc = cmd->misc;
663 unsigned long flags;
664
665 /* Check for read case */
666 if (!fail && cmd->read) {
667 if (cmd->pdata[0] < 1)
668 fail = 1;
669 else
670 memcpy(cmd->info.data, &cmd->pdata[1],
671 cmd->info.datalen);
672 }
673
674 DPRINTK("SMU: completing, success: %d\n", !fail);
675
676 /* Update status and mark no pending i2c command with lock
677 * held so nobody comes in while we dequeue an eventual
678 * pending next i2c command
679 */
680 spin_lock_irqsave(&smu->lock, flags);
681 smu->cmd_i2c_cur = NULL;
682 wmb();
683 cmd->status = fail ? -EIO : 0;
684
685 /* Is there another i2c command waiting ? */
686 if (!list_empty(&smu->cmd_i2c_list)) {
687 struct smu_i2c_cmd *newcmd;
688
689 /* Fetch it, new current, remove from list */
690 newcmd = list_entry(smu->cmd_i2c_list.next,
691 struct smu_i2c_cmd, link);
692 smu->cmd_i2c_cur = newcmd;
693 list_del(&cmd->link);
694
695 /* Queue with low level smu */
696 list_add_tail(&cmd->scmd.link, &smu->cmd_list);
697 if (smu->cmd_cur == NULL)
698 smu_start_cmd();
699 }
700 spin_unlock_irqrestore(&smu->lock, flags);
701
702 /* Call command completion handler if any */
703 if (done)
704 done(cmd, misc);
705
706}
707
708
709static void smu_i2c_retry(unsigned long data)
710{
730745a5 711 struct smu_i2c_cmd *cmd = smu->cmd_i2c_cur;
0365ba7f
BH
712
713 DPRINTK("SMU: i2c failure, requeuing...\n");
714
715 /* requeue command simply by resetting reply_len */
716 cmd->pdata[0] = 0xff;
730745a5 717 cmd->scmd.reply_len = sizeof(cmd->pdata);
0365ba7f
BH
718 smu_queue_cmd(&cmd->scmd);
719}
720
721
722static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
723{
724 struct smu_i2c_cmd *cmd = misc;
725 int fail = 0;
726
727 DPRINTK("SMU: i2c compl. stage=%d status=%x pdata[0]=%x rlen: %x\n",
728 cmd->stage, scmd->status, cmd->pdata[0], scmd->reply_len);
729
730 /* Check for possible status */
731 if (scmd->status < 0)
732 fail = 1;
733 else if (cmd->read) {
734 if (cmd->stage == 0)
735 fail = cmd->pdata[0] != 0;
736 else
737 fail = cmd->pdata[0] >= 0x80;
738 } else {
739 fail = cmd->pdata[0] != 0;
740 }
741
742 /* Handle failures by requeuing command, after 5ms interval
743 */
744 if (fail && --cmd->retries > 0) {
745 DPRINTK("SMU: i2c failure, starting timer...\n");
730745a5
BH
746 BUG_ON(cmd != smu->cmd_i2c_cur);
747 mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5));
0365ba7f
BH
748 return;
749 }
750
751 /* If failure or stage 1, command is complete */
752 if (fail || cmd->stage != 0) {
753 smu_i2c_complete_command(cmd, fail);
754 return;
755 }
756
757 DPRINTK("SMU: going to stage 1\n");
758
759 /* Ok, initial command complete, now poll status */
760 scmd->reply_buf = cmd->pdata;
730745a5 761 scmd->reply_len = sizeof(cmd->pdata);
0365ba7f
BH
762 scmd->data_buf = cmd->pdata;
763 scmd->data_len = 1;
764 cmd->pdata[0] = 0;
765 cmd->stage = 1;
766 cmd->retries = 20;
767 smu_queue_cmd(scmd);
768}
769
770
771int smu_queue_i2c(struct smu_i2c_cmd *cmd)
772{
773 unsigned long flags;
774
775 if (smu == NULL)
776 return -ENODEV;
777
778 /* Fill most fields of scmd */
779 cmd->scmd.cmd = SMU_CMD_I2C_COMMAND;
780 cmd->scmd.done = smu_i2c_low_completion;
781 cmd->scmd.misc = cmd;
782 cmd->scmd.reply_buf = cmd->pdata;
730745a5 783 cmd->scmd.reply_len = sizeof(cmd->pdata);
0365ba7f
BH
784 cmd->scmd.data_buf = (u8 *)(char *)&cmd->info;
785 cmd->scmd.status = 1;
786 cmd->stage = 0;
787 cmd->pdata[0] = 0xff;
788 cmd->retries = 20;
789 cmd->status = 1;
790
791 /* Check transfer type, sanitize some "info" fields
792 * based on transfer type and do more checking
793 */
794 cmd->info.caddr = cmd->info.devaddr;
795 cmd->read = cmd->info.devaddr & 0x01;
796 switch(cmd->info.type) {
797 case SMU_I2C_TRANSFER_SIMPLE:
798 memset(&cmd->info.sublen, 0, 4);
799 break;
800 case SMU_I2C_TRANSFER_COMBINED:
801 cmd->info.devaddr &= 0xfe;
802 case SMU_I2C_TRANSFER_STDSUB:
803 if (cmd->info.sublen > 3)
804 return -EINVAL;
805 break;
806 default:
807 return -EINVAL;
808 }
809
810 /* Finish setting up command based on transfer direction
811 */
812 if (cmd->read) {
813 if (cmd->info.datalen > SMU_I2C_READ_MAX)
814 return -EINVAL;
815 memset(cmd->info.data, 0xff, cmd->info.datalen);
816 cmd->scmd.data_len = 9;
817 } else {
818 if (cmd->info.datalen > SMU_I2C_WRITE_MAX)
819 return -EINVAL;
820 cmd->scmd.data_len = 9 + cmd->info.datalen;
821 }
822
823 DPRINTK("SMU: i2c enqueuing command\n");
824 DPRINTK("SMU: %s, len=%d bus=%x addr=%x sub0=%x type=%x\n",
825 cmd->read ? "read" : "write", cmd->info.datalen,
826 cmd->info.bus, cmd->info.caddr,
827 cmd->info.subaddr[0], cmd->info.type);
828
829
830 /* Enqueue command in i2c list, and if empty, enqueue also in
831 * main command list
832 */
833 spin_lock_irqsave(&smu->lock, flags);
834 if (smu->cmd_i2c_cur == NULL) {
835 smu->cmd_i2c_cur = cmd;
836 list_add_tail(&cmd->scmd.link, &smu->cmd_list);
837 if (smu->cmd_cur == NULL)
838 smu_start_cmd();
839 } else
840 list_add_tail(&cmd->link, &smu->cmd_i2c_list);
841 spin_unlock_irqrestore(&smu->lock, flags);
842
843 return 0;
844}
845
183d0202
BH
846/*
847 * Handling of "partitions"
848 */
849
850static int smu_read_datablock(u8 *dest, unsigned int addr, unsigned int len)
851{
852 DECLARE_COMPLETION(comp);
853 unsigned int chunk;
854 struct smu_cmd cmd;
855 int rc;
856 u8 params[8];
857
858 /* We currently use a chunk size of 0xe. We could check the
859 * SMU firmware version and use bigger sizes though
860 */
861 chunk = 0xe;
862
863 while (len) {
864 unsigned int clen = min(len, chunk);
865
866 cmd.cmd = SMU_CMD_MISC_ee_COMMAND;
867 cmd.data_len = 7;
868 cmd.data_buf = params;
869 cmd.reply_len = chunk;
870 cmd.reply_buf = dest;
871 cmd.done = smu_done_complete;
872 cmd.misc = &comp;
873 params[0] = SMU_CMD_MISC_ee_GET_DATABLOCK_REC;
874 params[1] = 0x4;
875 *((u32 *)&params[2]) = addr;
876 params[6] = clen;
877
878 rc = smu_queue_cmd(&cmd);
879 if (rc)
880 return rc;
881 wait_for_completion(&comp);
882 if (cmd.status != 0)
883 return rc;
884 if (cmd.reply_len != clen) {
885 printk(KERN_DEBUG "SMU: short read in "
886 "smu_read_datablock, got: %d, want: %d\n",
887 cmd.reply_len, clen);
888 return -EIO;
889 }
890 len -= clen;
891 addr += clen;
892 dest += clen;
893 }
894 return 0;
895}
896
897static struct smu_sdbp_header *smu_create_sdb_partition(int id)
898{
899 DECLARE_COMPLETION(comp);
900 struct smu_simple_cmd cmd;
901 unsigned int addr, len, tlen;
902 struct smu_sdbp_header *hdr;
903 struct property *prop;
904
905 /* First query the partition info */
1beb6a7d 906 DPRINTK("SMU: Query partition infos ... (irq=%d)\n", smu->db_irq);
183d0202
BH
907 smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2,
908 smu_done_complete, &comp,
909 SMU_CMD_PARTITION_LATEST, id);
910 wait_for_completion(&comp);
1beb6a7d
BH
911 DPRINTK("SMU: done, status: %d, reply_len: %d\n",
912 cmd.cmd.status, cmd.cmd.reply_len);
183d0202
BH
913
914 /* Partition doesn't exist (or other error) */
915 if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6)
916 return NULL;
917
918 /* Fetch address and length from reply */
919 addr = *((u16 *)cmd.buffer);
920 len = cmd.buffer[3] << 2;
921 /* Calucluate total length to allocate, including the 17 bytes
922 * for "sdb-partition-XX" that we append at the end of the buffer
923 */
924 tlen = sizeof(struct property) + len + 18;
925
926 prop = kcalloc(tlen, 1, GFP_KERNEL);
927 if (prop == NULL)
928 return NULL;
929 hdr = (struct smu_sdbp_header *)(prop + 1);
930 prop->name = ((char *)prop) + tlen - 18;
931 sprintf(prop->name, "sdb-partition-%02x", id);
932 prop->length = len;
933 prop->value = (unsigned char *)hdr;
934 prop->next = NULL;
935
936 /* Read the datablock */
937 if (smu_read_datablock((u8 *)hdr, addr, len)) {
938 printk(KERN_DEBUG "SMU: datablock read failed while reading "
939 "partition %02x !\n", id);
940 goto failure;
941 }
942
943 /* Got it, check a few things and create the property */
944 if (hdr->id != id) {
945 printk(KERN_DEBUG "SMU: Reading partition %02x and got "
946 "%02x !\n", id, hdr->id);
947 goto failure;
948 }
949 if (prom_add_property(smu->of_node, prop)) {
950 printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x "
951 "property !\n", id);
952 goto failure;
953 }
954
955 return hdr;
956 failure:
957 kfree(prop);
958 return NULL;
959}
960
961/* Note: Only allowed to return error code in pointers (using ERR_PTR)
962 * when interruptible is 1
963 */
964struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size,
965 int interruptible)
4350147a
BH
966{
967 char pname[32];
183d0202 968 struct smu_sdbp_header *part;
4350147a
BH
969
970 if (!smu)
971 return NULL;
972
973 sprintf(pname, "sdb-partition-%02x", id);
183d0202 974
1beb6a7d
BH
975 DPRINTK("smu_get_sdb_partition(%02x)\n", id);
976
183d0202
BH
977 if (interruptible) {
978 int rc;
979 rc = down_interruptible(&smu_part_access);
980 if (rc)
981 return ERR_PTR(rc);
982 } else
983 down(&smu_part_access);
984
985 part = (struct smu_sdbp_header *)get_property(smu->of_node,
4350147a 986 pname, size);
183d0202 987 if (part == NULL) {
1beb6a7d 988 DPRINTK("trying to extract from SMU ...\n");
183d0202
BH
989 part = smu_create_sdb_partition(id);
990 if (part != NULL && size)
991 *size = part->len << 2;
992 }
993 up(&smu_part_access);
994 return part;
995}
996
997struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size)
998{
999 return __smu_get_sdb_partition(id, size, 0);
4350147a
BH
1000}
1001EXPORT_SYMBOL(smu_get_sdb_partition);
0365ba7f
BH
1002
1003
1004/*
1005 * Userland driver interface
1006 */
1007
1008
1009static LIST_HEAD(smu_clist);
1010static DEFINE_SPINLOCK(smu_clist_lock);
1011
1012enum smu_file_mode {
1013 smu_file_commands,
1014 smu_file_events,
1015 smu_file_closing
1016};
1017
1018struct smu_private
1019{
1020 struct list_head list;
1021 enum smu_file_mode mode;
1022 int busy;
1023 struct smu_cmd cmd;
1024 spinlock_t lock;
1025 wait_queue_head_t wait;
1026 u8 buffer[SMU_MAX_DATA];
1027};
1028
1029
1030static int smu_open(struct inode *inode, struct file *file)
1031{
1032 struct smu_private *pp;
1033 unsigned long flags;
1034
1035 pp = kmalloc(sizeof(struct smu_private), GFP_KERNEL);
1036 if (pp == 0)
1037 return -ENOMEM;
1038 memset(pp, 0, sizeof(struct smu_private));
1039 spin_lock_init(&pp->lock);
1040 pp->mode = smu_file_commands;
1041 init_waitqueue_head(&pp->wait);
1042
1043 spin_lock_irqsave(&smu_clist_lock, flags);
1044 list_add(&pp->list, &smu_clist);
1045 spin_unlock_irqrestore(&smu_clist_lock, flags);
1046 file->private_data = pp;
1047
1048 return 0;
1049}
1050
1051
1052static void smu_user_cmd_done(struct smu_cmd *cmd, void *misc)
1053{
1054 struct smu_private *pp = misc;
1055
1056 wake_up_all(&pp->wait);
1057}
1058
1059
1060static ssize_t smu_write(struct file *file, const char __user *buf,
1061 size_t count, loff_t *ppos)
1062{
1063 struct smu_private *pp = file->private_data;
1064 unsigned long flags;
1065 struct smu_user_cmd_hdr hdr;
1066 int rc = 0;
1067
1068 if (pp->busy)
1069 return -EBUSY;
1070 else if (copy_from_user(&hdr, buf, sizeof(hdr)))
1071 return -EFAULT;
1072 else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) {
1073 pp->mode = smu_file_events;
1074 return 0;
183d0202
BH
1075 } else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) {
1076 struct smu_sdbp_header *part;
1077 part = __smu_get_sdb_partition(hdr.cmd, NULL, 1);
1078 if (part == NULL)
1079 return -EINVAL;
1080 else if (IS_ERR(part))
1081 return PTR_ERR(part);
1082 return 0;
0365ba7f
BH
1083 } else if (hdr.cmdtype != SMU_CMDTYPE_SMU)
1084 return -EINVAL;
1085 else if (pp->mode != smu_file_commands)
1086 return -EBADFD;
1087 else if (hdr.data_len > SMU_MAX_DATA)
1088 return -EINVAL;
1089
1090 spin_lock_irqsave(&pp->lock, flags);
1091 if (pp->busy) {
1092 spin_unlock_irqrestore(&pp->lock, flags);
1093 return -EBUSY;
1094 }
1095 pp->busy = 1;
1096 pp->cmd.status = 1;
1097 spin_unlock_irqrestore(&pp->lock, flags);
1098
1099 if (copy_from_user(pp->buffer, buf + sizeof(hdr), hdr.data_len)) {
1100 pp->busy = 0;
1101 return -EFAULT;
1102 }
1103
1104 pp->cmd.cmd = hdr.cmd;
1105 pp->cmd.data_len = hdr.data_len;
1106 pp->cmd.reply_len = SMU_MAX_DATA;
1107 pp->cmd.data_buf = pp->buffer;
1108 pp->cmd.reply_buf = pp->buffer;
1109 pp->cmd.done = smu_user_cmd_done;
1110 pp->cmd.misc = pp;
1111 rc = smu_queue_cmd(&pp->cmd);
1112 if (rc < 0)
1113 return rc;
1114 return count;
1115}
1116
1117
1118static ssize_t smu_read_command(struct file *file, struct smu_private *pp,
1119 char __user *buf, size_t count)
1120{
1121 DECLARE_WAITQUEUE(wait, current);
1122 struct smu_user_reply_hdr hdr;
1123 unsigned long flags;
1124 int size, rc = 0;
1125
1126 if (!pp->busy)
1127 return 0;
1128 if (count < sizeof(struct smu_user_reply_hdr))
1129 return -EOVERFLOW;
1130 spin_lock_irqsave(&pp->lock, flags);
1131 if (pp->cmd.status == 1) {
1132 if (file->f_flags & O_NONBLOCK)
1133 return -EAGAIN;
1134 add_wait_queue(&pp->wait, &wait);
1135 for (;;) {
1136 set_current_state(TASK_INTERRUPTIBLE);
1137 rc = 0;
1138 if (pp->cmd.status != 1)
1139 break;
1140 rc = -ERESTARTSYS;
1141 if (signal_pending(current))
1142 break;
1143 spin_unlock_irqrestore(&pp->lock, flags);
1144 schedule();
1145 spin_lock_irqsave(&pp->lock, flags);
1146 }
1147 set_current_state(TASK_RUNNING);
1148 remove_wait_queue(&pp->wait, &wait);
1149 }
1150 spin_unlock_irqrestore(&pp->lock, flags);
1151 if (rc)
1152 return rc;
1153 if (pp->cmd.status != 0)
1154 pp->cmd.reply_len = 0;
1155 size = sizeof(hdr) + pp->cmd.reply_len;
1156 if (count < size)
1157 size = count;
1158 rc = size;
1159 hdr.status = pp->cmd.status;
1160 hdr.reply_len = pp->cmd.reply_len;
1161 if (copy_to_user(buf, &hdr, sizeof(hdr)))
1162 return -EFAULT;
1163 size -= sizeof(hdr);
1164 if (size && copy_to_user(buf + sizeof(hdr), pp->buffer, size))
1165 return -EFAULT;
1166 pp->busy = 0;
1167
1168 return rc;
1169}
1170
1171
1172static ssize_t smu_read_events(struct file *file, struct smu_private *pp,
1173 char __user *buf, size_t count)
1174{
1175 /* Not implemented */
1176 msleep_interruptible(1000);
1177 return 0;
1178}
1179
1180
1181static ssize_t smu_read(struct file *file, char __user *buf,
1182 size_t count, loff_t *ppos)
1183{
1184 struct smu_private *pp = file->private_data;
1185
1186 if (pp->mode == smu_file_commands)
1187 return smu_read_command(file, pp, buf, count);
1188 if (pp->mode == smu_file_events)
1189 return smu_read_events(file, pp, buf, count);
1190
1191 return -EBADFD;
1192}
1193
1194static unsigned int smu_fpoll(struct file *file, poll_table *wait)
1195{
1196 struct smu_private *pp = file->private_data;
1197 unsigned int mask = 0;
1198 unsigned long flags;
1199
1200 if (pp == 0)
1201 return 0;
1202
1203 if (pp->mode == smu_file_commands) {
1204 poll_wait(file, &pp->wait, wait);
1205
1206 spin_lock_irqsave(&pp->lock, flags);
1207 if (pp->busy && pp->cmd.status != 1)
1208 mask |= POLLIN;
1209 spin_unlock_irqrestore(&pp->lock, flags);
1210 } if (pp->mode == smu_file_events) {
1211 /* Not yet implemented */
1212 }
1213 return mask;
1214}
1215
1216static int smu_release(struct inode *inode, struct file *file)
1217{
1218 struct smu_private *pp = file->private_data;
1219 unsigned long flags;
1220 unsigned int busy;
1221
1222 if (pp == 0)
1223 return 0;
1224
1225 file->private_data = NULL;
1226
1227 /* Mark file as closing to avoid races with new request */
1228 spin_lock_irqsave(&pp->lock, flags);
1229 pp->mode = smu_file_closing;
1230 busy = pp->busy;
1231
1232 /* Wait for any pending request to complete */
1233 if (busy && pp->cmd.status == 1) {
1234 DECLARE_WAITQUEUE(wait, current);
1235
1236 add_wait_queue(&pp->wait, &wait);
1237 for (;;) {
1238 set_current_state(TASK_UNINTERRUPTIBLE);
1239 if (pp->cmd.status != 1)
1240 break;
1241 spin_lock_irqsave(&pp->lock, flags);
1242 schedule();
1243 spin_unlock_irqrestore(&pp->lock, flags);
1244 }
1245 set_current_state(TASK_RUNNING);
1246 remove_wait_queue(&pp->wait, &wait);
1247 }
1248 spin_unlock_irqrestore(&pp->lock, flags);
1249
1250 spin_lock_irqsave(&smu_clist_lock, flags);
1251 list_del(&pp->list);
1252 spin_unlock_irqrestore(&smu_clist_lock, flags);
1253 kfree(pp);
1254
1255 return 0;
1256}
1257
1258
6b67f62c 1259static struct file_operations smu_device_fops = {
0365ba7f
BH
1260 .llseek = no_llseek,
1261 .read = smu_read,
1262 .write = smu_write,
1263 .poll = smu_fpoll,
1264 .open = smu_open,
1265 .release = smu_release,
1266};
1267
6b67f62c 1268static struct miscdevice pmu_device = {
0365ba7f
BH
1269 MISC_DYNAMIC_MINOR, "smu", &smu_device_fops
1270};
1271
1272static int smu_device_init(void)
1273{
1274 if (!smu)
1275 return -ENODEV;
1276 if (misc_register(&pmu_device) < 0)
1277 printk(KERN_ERR "via-pmu: cannot register misc device.\n");
1278 return 0;
1279}
1280device_initcall(smu_device_init);