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/module.h>
8 #include <linux/debugfs.h>
9 #include <linux/seq_file.h>
10 #include <linux/mfd/abx500.h>
11 #include <linux/mfd/abx500/ab5500.h>
12 #include <linux/uaccess.h>
14 #include "ab5500-core.h"
15 #include "ab5500-debugfs.h"
17 static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = {
19 .bankid = AB5500_BANK_LED,
21 .range = (struct ab5500_reg_range[]) {
25 .perm = AB5500_PERM_RW,
30 .bankid = AB5500_BANK_ADC,
32 .range = (struct ab5500_reg_range[]) {
36 .perm = AB5500_PERM_RO,
41 .perm = AB5500_PERM_RW,
46 .perm = AB5500_PERM_RO,
51 .perm = AB5500_PERM_RW,
56 .perm = AB5500_PERM_RW,
61 .perm = AB5500_PERM_RO,
66 .bankid = AB5500_BANK_RTC,
68 .range = (struct ab5500_reg_range[]) {
72 .perm = AB5500_PERM_RW,
77 .perm = AB5500_PERM_RW,
81 [AB5500_BANK_STARTUP] = {
82 .bankid = AB5500_BANK_STARTUP,
84 .range = (struct ab5500_reg_range[]) {
88 .perm = AB5500_PERM_RW,
93 .perm = AB5500_PERM_RW,
98 .perm = AB5500_PERM_RO,
103 .perm = AB5500_PERM_RW,
108 .perm = AB5500_PERM_RW,
113 .perm = AB5500_PERM_RW,
118 .perm = AB5500_PERM_RW,
123 .perm = AB5500_PERM_RW,
128 .perm = AB5500_PERM_RW,
133 .perm = AB5500_PERM_RW,
138 .perm = AB5500_PERM_RW,
143 .perm = AB5500_PERM_RW,
147 [AB5500_BANK_DBI_ECI] = {
148 .bankid = AB5500_BANK_DBI_ECI,
150 .range = (struct ab5500_reg_range[]) {
154 .perm = AB5500_PERM_RW,
159 .perm = AB5500_PERM_RW,
164 .perm = AB5500_PERM_RW,
168 [AB5500_BANK_CHG] = {
169 .bankid = AB5500_BANK_CHG,
171 .range = (struct ab5500_reg_range[]) {
175 .perm = AB5500_PERM_RO,
180 .perm = AB5500_PERM_RW,
184 [AB5500_BANK_FG_BATTCOM_ACC] = {
185 .bankid = AB5500_BANK_FG_BATTCOM_ACC,
187 .range = (struct ab5500_reg_range[]) {
191 .perm = AB5500_PERM_RO,
196 .perm = AB5500_PERM_RW,
200 [AB5500_BANK_USB] = {
201 .bankid = AB5500_BANK_USB,
203 .range = (struct ab5500_reg_range[]) {
207 .perm = AB5500_PERM_RW,
212 .perm = AB5500_PERM_RW,
217 .perm = AB5500_PERM_RW,
222 .perm = AB5500_PERM_RO,
227 .perm = AB5500_PERM_RO,
232 .perm = AB5500_PERM_RW,
237 .perm = AB5500_PERM_RO,
242 .perm = AB5500_PERM_RO,
247 .perm = AB5500_PERM_RO,
252 .perm = AB5500_PERM_RO,
257 .perm = AB5500_PERM_RO,
262 .perm = AB5500_PERM_RO,
267 .bankid = AB5500_BANK_IT,
269 .range = (struct ab5500_reg_range[]) {
273 .perm = AB5500_PERM_RO,
278 .perm = AB5500_PERM_RO,
283 .perm = AB5500_PERM_RO,
288 .perm = AB5500_PERM_RO,
292 [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
293 .bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST,
295 .range = (struct ab5500_reg_range[]) {
299 .perm = AB5500_PERM_RW,
304 .perm = AB5500_PERM_RW,
309 .perm = AB5500_PERM_RW,
314 .perm = AB5500_PERM_RW,
319 .perm = AB5500_PERM_RW,
324 .perm = AB5500_PERM_RW,
329 .perm = AB5500_PERM_RW,
333 [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
334 .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
336 .range = (struct ab5500_reg_range[]) {
340 .perm = AB5500_PERM_RW,
345 .perm = AB5500_PERM_RO,
350 .perm = AB5500_PERM_RW,
355 .perm = AB5500_PERM_RW,
360 .perm = AB5500_PERM_RW,
365 .perm = AB5500_PERM_RW,
370 .perm = AB5500_PERM_RW,
375 .perm = AB5500_PERM_RW,
380 .perm = AB5500_PERM_RW,
385 .perm = AB5500_PERM_RW,
390 .perm = AB5500_PERM_RW,
395 .perm = AB5500_PERM_RW,
400 .perm = AB5500_PERM_RW,
404 [AB5500_BANK_VIBRA] = {
405 .bankid = AB5500_BANK_VIBRA,
407 .range = (struct ab5500_reg_range[]) {
411 .perm = AB5500_PERM_RW,
416 .perm = AB5500_PERM_RW,
420 [AB5500_BANK_AUDIO_HEADSETUSB] = {
421 .bankid = AB5500_BANK_AUDIO_HEADSETUSB,
423 .range = (struct ab5500_reg_range[]) {
427 .perm = AB5500_PERM_RW,
432 .perm = AB5500_PERM_RW,
436 [AB5500_BANK_SIM_USBSIM] = {
437 .bankid = AB5500_BANK_SIM_USBSIM,
439 .range = (struct ab5500_reg_range[]) {
443 .perm = AB5500_PERM_RW,
447 [AB5500_BANK_VDENC] = {
448 .bankid = AB5500_BANK_VDENC,
450 .range = (struct ab5500_reg_range[]) {
454 .perm = AB5500_PERM_RW,
459 .perm = AB5500_PERM_RO,
464 .perm = AB5500_PERM_RW,
469 .perm = AB5500_PERM_RW,
474 .perm = AB5500_PERM_RW,
479 .perm = AB5500_PERM_RW,
484 .perm = AB5500_PERM_RW,
489 .perm = AB5500_PERM_RW,
494 .perm = AB5500_PERM_RW,
499 .perm = AB5500_PERM_RW,
504 .perm = AB5500_PERM_RW,
509 .perm = AB5500_PERM_RW,
515 static int ab5500_registers_print(struct seq_file *s, void *p)
517 struct ab5500 *ab = s->private;
519 u8 bank = (u8)ab->debug_bank;
521 seq_printf(s, "ab5500 register values:\n");
522 for (bank = 0; bank < AB5500_NUM_BANKS; bank++) {
523 seq_printf(s, " bank %u, %s (0x%x):\n", bank,
525 bankinfo[bank].slave_addr);
526 for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) {
530 for (reg = ab5500_reg_ranges[bank].range[i].first;
531 reg <= ab5500_reg_ranges[bank].range[i].last;
535 err = ab5500_get_register_interruptible_raw(ab,
539 dev_err(ab->dev, "get_reg failed %d"
540 "bank 0x%x reg 0x%x\n",
545 err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n",
549 "seq_printf overflow\n");
551 * Error is not returned here since
552 * the output is wanted in any case
562 static int ab5500_registers_open(struct inode *inode, struct file *file)
564 return single_open(file, ab5500_registers_print, inode->i_private);
567 static const struct file_operations ab5500_registers_fops = {
568 .open = ab5500_registers_open,
571 .release = single_release,
572 .owner = THIS_MODULE,
575 static int ab5500_bank_print(struct seq_file *s, void *p)
577 struct ab5500 *ab = s->private;
579 seq_printf(s, "%d\n", ab->debug_bank);
583 static int ab5500_bank_open(struct inode *inode, struct file *file)
585 return single_open(file, ab5500_bank_print, inode->i_private);
588 static ssize_t ab5500_bank_write(struct file *file,
589 const char __user *user_buf,
590 size_t count, loff_t *ppos)
592 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
595 unsigned long user_bank;
598 /* Get userspace string and assure termination */
599 buf_size = min(count, (sizeof(buf) - 1));
600 if (copy_from_user(buf, user_buf, buf_size))
604 err = strict_strtoul(buf, 0, &user_bank);
608 if (user_bank >= AB5500_NUM_BANKS) {
610 "debugfs error input > number of banks\n");
614 ab->debug_bank = user_bank;
619 static int ab5500_address_print(struct seq_file *s, void *p)
621 struct ab5500 *ab = s->private;
623 seq_printf(s, "0x%02X\n", ab->debug_address);
627 static int ab5500_address_open(struct inode *inode, struct file *file)
629 return single_open(file, ab5500_address_print, inode->i_private);
632 static ssize_t ab5500_address_write(struct file *file,
633 const char __user *user_buf,
634 size_t count, loff_t *ppos)
636 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
639 unsigned long user_address;
642 /* Get userspace string and assure termination */
643 buf_size = min(count, (sizeof(buf) - 1));
644 if (copy_from_user(buf, user_buf, buf_size))
648 err = strict_strtoul(buf, 0, &user_address);
651 if (user_address > 0xff) {
653 "debugfs error input > 0xff\n");
656 ab->debug_address = user_address;
660 static int ab5500_val_print(struct seq_file *s, void *p)
662 struct ab5500 *ab = s->private;
666 err = ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
667 (u8)ab->debug_address, ®value);
669 dev_err(ab->dev, "get_reg failed %d, bank 0x%x"
670 ", reg 0x%x\n", err, ab->debug_bank,
674 seq_printf(s, "0x%02X\n", regvalue);
679 static int ab5500_val_open(struct inode *inode, struct file *file)
681 return single_open(file, ab5500_val_print, inode->i_private);
684 static ssize_t ab5500_val_write(struct file *file,
685 const char __user *user_buf,
686 size_t count, loff_t *ppos)
688 struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
691 unsigned long user_val;
695 /* Get userspace string and assure termination */
696 buf_size = min(count, (sizeof(buf)-1));
697 if (copy_from_user(buf, user_buf, buf_size))
701 err = strict_strtoul(buf, 0, &user_val);
704 if (user_val > 0xff) {
706 "debugfs error input > 0xff\n");
709 err = ab5500_mask_and_set_register_interruptible_raw(
710 ab, (u8)ab->debug_bank,
711 (u8)ab->debug_address, 0xFF, (u8)user_val);
715 ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
716 (u8)ab->debug_address, ®value);
723 static const struct file_operations ab5500_bank_fops = {
724 .open = ab5500_bank_open,
725 .write = ab5500_bank_write,
728 .release = single_release,
729 .owner = THIS_MODULE,
732 static const struct file_operations ab5500_address_fops = {
733 .open = ab5500_address_open,
734 .write = ab5500_address_write,
737 .release = single_release,
738 .owner = THIS_MODULE,
741 static const struct file_operations ab5500_val_fops = {
742 .open = ab5500_val_open,
743 .write = ab5500_val_write,
746 .release = single_release,
747 .owner = THIS_MODULE,
750 static struct dentry *ab5500_dir;
751 static struct dentry *ab5500_reg_file;
752 static struct dentry *ab5500_bank_file;
753 static struct dentry *ab5500_address_file;
754 static struct dentry *ab5500_val_file;
756 void __init ab5500_setup_debugfs(struct ab5500 *ab)
758 ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP;
759 ab->debug_address = AB5500_CHIP_ID;
761 ab5500_dir = debugfs_create_dir("ab5500", NULL);
763 goto exit_no_debugfs;
765 ab5500_reg_file = debugfs_create_file("all-bank-registers",
766 S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops);
767 if (!ab5500_reg_file)
768 goto exit_destroy_dir;
770 ab5500_bank_file = debugfs_create_file("register-bank",
771 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops);
772 if (!ab5500_bank_file)
773 goto exit_destroy_reg;
775 ab5500_address_file = debugfs_create_file("register-address",
776 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops);
777 if (!ab5500_address_file)
778 goto exit_destroy_bank;
780 ab5500_val_file = debugfs_create_file("register-value",
781 (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops);
782 if (!ab5500_val_file)
783 goto exit_destroy_address;
787 exit_destroy_address:
788 debugfs_remove(ab5500_address_file);
790 debugfs_remove(ab5500_bank_file);
792 debugfs_remove(ab5500_reg_file);
794 debugfs_remove(ab5500_dir);
796 dev_err(ab->dev, "failed to create debugfs entries.\n");
800 void __exit ab5500_remove_debugfs(void)
802 debugfs_remove(ab5500_val_file);
803 debugfs_remove(ab5500_address_file);
804 debugfs_remove(ab5500_bank_file);
805 debugfs_remove(ab5500_reg_file);
806 debugfs_remove(ab5500_dir);