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