2 * Copyright (C) 2011 ST-Ericsson
3 * License terms: GNU General Public License (GPL) version 2
4 * Debugfs support for the AB5500 MFD driver
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
] = {
18 .bankid
= AB5500_BANK_LED
,
20 .range
= (struct ab5500_reg_range
[]) {
24 .perm
= AB5500_PERM_RW
,
29 .bankid
= AB5500_BANK_ADC
,
31 .range
= (struct ab5500_reg_range
[]) {
35 .perm
= AB5500_PERM_RO
,
40 .perm
= AB5500_PERM_RW
,
45 .perm
= AB5500_PERM_RO
,
50 .perm
= AB5500_PERM_RW
,
55 .perm
= AB5500_PERM_RW
,
60 .perm
= AB5500_PERM_RO
,
65 .bankid
= AB5500_BANK_RTC
,
67 .range
= (struct ab5500_reg_range
[]) {
71 .perm
= AB5500_PERM_RW
,
76 .perm
= AB5500_PERM_RW
,
80 [AB5500_BANK_STARTUP
] = {
81 .bankid
= AB5500_BANK_STARTUP
,
83 .range
= (struct ab5500_reg_range
[]) {
87 .perm
= AB5500_PERM_RW
,
92 .perm
= AB5500_PERM_RW
,
97 .perm
= AB5500_PERM_RO
,
102 .perm
= AB5500_PERM_RW
,
107 .perm
= AB5500_PERM_RW
,
112 .perm
= AB5500_PERM_RW
,
117 .perm
= AB5500_PERM_RW
,
122 .perm
= AB5500_PERM_RW
,
127 .perm
= AB5500_PERM_RW
,
132 .perm
= AB5500_PERM_RW
,
137 .perm
= AB5500_PERM_RW
,
142 .perm
= AB5500_PERM_RW
,
146 [AB5500_BANK_DBI_ECI
] = {
147 .bankid
= AB5500_BANK_DBI_ECI
,
149 .range
= (struct ab5500_reg_range
[]) {
153 .perm
= AB5500_PERM_RW
,
158 .perm
= AB5500_PERM_RW
,
163 .perm
= AB5500_PERM_RW
,
167 [AB5500_BANK_CHG
] = {
168 .bankid
= AB5500_BANK_CHG
,
170 .range
= (struct ab5500_reg_range
[]) {
174 .perm
= AB5500_PERM_RO
,
179 .perm
= AB5500_PERM_RW
,
183 [AB5500_BANK_FG_BATTCOM_ACC
] = {
184 .bankid
= AB5500_BANK_FG_BATTCOM_ACC
,
186 .range
= (struct ab5500_reg_range
[]) {
190 .perm
= AB5500_PERM_RO
,
195 .perm
= AB5500_PERM_RW
,
199 [AB5500_BANK_USB
] = {
200 .bankid
= AB5500_BANK_USB
,
202 .range
= (struct ab5500_reg_range
[]) {
206 .perm
= AB5500_PERM_RW
,
211 .perm
= AB5500_PERM_RW
,
216 .perm
= AB5500_PERM_RW
,
221 .perm
= AB5500_PERM_RO
,
226 .perm
= AB5500_PERM_RO
,
231 .perm
= AB5500_PERM_RW
,
236 .perm
= AB5500_PERM_RO
,
241 .perm
= AB5500_PERM_RO
,
246 .perm
= AB5500_PERM_RO
,
251 .perm
= AB5500_PERM_RO
,
256 .perm
= AB5500_PERM_RO
,
261 .perm
= AB5500_PERM_RO
,
266 .bankid
= AB5500_BANK_IT
,
268 .range
= (struct ab5500_reg_range
[]) {
272 .perm
= AB5500_PERM_RO
,
277 .perm
= AB5500_PERM_RO
,
282 .perm
= AB5500_PERM_RO
,
287 .perm
= AB5500_PERM_RO
,
291 [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST
] = {
292 .bankid
= AB5500_BANK_VDDDIG_IO_I2C_CLK_TST
,
294 .range
= (struct ab5500_reg_range
[]) {
298 .perm
= AB5500_PERM_RW
,
303 .perm
= AB5500_PERM_RW
,
308 .perm
= AB5500_PERM_RW
,
313 .perm
= AB5500_PERM_RW
,
318 .perm
= AB5500_PERM_RW
,
323 .perm
= AB5500_PERM_RW
,
328 .perm
= AB5500_PERM_RW
,
332 [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP
] = {
333 .bankid
= AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP
,
335 .range
= (struct ab5500_reg_range
[]) {
339 .perm
= AB5500_PERM_RW
,
344 .perm
= AB5500_PERM_RO
,
349 .perm
= AB5500_PERM_RW
,
354 .perm
= AB5500_PERM_RW
,
359 .perm
= AB5500_PERM_RW
,
364 .perm
= AB5500_PERM_RW
,
369 .perm
= AB5500_PERM_RW
,
374 .perm
= AB5500_PERM_RW
,
379 .perm
= AB5500_PERM_RW
,
384 .perm
= AB5500_PERM_RW
,
389 .perm
= AB5500_PERM_RW
,
394 .perm
= AB5500_PERM_RW
,
399 .perm
= AB5500_PERM_RW
,
403 [AB5500_BANK_VIBRA
] = {
404 .bankid
= AB5500_BANK_VIBRA
,
406 .range
= (struct ab5500_reg_range
[]) {
410 .perm
= AB5500_PERM_RW
,
415 .perm
= AB5500_PERM_RW
,
419 [AB5500_BANK_AUDIO_HEADSETUSB
] = {
420 .bankid
= AB5500_BANK_AUDIO_HEADSETUSB
,
422 .range
= (struct ab5500_reg_range
[]) {
426 .perm
= AB5500_PERM_RW
,
431 .perm
= AB5500_PERM_RW
,
435 [AB5500_BANK_SIM_USBSIM
] = {
436 .bankid
= AB5500_BANK_SIM_USBSIM
,
438 .range
= (struct ab5500_reg_range
[]) {
442 .perm
= AB5500_PERM_RW
,
446 [AB5500_BANK_VDENC
] = {
447 .bankid
= AB5500_BANK_VDENC
,
449 .range
= (struct ab5500_reg_range
[]) {
453 .perm
= AB5500_PERM_RW
,
458 .perm
= AB5500_PERM_RO
,
463 .perm
= AB5500_PERM_RW
,
468 .perm
= AB5500_PERM_RW
,
473 .perm
= AB5500_PERM_RW
,
478 .perm
= AB5500_PERM_RW
,
483 .perm
= AB5500_PERM_RW
,
488 .perm
= AB5500_PERM_RW
,
493 .perm
= AB5500_PERM_RW
,
498 .perm
= AB5500_PERM_RW
,
503 .perm
= AB5500_PERM_RW
,
508 .perm
= AB5500_PERM_RW
,
514 static int ab5500_registers_print(struct seq_file
*s
, void *p
)
516 struct ab5500
*ab
= s
->private;
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
,
524 bankinfo
[bank
].slave_addr
);
525 for (i
= 0; i
< ab5500_reg_ranges
[bank
].nranges
; i
++) {
529 for (reg
= ab5500_reg_ranges
[bank
].range
[i
].first
;
530 reg
<= ab5500_reg_ranges
[bank
].range
[i
].last
;
534 err
= ab5500_get_register_interruptible_raw(ab
,
538 dev_err(ab
->dev
, "get_reg failed %d"
539 "bank 0x%x reg 0x%x\n",
544 err
= seq_printf(s
, "[%d/0x%02X]: 0x%02X\n",
548 "seq_printf overflow\n");
550 * Error is not returned here since
551 * the output is wanted in any case
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
,
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
);
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;
594 unsigned long user_bank
;
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
))
603 err
= strict_strtoul(buf
, 0, &user_bank
);
607 if (user_bank
>= AB5500_NUM_BANKS
) {
609 "debugfs error input > number of banks\n");
613 ab
->debug_bank
= user_bank
;
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
);
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;
638 unsigned long user_address
;
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
))
647 err
= strict_strtoul(buf
, 0, &user_address
);
650 if (user_address
> 0xff) {
652 "debugfs error input > 0xff\n");
655 ab
->debug_address
= user_address
;
659 static int ab5500_val_print(struct seq_file
*s
, void *p
)
661 struct ab5500
*ab
= s
->private;
665 err
= ab5500_get_register_interruptible_raw(ab
, (u8
)ab
->debug_bank
,
666 (u8
)ab
->debug_address
, ®value
);
668 dev_err(ab
->dev
, "get_reg failed %d, bank 0x%x"
669 ", reg 0x%x\n", err
, ab
->debug_bank
,
673 seq_printf(s
, "0x%02X\n", regvalue
);
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;
690 unsigned long user_val
;
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
))
700 err
= strict_strtoul(buf
, 0, &user_val
);
703 if (user_val
> 0xff) {
705 "debugfs error input > 0xff\n");
708 err
= ab5500_mask_and_set_register_interruptible_raw(
709 ab
, (u8
)ab
->debug_bank
,
710 (u8
)ab
->debug_address
, 0xFF, (u8
)user_val
);
714 ab5500_get_register_interruptible_raw(ab
, (u8
)ab
->debug_bank
,
715 (u8
)ab
->debug_address
, ®value
);
722 static const struct file_operations ab5500_bank_fops
= {
723 .open
= ab5500_bank_open
,
724 .write
= ab5500_bank_write
,
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
,
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
,
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
);
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
;
786 exit_destroy_address
:
787 debugfs_remove(ab5500_address_file
);
789 debugfs_remove(ab5500_bank_file
);
791 debugfs_remove(ab5500_reg_file
);
793 debugfs_remove(ab5500_dir
);
795 dev_err(ab
->dev
, "failed to create debugfs entries.\n");
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
);