8d1e05a3981595463774d8018ca8c67c615e42ab
[pandora-kernel.git] / drivers / mfd / ab8500-debugfs.c
1 /*
2  * Copyright (C) ST-Ericsson SA 2010
3  *
4  * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson.
5  * License Terms: GNU General Public License v2
6  */
7
8 #include <linux/seq_file.h>
9 #include <linux/uaccess.h>
10 #include <linux/fs.h>
11 #include <linux/debugfs.h>
12 #include <linux/platform_device.h>
13
14 #include <linux/mfd/abx500.h>
15 #include <linux/mfd/ab8500.h>
16
17 static u32 debug_bank;
18 static u32 debug_address;
19
20 /**
21  * struct ab8500_reg_range
22  * @first: the first address of the range
23  * @last: the last address of the range
24  * @perm: access permissions for the range
25  */
26 struct ab8500_reg_range {
27        u8 first;
28        u8 last;
29        u8 perm;
30 };
31
32 /**
33  * struct ab8500_i2c_ranges
34  * @num_ranges: the number of ranges in the list
35  * @bankid: bank identifier
36  * @range: the list of register ranges
37  */
38 struct ab8500_i2c_ranges {
39        u8 num_ranges;
40        u8 bankid;
41        const struct ab8500_reg_range *range;
42 };
43
44 #define AB8500_NAME_STRING "ab8500"
45 #define AB8500_NUM_BANKS 22
46
47 #define AB8500_REV_REG 0x80
48
49 static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = {
50        [0x0] = {
51                .num_ranges = 0,
52                .range = 0,
53        },
54        [AB8500_SYS_CTRL1_BLOCK] = {
55                .num_ranges = 3,
56                .range = (struct ab8500_reg_range[]) {
57                        {
58                                .first = 0x00,
59                                .last = 0x02,
60                        },
61                        {
62                                .first = 0x42,
63                                .last = 0x42,
64                        },
65                        {
66                                .first = 0x80,
67                                .last = 0x81,
68                        },
69                },
70        },
71        [AB8500_SYS_CTRL2_BLOCK] = {
72                .num_ranges = 4,
73                .range = (struct ab8500_reg_range[]) {
74                        {
75                                .first = 0x00,
76                                .last = 0x0D,
77                        },
78                        {
79                                .first = 0x0F,
80                                .last = 0x17,
81                        },
82                        {
83                                .first = 0x30,
84                                .last = 0x30,
85                        },
86                        {
87                                .first = 0x32,
88                                .last = 0x33,
89                        },
90                },
91        },
92        [AB8500_REGU_CTRL1] = {
93                .num_ranges = 3,
94                .range = (struct ab8500_reg_range[]) {
95                        {
96                                .first = 0x00,
97                                .last = 0x00,
98                        },
99                        {
100                                .first = 0x03,
101                                .last = 0x10,
102                        },
103                        {
104                                .first = 0x80,
105                                .last = 0x84,
106                        },
107                },
108        },
109        [AB8500_REGU_CTRL2] = {
110                .num_ranges = 5,
111                .range = (struct ab8500_reg_range[]) {
112                        {
113                                .first = 0x00,
114                                .last = 0x15,
115                        },
116                        {
117                                .first = 0x17,
118                                .last = 0x19,
119                        },
120                        {
121                                .first = 0x1B,
122                                .last = 0x1D,
123                        },
124                        {
125                                .first = 0x1F,
126                                .last = 0x22,
127                        },
128                        {
129                                .first = 0x40,
130                                .last = 0x44,
131                        },
132                        /* 0x80-0x8B is SIM registers and should
133                         * not be accessed from here */
134                },
135        },
136        [AB8500_USB] = {
137                .num_ranges = 2,
138                .range = (struct ab8500_reg_range[]) {
139                        {
140                                .first = 0x80,
141                                .last = 0x83,
142                        },
143                        {
144                                .first = 0x87,
145                                .last = 0x8A,
146                        },
147                },
148        },
149        [AB8500_TVOUT] = {
150                .num_ranges = 9,
151                .range = (struct ab8500_reg_range[]) {
152                        {
153                                .first = 0x00,
154                                .last = 0x12,
155                        },
156                        {
157                                .first = 0x15,
158                                .last = 0x17,
159                        },
160                        {
161                                .first = 0x19,
162                                .last = 0x21,
163                        },
164                        {
165                                .first = 0x27,
166                                .last = 0x2C,
167                        },
168                        {
169                                .first = 0x41,
170                                .last = 0x41,
171                        },
172                        {
173                                .first = 0x45,
174                                .last = 0x5B,
175                        },
176                        {
177                                .first = 0x5D,
178                                .last = 0x5D,
179                        },
180                        {
181                                .first = 0x69,
182                                .last = 0x69,
183                        },
184                        {
185                                .first = 0x80,
186                                .last = 0x81,
187                        },
188                },
189        },
190        [AB8500_DBI] = {
191                .num_ranges = 0,
192                .range = 0,
193        },
194        [AB8500_ECI_AV_ACC] = {
195                .num_ranges = 1,
196                .range = (struct ab8500_reg_range[]) {
197                        {
198                                .first = 0x80,
199                                .last = 0x82,
200                        },
201                },
202        },
203        [0x9] = {
204                .num_ranges = 0,
205                .range = 0,
206        },
207        [AB8500_GPADC] = {
208                .num_ranges = 1,
209                .range = (struct ab8500_reg_range[]) {
210                        {
211                                .first = 0x00,
212                                .last = 0x08,
213                        },
214                },
215        },
216        [AB8500_CHARGER] = {
217                .num_ranges = 8,
218                .range = (struct ab8500_reg_range[]) {
219                        {
220                                .first = 0x00,
221                                .last = 0x03,
222                        },
223                        {
224                                .first = 0x05,
225                                .last = 0x05,
226                        },
227                        {
228                                .first = 0x40,
229                                .last = 0x40,
230                        },
231                        {
232                                .first = 0x42,
233                                .last = 0x42,
234                        },
235                        {
236                                .first = 0x44,
237                                .last = 0x44,
238                        },
239                        {
240                                .first = 0x50,
241                                .last = 0x55,
242                        },
243                        {
244                                .first = 0x80,
245                                .last = 0x82,
246                        },
247                        {
248                                .first = 0xC0,
249                                .last = 0xC2,
250                        },
251                },
252        },
253        [AB8500_GAS_GAUGE] = {
254                .num_ranges = 3,
255                .range = (struct ab8500_reg_range[]) {
256                        {
257                                .first = 0x00,
258                                .last = 0x00,
259                        },
260                        {
261                                .first = 0x07,
262                                .last = 0x0A,
263                        },
264                        {
265                                .first = 0x10,
266                                .last = 0x14,
267                        },
268                },
269        },
270        [AB8500_AUDIO] = {
271                .num_ranges = 1,
272                .range = (struct ab8500_reg_range[]) {
273                        {
274                                .first = 0x00,
275                                .last = 0x6F,
276                        },
277                },
278        },
279        [AB8500_INTERRUPT] = {
280                .num_ranges = 0,
281                .range = 0,
282        },
283        [AB8500_RTC] = {
284                .num_ranges = 1,
285                .range = (struct ab8500_reg_range[]) {
286                        {
287                                .first = 0x00,
288                                .last = 0x0F,
289                        },
290                },
291        },
292        [AB8500_MISC] = {
293                .num_ranges = 8,
294                .range = (struct ab8500_reg_range[]) {
295                        {
296                                .first = 0x00,
297                                .last = 0x05,
298                        },
299                        {
300                                .first = 0x10,
301                                .last = 0x15,
302                        },
303                        {
304                                .first = 0x20,
305                                .last = 0x25,
306                        },
307                        {
308                                .first = 0x30,
309                                .last = 0x35,
310                        },
311                        {
312                                .first = 0x40,
313                                .last = 0x45,
314                        },
315                        {
316                                .first = 0x50,
317                                .last = 0x50,
318                        },
319                        {
320                                .first = 0x60,
321                                .last = 0x67,
322                        },
323                        {
324                                .first = 0x80,
325                                .last = 0x80,
326                        },
327                },
328        },
329        [0x11] = {
330                .num_ranges = 0,
331                .range = 0,
332        },
333        [0x12] = {
334                .num_ranges = 0,
335                .range = 0,
336        },
337        [0x13] = {
338                .num_ranges = 0,
339                .range = 0,
340        },
341        [0x14] = {
342                .num_ranges = 0,
343                .range = 0,
344        },
345        [AB8500_OTP_EMUL] = {
346                .num_ranges = 1,
347                .range = (struct ab8500_reg_range[]) {
348                        {
349                                .first = 0x01,
350                                .last = 0x0F,
351                        },
352                },
353        },
354 };
355
356 static int ab8500_registers_print(struct seq_file *s, void *p)
357 {
358        struct device *dev = s->private;
359        unsigned int i;
360        u32 bank = debug_bank;
361
362        seq_printf(s, AB8500_NAME_STRING " register values:\n");
363
364        seq_printf(s, " bank %u:\n", bank);
365        for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
366                u32 reg;
367
368                for (reg = debug_ranges[bank].range[i].first;
369                        reg <= debug_ranges[bank].range[i].last;
370                        reg++) {
371                        u8 value;
372                        int err;
373
374                        err = abx500_get_register_interruptible(dev,
375                                (u8)bank, (u8)reg, &value);
376                        if (err < 0) {
377                                dev_err(dev, "ab->read fail %d\n", err);
378                                return err;
379                        }
380
381                        err = seq_printf(s, "  [%u/0x%02X]: 0x%02X\n", bank,
382                                reg, value);
383                        if (err < 0) {
384                                dev_err(dev, "seq_printf overflow\n");
385                                /* Error is not returned here since
386                                 * the output is wanted in any case */
387                                return 0;
388                        }
389                }
390        }
391        return 0;
392 }
393
394 static int ab8500_registers_open(struct inode *inode, struct file *file)
395 {
396        return single_open(file, ab8500_registers_print, inode->i_private);
397 }
398
399 static const struct file_operations ab8500_registers_fops = {
400        .open = ab8500_registers_open,
401        .read = seq_read,
402        .llseek = seq_lseek,
403        .release = single_release,
404        .owner = THIS_MODULE,
405 };
406
407 static int ab8500_bank_print(struct seq_file *s, void *p)
408 {
409        return seq_printf(s, "%d\n", debug_bank);
410 }
411
412 static int ab8500_bank_open(struct inode *inode, struct file *file)
413 {
414        return single_open(file, ab8500_bank_print, inode->i_private);
415 }
416
417 static ssize_t ab8500_bank_write(struct file *file,
418        const char __user *user_buf,
419        size_t count, loff_t *ppos)
420 {
421        struct device *dev = ((struct seq_file *)(file->private_data))->private;
422        char buf[32];
423        int buf_size;
424        unsigned long user_bank;
425        int err;
426
427        /* Get userspace string and assure termination */
428        buf_size = min(count, (sizeof(buf) - 1));
429        if (copy_from_user(buf, user_buf, buf_size))
430                return -EFAULT;
431        buf[buf_size] = 0;
432
433        err = strict_strtoul(buf, 0, &user_bank);
434        if (err)
435                return -EINVAL;
436
437        if (user_bank >= AB8500_NUM_BANKS) {
438                dev_err(dev, "debugfs error input > number of banks\n");
439                return -EINVAL;
440        }
441
442        debug_bank = user_bank;
443
444        return buf_size;
445 }
446
447 static int ab8500_address_print(struct seq_file *s, void *p)
448 {
449        return seq_printf(s, "0x%02X\n", debug_address);
450 }
451
452 static int ab8500_address_open(struct inode *inode, struct file *file)
453 {
454        return single_open(file, ab8500_address_print, inode->i_private);
455 }
456
457 static ssize_t ab8500_address_write(struct file *file,
458        const char __user *user_buf,
459        size_t count, loff_t *ppos)
460 {
461        struct device *dev = ((struct seq_file *)(file->private_data))->private;
462        char buf[32];
463        int buf_size;
464        unsigned long user_address;
465        int err;
466
467        /* Get userspace string and assure termination */
468        buf_size = min(count, (sizeof(buf) - 1));
469        if (copy_from_user(buf, user_buf, buf_size))
470                return -EFAULT;
471        buf[buf_size] = 0;
472
473        err = strict_strtoul(buf, 0, &user_address);
474        if (err)
475                return -EINVAL;
476        if (user_address > 0xff) {
477                dev_err(dev, "debugfs error input > 0xff\n");
478                return -EINVAL;
479        }
480        debug_address = user_address;
481        return buf_size;
482 }
483
484 static int ab8500_val_print(struct seq_file *s, void *p)
485 {
486        struct device *dev = s->private;
487        int ret;
488        u8 regvalue;
489
490        ret = abx500_get_register_interruptible(dev,
491                (u8)debug_bank, (u8)debug_address, &regvalue);
492        if (ret < 0) {
493                dev_err(dev, "abx500_get_reg fail %d, %d\n",
494                        ret, __LINE__);
495                return -EINVAL;
496        }
497        seq_printf(s, "0x%02X\n", regvalue);
498
499        return 0;
500 }
501
502 static int ab8500_val_open(struct inode *inode, struct file *file)
503 {
504        return single_open(file, ab8500_val_print, inode->i_private);
505 }
506
507 static ssize_t ab8500_val_write(struct file *file,
508        const char __user *user_buf,
509        size_t count, loff_t *ppos)
510 {
511        struct device *dev = ((struct seq_file *)(file->private_data))->private;
512        char buf[32];
513        int buf_size;
514        unsigned long user_val;
515        int err;
516
517        /* Get userspace string and assure termination */
518        buf_size = min(count, (sizeof(buf)-1));
519        if (copy_from_user(buf, user_buf, buf_size))
520                return -EFAULT;
521        buf[buf_size] = 0;
522
523        err = strict_strtoul(buf, 0, &user_val);
524        if (err)
525                return -EINVAL;
526        if (user_val > 0xff) {
527                dev_err(dev, "debugfs error input > 0xff\n");
528                return -EINVAL;
529        }
530        err = abx500_set_register_interruptible(dev,
531                (u8)debug_bank, debug_address, (u8)user_val);
532        if (err < 0) {
533                printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
534                return -EINVAL;
535        }
536
537        return buf_size;
538 }
539
540 static const struct file_operations ab8500_bank_fops = {
541        .open = ab8500_bank_open,
542        .write = ab8500_bank_write,
543        .read = seq_read,
544        .llseek = seq_lseek,
545        .release = single_release,
546        .owner = THIS_MODULE,
547 };
548
549 static const struct file_operations ab8500_address_fops = {
550        .open = ab8500_address_open,
551        .write = ab8500_address_write,
552        .read = seq_read,
553        .llseek = seq_lseek,
554        .release = single_release,
555        .owner = THIS_MODULE,
556 };
557
558 static const struct file_operations ab8500_val_fops = {
559        .open = ab8500_val_open,
560        .write = ab8500_val_write,
561        .read = seq_read,
562        .llseek = seq_lseek,
563        .release = single_release,
564        .owner = THIS_MODULE,
565 };
566
567 static struct dentry *ab8500_dir;
568 static struct dentry *ab8500_reg_file;
569 static struct dentry *ab8500_bank_file;
570 static struct dentry *ab8500_address_file;
571 static struct dentry *ab8500_val_file;
572
573 static int __devinit ab8500_debug_probe(struct platform_device *plf)
574 {
575        debug_bank = AB8500_MISC;
576        debug_address = AB8500_REV_REG & 0x00FF;
577
578        ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
579        if (!ab8500_dir)
580                goto exit_no_debugfs;
581
582        ab8500_reg_file = debugfs_create_file("all-bank-registers",
583                S_IRUGO, ab8500_dir, &plf->dev, &ab8500_registers_fops);
584        if (!ab8500_reg_file)
585                goto exit_destroy_dir;
586
587        ab8500_bank_file = debugfs_create_file("register-bank",
588                (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops);
589        if (!ab8500_bank_file)
590                goto exit_destroy_reg;
591
592        ab8500_address_file = debugfs_create_file("register-address",
593                (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev,
594                &ab8500_address_fops);
595        if (!ab8500_address_file)
596                goto exit_destroy_bank;
597
598        ab8500_val_file = debugfs_create_file("register-value",
599                (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops);
600        if (!ab8500_val_file)
601                goto exit_destroy_address;
602
603        return 0;
604
605 exit_destroy_address:
606        debugfs_remove(ab8500_address_file);
607 exit_destroy_bank:
608        debugfs_remove(ab8500_bank_file);
609 exit_destroy_reg:
610        debugfs_remove(ab8500_reg_file);
611 exit_destroy_dir:
612        debugfs_remove(ab8500_dir);
613 exit_no_debugfs:
614        dev_err(&plf->dev, "failed to create debugfs entries.\n");
615        return -ENOMEM;
616 }
617
618 static int __devexit ab8500_debug_remove(struct platform_device *plf)
619 {
620        debugfs_remove(ab8500_val_file);
621        debugfs_remove(ab8500_address_file);
622        debugfs_remove(ab8500_bank_file);
623        debugfs_remove(ab8500_reg_file);
624        debugfs_remove(ab8500_dir);
625
626        return 0;
627 }
628
629 static struct platform_driver ab8500_debug_driver = {
630        .driver = {
631                .name = "ab8500-debug",
632                .owner = THIS_MODULE,
633        },
634        .probe  = ab8500_debug_probe,
635        .remove = __devexit_p(ab8500_debug_remove)
636 };
637
638 static int __init ab8500_debug_init(void)
639 {
640        return platform_driver_register(&ab8500_debug_driver);
641 }
642
643 static void __exit ab8500_debug_exit(void)
644 {
645        platform_driver_unregister(&ab8500_debug_driver);
646 }
647 subsys_initcall(ab8500_debug_init);
648 module_exit(ab8500_debug_exit);
649
650 MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
651 MODULE_DESCRIPTION("AB8500 DEBUG");
652 MODULE_LICENSE("GPL v2");