hwmon: (lm73) Make detection less problematic
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / mfd / ab5500-debugfs.c
blob6be1fe6b5f9ac70c8ef31df1a3d546a3dc695707
1 /*
2 * Copyright (C) 2011 ST-Ericsson
3 * License terms: GNU General Public License (GPL) version 2
4 * Debugfs support for the AB5500 MFD driver
5 */
7 #include <linux/debugfs.h>
8 #include <linux/seq_file.h>
9 #include <linux/mfd/ab5500/ab5500.h>
10 #include <linux/mfd/abx500.h>
11 #include <linux/uaccess.h>
13 #include "ab5500-core.h"
14 #include "ab5500-debugfs.h"
16 static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = {
17 [AB5500_BANK_LED] = {
18 .bankid = AB5500_BANK_LED,
19 .nranges = 1,
20 .range = (struct ab5500_reg_range[]) {
22 .first = 0x00,
23 .last = 0x0C,
24 .perm = AB5500_PERM_RW,
28 [AB5500_BANK_ADC] = {
29 .bankid = AB5500_BANK_ADC,
30 .nranges = 6,
31 .range = (struct ab5500_reg_range[]) {
33 .first = 0x1F,
34 .last = 0x22,
35 .perm = AB5500_PERM_RO,
38 .first = 0x23,
39 .last = 0x24,
40 .perm = AB5500_PERM_RW,
43 .first = 0x26,
44 .last = 0x2D,
45 .perm = AB5500_PERM_RO,
48 .first = 0x2F,
49 .last = 0x34,
50 .perm = AB5500_PERM_RW,
53 .first = 0x37,
54 .last = 0x57,
55 .perm = AB5500_PERM_RW,
58 .first = 0x58,
59 .last = 0x58,
60 .perm = AB5500_PERM_RO,
64 [AB5500_BANK_RTC] = {
65 .bankid = AB5500_BANK_RTC,
66 .nranges = 2,
67 .range = (struct ab5500_reg_range[]) {
69 .first = 0x00,
70 .last = 0x04,
71 .perm = AB5500_PERM_RW,
74 .first = 0x06,
75 .last = 0x0C,
76 .perm = AB5500_PERM_RW,
80 [AB5500_BANK_STARTUP] = {
81 .bankid = AB5500_BANK_STARTUP,
82 .nranges = 12,
83 .range = (struct ab5500_reg_range[]) {
85 .first = 0x00,
86 .last = 0x01,
87 .perm = AB5500_PERM_RW,
90 .first = 0x1F,
91 .last = 0x1F,
92 .perm = AB5500_PERM_RW,
95 .first = 0x2E,
96 .last = 0x2E,
97 .perm = AB5500_PERM_RO,
100 .first = 0x2F,
101 .last = 0x30,
102 .perm = AB5500_PERM_RW,
105 .first = 0x50,
106 .last = 0x51,
107 .perm = AB5500_PERM_RW,
110 .first = 0x60,
111 .last = 0x61,
112 .perm = AB5500_PERM_RW,
115 .first = 0x66,
116 .last = 0x8A,
117 .perm = AB5500_PERM_RW,
120 .first = 0x8C,
121 .last = 0x96,
122 .perm = AB5500_PERM_RW,
125 .first = 0xAA,
126 .last = 0xB4,
127 .perm = AB5500_PERM_RW,
130 .first = 0xB7,
131 .last = 0xBF,
132 .perm = AB5500_PERM_RW,
135 .first = 0xC1,
136 .last = 0xCA,
137 .perm = AB5500_PERM_RW,
140 .first = 0xD3,
141 .last = 0xE0,
142 .perm = AB5500_PERM_RW,
146 [AB5500_BANK_DBI_ECI] = {
147 .bankid = AB5500_BANK_DBI_ECI,
148 .nranges = 3,
149 .range = (struct ab5500_reg_range[]) {
151 .first = 0x00,
152 .last = 0x07,
153 .perm = AB5500_PERM_RW,
156 .first = 0x10,
157 .last = 0x10,
158 .perm = AB5500_PERM_RW,
161 .first = 0x13,
162 .last = 0x13,
163 .perm = AB5500_PERM_RW,
167 [AB5500_BANK_CHG] = {
168 .bankid = AB5500_BANK_CHG,
169 .nranges = 2,
170 .range = (struct ab5500_reg_range[]) {
172 .first = 0x11,
173 .last = 0x11,
174 .perm = AB5500_PERM_RO,
177 .first = 0x12,
178 .last = 0x1B,
179 .perm = AB5500_PERM_RW,
183 [AB5500_BANK_FG_BATTCOM_ACC] = {
184 .bankid = AB5500_BANK_FG_BATTCOM_ACC,
185 .nranges = 2,
186 .range = (struct ab5500_reg_range[]) {
188 .first = 0x00,
189 .last = 0x0B,
190 .perm = AB5500_PERM_RO,
193 .first = 0x0C,
194 .last = 0x10,
195 .perm = AB5500_PERM_RW,
199 [AB5500_BANK_USB] = {
200 .bankid = AB5500_BANK_USB,
201 .nranges = 12,
202 .range = (struct ab5500_reg_range[]) {
204 .first = 0x01,
205 .last = 0x01,
206 .perm = AB5500_PERM_RW,
209 .first = 0x80,
210 .last = 0x83,
211 .perm = AB5500_PERM_RW,
214 .first = 0x87,
215 .last = 0x8A,
216 .perm = AB5500_PERM_RW,
219 .first = 0x8B,
220 .last = 0x8B,
221 .perm = AB5500_PERM_RO,
224 .first = 0x91,
225 .last = 0x92,
226 .perm = AB5500_PERM_RO,
229 .first = 0x93,
230 .last = 0x93,
231 .perm = AB5500_PERM_RW,
234 .first = 0x94,
235 .last = 0x94,
236 .perm = AB5500_PERM_RO,
239 .first = 0xA8,
240 .last = 0xB0,
241 .perm = AB5500_PERM_RO,
244 .first = 0xB2,
245 .last = 0xB2,
246 .perm = AB5500_PERM_RO,
249 .first = 0xB4,
250 .last = 0xBC,
251 .perm = AB5500_PERM_RO,
254 .first = 0xBF,
255 .last = 0xBF,
256 .perm = AB5500_PERM_RO,
259 .first = 0xC1,
260 .last = 0xC5,
261 .perm = AB5500_PERM_RO,
265 [AB5500_BANK_IT] = {
266 .bankid = AB5500_BANK_IT,
267 .nranges = 4,
268 .range = (struct ab5500_reg_range[]) {
270 .first = 0x00,
271 .last = 0x02,
272 .perm = AB5500_PERM_RO,
275 .first = 0x20,
276 .last = 0x36,
277 .perm = AB5500_PERM_RO,
280 .first = 0x40,
281 .last = 0x56,
282 .perm = AB5500_PERM_RO,
285 .first = 0x60,
286 .last = 0x76,
287 .perm = AB5500_PERM_RO,
291 [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
292 .bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST,
293 .nranges = 7,
294 .range = (struct ab5500_reg_range[]) {
296 .first = 0x02,
297 .last = 0x02,
298 .perm = AB5500_PERM_RW,
301 .first = 0x12,
302 .last = 0x12,
303 .perm = AB5500_PERM_RW,
306 .first = 0x30,
307 .last = 0x34,
308 .perm = AB5500_PERM_RW,
311 .first = 0x40,
312 .last = 0x44,
313 .perm = AB5500_PERM_RW,
316 .first = 0x50,
317 .last = 0x54,
318 .perm = AB5500_PERM_RW,
321 .first = 0x60,
322 .last = 0x64,
323 .perm = AB5500_PERM_RW,
326 .first = 0x70,
327 .last = 0x74,
328 .perm = AB5500_PERM_RW,
332 [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
333 .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
334 .nranges = 13,
335 .range = (struct ab5500_reg_range[]) {
337 .first = 0x01,
338 .last = 0x01,
339 .perm = AB5500_PERM_RW,
342 .first = 0x02,
343 .last = 0x02,
344 .perm = AB5500_PERM_RO,
347 .first = 0x0D,
348 .last = 0x0F,
349 .perm = AB5500_PERM_RW,
352 .first = 0x1C,
353 .last = 0x1C,
354 .perm = AB5500_PERM_RW,
357 .first = 0x1E,
358 .last = 0x1E,
359 .perm = AB5500_PERM_RW,
362 .first = 0x20,
363 .last = 0x21,
364 .perm = AB5500_PERM_RW,
367 .first = 0x25,
368 .last = 0x25,
369 .perm = AB5500_PERM_RW,
372 .first = 0x28,
373 .last = 0x2A,
374 .perm = AB5500_PERM_RW,
377 .first = 0x30,
378 .last = 0x33,
379 .perm = AB5500_PERM_RW,
382 .first = 0x40,
383 .last = 0x43,
384 .perm = AB5500_PERM_RW,
387 .first = 0x50,
388 .last = 0x53,
389 .perm = AB5500_PERM_RW,
392 .first = 0x60,
393 .last = 0x63,
394 .perm = AB5500_PERM_RW,
397 .first = 0x70,
398 .last = 0x73,
399 .perm = AB5500_PERM_RW,
403 [AB5500_BANK_VIBRA] = {
404 .bankid = AB5500_BANK_VIBRA,
405 .nranges = 2,
406 .range = (struct ab5500_reg_range[]) {
408 .first = 0x10,
409 .last = 0x13,
410 .perm = AB5500_PERM_RW,
413 .first = 0xFE,
414 .last = 0xFE,
415 .perm = AB5500_PERM_RW,
419 [AB5500_BANK_AUDIO_HEADSETUSB] = {
420 .bankid = AB5500_BANK_AUDIO_HEADSETUSB,
421 .nranges = 2,
422 .range = (struct ab5500_reg_range[]) {
424 .first = 0x00,
425 .last = 0x48,
426 .perm = AB5500_PERM_RW,
429 .first = 0xEB,
430 .last = 0xFB,
431 .perm = AB5500_PERM_RW,
435 [AB5500_BANK_SIM_USBSIM] = {
436 .bankid = AB5500_BANK_SIM_USBSIM,
437 .nranges = 1,
438 .range = (struct ab5500_reg_range[]) {
440 .first = 0x13,
441 .last = 0x19,
442 .perm = AB5500_PERM_RW,
446 [AB5500_BANK_VDENC] = {
447 .bankid = AB5500_BANK_VDENC,
448 .nranges = 12,
449 .range = (struct ab5500_reg_range[]) {
451 .first = 0x00,
452 .last = 0x08,
453 .perm = AB5500_PERM_RW,
456 .first = 0x09,
457 .last = 0x09,
458 .perm = AB5500_PERM_RO,
461 .first = 0x0A,
462 .last = 0x12,
463 .perm = AB5500_PERM_RW,
466 .first = 0x15,
467 .last = 0x19,
468 .perm = AB5500_PERM_RW,
471 .first = 0x1B,
472 .last = 0x21,
473 .perm = AB5500_PERM_RW,
476 .first = 0x27,
477 .last = 0x2C,
478 .perm = AB5500_PERM_RW,
481 .first = 0x41,
482 .last = 0x41,
483 .perm = AB5500_PERM_RW,
486 .first = 0x45,
487 .last = 0x5B,
488 .perm = AB5500_PERM_RW,
491 .first = 0x5D,
492 .last = 0x5D,
493 .perm = AB5500_PERM_RW,
496 .first = 0x69,
497 .last = 0x69,
498 .perm = AB5500_PERM_RW,
501 .first = 0x6C,
502 .last = 0x6D,
503 .perm = AB5500_PERM_RW,
506 .first = 0x80,
507 .last = 0x81,
508 .perm = AB5500_PERM_RW,
514 static int ab5500_registers_print(struct seq_file *s, void *p)
516 struct ab5500 *ab = s->private;
517 unsigned int i;
518 u8 bank = (u8)ab->debug_bank;
520 seq_printf(s, "ab5500 register values:\n");
521 for (bank = 0; bank < AB5500_NUM_BANKS; bank++) {
522 seq_printf(s, " bank %u, %s (0x%x):\n", bank,
523 bankinfo[bank].name,
524 bankinfo[bank].slave_addr);
525 for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) {
526 u8 reg;
527 int err;
529 for (reg = ab5500_reg_ranges[bank].range[i].first;
530 reg <= ab5500_reg_ranges[bank].range[i].last;
531 reg++) {
532 u8 value;
534 err = ab5500_get_register_interruptible_raw(ab,
535 bank, reg,
536 &value);
537 if (err < 0) {
538 dev_err(ab->dev, "get_reg failed %d"
539 "bank 0x%x reg 0x%x\n",
540 err, bank, reg);
541 return err;
544 err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n",
545 bank, reg, value);
546 if (err < 0) {
547 dev_err(ab->dev,
548 "seq_printf overflow\n");
550 * Error is not returned here since
551 * the output is wanted in any case
553 return 0;
558 return 0;
561 static int ab5500_registers_open(struct inode *inode, struct file *file)
563 return single_open(file, ab5500_registers_print, inode->i_private);
566 static const struct file_operations ab5500_registers_fops = {
567 .open = ab5500_registers_open,
568 .read = seq_read,
569 .llseek = seq_lseek,
570 .release = single_release,
571 .owner = THIS_MODULE,
574 static int ab5500_bank_print(struct seq_file *s, void *p)
576 struct ab5500 *ab = s->private;
578 seq_printf(s, "%d\n", ab->debug_bank);
579 return 0;
582 static int ab5500_bank_open(struct inode *inode, struct file *file)
584 return single_open(file, ab5500_bank_print, inode->i_private);
587 static ssize_t ab5500_bank_write(struct file *file,
588 const char __user *user_buf,
589 size_t count, loff_t *ppos)
591 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
592 char buf[32];
593 int buf_size;
594 unsigned long user_bank;
595 int err;
597 /* Get userspace string and assure termination */
598 buf_size = min(count, (sizeof(buf) - 1));
599 if (copy_from_user(buf, user_buf, buf_size))
600 return -EFAULT;
601 buf[buf_size] = 0;
603 err = strict_strtoul(buf, 0, &user_bank);
604 if (err)
605 return -EINVAL;
607 if (user_bank >= AB5500_NUM_BANKS) {
608 dev_err(ab->dev,
609 "debugfs error input > number of banks\n");
610 return -EINVAL;
613 ab->debug_bank = user_bank;
615 return buf_size;
618 static int ab5500_address_print(struct seq_file *s, void *p)
620 struct ab5500 *ab = s->private;
622 seq_printf(s, "0x%02X\n", ab->debug_address);
623 return 0;
626 static int ab5500_address_open(struct inode *inode, struct file *file)
628 return single_open(file, ab5500_address_print, inode->i_private);
631 static ssize_t ab5500_address_write(struct file *file,
632 const char __user *user_buf,
633 size_t count, loff_t *ppos)
635 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
636 char buf[32];
637 int buf_size;
638 unsigned long user_address;
639 int err;
641 /* Get userspace string and assure termination */
642 buf_size = min(count, (sizeof(buf) - 1));
643 if (copy_from_user(buf, user_buf, buf_size))
644 return -EFAULT;
645 buf[buf_size] = 0;
647 err = strict_strtoul(buf, 0, &user_address);
648 if (err)
649 return -EINVAL;
650 if (user_address > 0xff) {
651 dev_err(ab->dev,
652 "debugfs error input > 0xff\n");
653 return -EINVAL;
655 ab->debug_address = user_address;
656 return buf_size;
659 static int ab5500_val_print(struct seq_file *s, void *p)
661 struct ab5500 *ab = s->private;
662 int err;
663 u8 regvalue;
665 err = ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
666 (u8)ab->debug_address, &regvalue);
667 if (err) {
668 dev_err(ab->dev, "get_reg failed %d, bank 0x%x"
669 ", reg 0x%x\n", err, ab->debug_bank,
670 ab->debug_address);
671 return -EINVAL;
673 seq_printf(s, "0x%02X\n", regvalue);
675 return 0;
678 static int ab5500_val_open(struct inode *inode, struct file *file)
680 return single_open(file, ab5500_val_print, inode->i_private);
683 static ssize_t ab5500_val_write(struct file *file,
684 const char __user *user_buf,
685 size_t count, loff_t *ppos)
687 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
688 char buf[32];
689 int buf_size;
690 unsigned long user_val;
691 int err;
692 u8 regvalue;
694 /* Get userspace string and assure termination */
695 buf_size = min(count, (sizeof(buf)-1));
696 if (copy_from_user(buf, user_buf, buf_size))
697 return -EFAULT;
698 buf[buf_size] = 0;
700 err = strict_strtoul(buf, 0, &user_val);
701 if (err)
702 return -EINVAL;
703 if (user_val > 0xff) {
704 dev_err(ab->dev,
705 "debugfs error input > 0xff\n");
706 return -EINVAL;
708 err = ab5500_mask_and_set_register_interruptible_raw(
709 ab, (u8)ab->debug_bank,
710 (u8)ab->debug_address, 0xFF, (u8)user_val);
711 if (err)
712 return -EINVAL;
714 ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
715 (u8)ab->debug_address, &regvalue);
716 if (err)
717 return -EINVAL;
719 return buf_size;
722 static const struct file_operations ab5500_bank_fops = {
723 .open = ab5500_bank_open,
724 .write = ab5500_bank_write,
725 .read = seq_read,
726 .llseek = seq_lseek,
727 .release = single_release,
728 .owner = THIS_MODULE,
731 static const struct file_operations ab5500_address_fops = {
732 .open = ab5500_address_open,
733 .write = ab5500_address_write,
734 .read = seq_read,
735 .llseek = seq_lseek,
736 .release = single_release,
737 .owner = THIS_MODULE,
740 static const struct file_operations ab5500_val_fops = {
741 .open = ab5500_val_open,
742 .write = ab5500_val_write,
743 .read = seq_read,
744 .llseek = seq_lseek,
745 .release = single_release,
746 .owner = THIS_MODULE,
749 static struct dentry *ab5500_dir;
750 static struct dentry *ab5500_reg_file;
751 static struct dentry *ab5500_bank_file;
752 static struct dentry *ab5500_address_file;
753 static struct dentry *ab5500_val_file;
755 void __init ab5500_setup_debugfs(struct ab5500 *ab)
757 ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP;
758 ab->debug_address = AB5500_CHIP_ID;
760 ab5500_dir = debugfs_create_dir("ab5500", NULL);
761 if (!ab5500_dir)
762 goto exit_no_debugfs;
764 ab5500_reg_file = debugfs_create_file("all-bank-registers",
765 S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops);
766 if (!ab5500_reg_file)
767 goto exit_destroy_dir;
769 ab5500_bank_file = debugfs_create_file("register-bank",
770 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops);
771 if (!ab5500_bank_file)
772 goto exit_destroy_reg;
774 ab5500_address_file = debugfs_create_file("register-address",
775 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops);
776 if (!ab5500_address_file)
777 goto exit_destroy_bank;
779 ab5500_val_file = debugfs_create_file("register-value",
780 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops);
781 if (!ab5500_val_file)
782 goto exit_destroy_address;
784 return;
786 exit_destroy_address:
787 debugfs_remove(ab5500_address_file);
788 exit_destroy_bank:
789 debugfs_remove(ab5500_bank_file);
790 exit_destroy_reg:
791 debugfs_remove(ab5500_reg_file);
792 exit_destroy_dir:
793 debugfs_remove(ab5500_dir);
794 exit_no_debugfs:
795 dev_err(ab->dev, "failed to create debugfs entries.\n");
796 return;
799 void __exit ab5500_remove_debugfs(void)
801 debugfs_remove(ab5500_val_file);
802 debugfs_remove(ab5500_address_file);
803 debugfs_remove(ab5500_bank_file);
804 debugfs_remove(ab5500_reg_file);
805 debugfs_remove(ab5500_dir);