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);