rk3188:pmu:rt5025:modify some bug for pmu charger & irq & guage
[firefly-linux-kernel-4.4.55.git] / drivers / mfd / rt5025-debug.c
1 /*
2  *  drivers/mfd/rt5025-debug.c
3  *  Driver foo Richtek RT5025 PMIC Debug
4  *
5  *  Copyright (C) 2013 Richtek Electronics
6  *  cy_huang <cy_huang@richtek.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/err.h>
16 #include <linux/i2c.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19
20 #include <linux/uaccess.h>
21 #include <linux/debugfs.h>
22 #include <linux/string.h>
23
24 #include <linux/mfd/rt5025.h>
25
26 struct rt5025_debug_info {
27         struct i2c_client *i2c;
28 };
29
30 static struct i2c_client *client;
31 static struct dentry *debugfs_rt_dent;
32 static struct dentry *debugfs_peek;
33 static struct dentry *debugfs_poke;
34
35 static unsigned char read_data;
36
37 static int reg_debug_open(struct inode *inode, struct file *file)
38 {
39         file->private_data = inode->i_private;
40         return 0;
41 }
42
43 static int get_parameters(char *buf, long int *param1, int num_of_par)
44 {
45         char *token;
46         int base, cnt;
47
48         token = strsep(&buf, " ");
49
50         for (cnt = 0; cnt < num_of_par; cnt++) {
51                 if (token != NULL) {
52                         if ((token[1] == 'x') || (token[1] == 'X'))
53                                 base = 16;
54                         else
55                                 base = 10;
56
57                         if (strict_strtoul(token, base, &param1[cnt]) != 0)
58                                 return -EINVAL;
59
60                         token = strsep(&buf, " ");
61                         }
62                 else
63                         return -EINVAL;
64         }
65         return 0;
66 }
67
68 static ssize_t reg_debug_read(struct file *filp, char __user *ubuf,
69                                 size_t count, loff_t *ppos)
70 {
71         char lbuf[8];
72         
73         snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
74         return simple_read_from_buffer(ubuf, count, ppos, lbuf, strlen(lbuf));
75 }
76
77 static ssize_t reg_debug_write(struct file *filp,
78         const char __user *ubuf, size_t cnt, loff_t *ppos)
79 {
80         char *access_str = filp->private_data;
81         char lbuf[32];
82         int rc;
83         long int param[5];
84
85         if (cnt > sizeof(lbuf) - 1)
86                 return -EINVAL;
87
88         rc = copy_from_user(lbuf, ubuf, cnt);
89         if (rc)
90                 return -EFAULT;
91
92         lbuf[cnt] = '\0';
93
94         if (!strcmp(access_str, "poke")) {
95                 /* write */
96                 rc = get_parameters(lbuf, param, 2);
97                 if ((param[0] <= 0xFF) && (param[1] <= 0xFF) && (rc == 0))
98                 {
99                         rt5025_reg_write(client, param[0], (unsigned char)param[1]);
100                 }
101                 else
102                         rc = -EINVAL;
103         } else if (!strcmp(access_str, "peek")) {
104                 /* read */
105                 rc = get_parameters(lbuf, param, 1);
106                 if ((param[0] <= 0xFF) && (rc == 0))
107                 {
108                         read_data = rt5025_reg_read(client, param[0]);
109                 }
110                 else
111                         rc = -EINVAL;
112         }
113
114         if (rc == 0)
115                 rc = cnt;
116
117         return rc;
118 }
119
120 static const struct file_operations reg_debug_ops = {
121         .open = reg_debug_open,
122         .write = reg_debug_write,
123         .read = reg_debug_read
124 };
125
126 static int __devinit rt5025_debug_probe(struct platform_device *pdev)
127 {
128         struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
129         struct rt5025_debug_info *di;
130
131         di = kzalloc(sizeof(*di), GFP_KERNEL);
132         if (!di)
133                 return -ENOMEM;
134
135         di->i2c = chip->i2c;
136
137         RTINFO("add debugfs for core RT5025");
138         client = chip->i2c;
139         debugfs_rt_dent = debugfs_create_dir("rt5025_dbg", 0);
140         if (!IS_ERR(debugfs_rt_dent)) {
141                 debugfs_peek = debugfs_create_file("peek",
142                 S_IFREG | S_IRUGO, debugfs_rt_dent,
143                 (void *) "peek", &reg_debug_ops);
144
145                 debugfs_poke = debugfs_create_file("poke",
146                 S_IFREG | S_IRUGO, debugfs_rt_dent,
147                 (void *) "poke", &reg_debug_ops);
148         }
149
150         platform_set_drvdata(pdev, di);
151
152         return 0;
153 }
154
155 static int __devexit rt5025_debug_remove(struct platform_device *pdev)
156 {
157         struct rt5025_debug_info *di = platform_get_drvdata(pdev);
158
159         if (!IS_ERR(debugfs_rt_dent))
160                 debugfs_remove_recursive(debugfs_rt_dent);
161
162         kfree(di);
163         return 0;
164 }
165
166 static struct platform_driver rt5025_debug_driver = 
167 {
168         .driver = {
169                 .name = RT5025_DEVICE_NAME "-debug",
170                 .owner = THIS_MODULE,
171         },
172         .probe = rt5025_debug_probe,
173         .remove = __devexit_p(rt5025_debug_remove),
174 };
175
176 static int __init rt5025_debug_init(void)
177 {
178         return platform_driver_register(&rt5025_debug_driver);
179 }
180 module_init(rt5025_debug_init);
181
182 static void __exit rt5025_debug_exit(void)
183 {
184         platform_driver_unregister(&rt5025_debug_driver);
185 }
186 module_exit(rt5025_debug_exit);
187
188 MODULE_LICENSE("GPL v2");
189 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
190 MODULE_DESCRIPTION("Debug driver for RT5025");
191 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-debug");