PageRenderTime 43ms CodeModel.GetById 15ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/mfd/ab8500-debugfs.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
C | 652 lines | 572 code | 55 blank | 25 comment | 20 complexity | b476f2babcd72944c88a42f5ed637100 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  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
 17static u32 debug_bank;
 18static 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 */
 26struct 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 */
 38struct 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
 49static 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 = NULL,
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 = NULL,
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 = NULL,
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 = NULL,
332	},
333	[0x12] = {
334		.num_ranges = 0,
335		.range = NULL,
336	},
337	[0x13] = {
338		.num_ranges = 0,
339		.range = NULL,
340	},
341	[0x14] = {
342		.num_ranges = 0,
343		.range = NULL,
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
356static 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
394static int ab8500_registers_open(struct inode *inode, struct file *file)
395{
396	return single_open(file, ab8500_registers_print, inode->i_private);
397}
398
399static 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
407static int ab8500_bank_print(struct seq_file *s, void *p)
408{
409	return seq_printf(s, "%d\n", debug_bank);
410}
411
412static int ab8500_bank_open(struct inode *inode, struct file *file)
413{
414	return single_open(file, ab8500_bank_print, inode->i_private);
415}
416
417static 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
447static int ab8500_address_print(struct seq_file *s, void *p)
448{
449	return seq_printf(s, "0x%02X\n", debug_address);
450}
451
452static int ab8500_address_open(struct inode *inode, struct file *file)
453{
454	return single_open(file, ab8500_address_print, inode->i_private);
455}
456
457static 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
484static 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
502static int ab8500_val_open(struct inode *inode, struct file *file)
503{
504	return single_open(file, ab8500_val_print, inode->i_private);
505}
506
507static 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
540static 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
549static 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
558static 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
567static struct dentry *ab8500_dir;
568static struct dentry *ab8500_reg_file;
569static struct dentry *ab8500_bank_file;
570static struct dentry *ab8500_address_file;
571static struct dentry *ab8500_val_file;
572
573static 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_IWUSR), 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_IWUSR), 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_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops);
600	if (!ab8500_val_file)
601		goto exit_destroy_address;
602
603	return 0;
604
605exit_destroy_address:
606	debugfs_remove(ab8500_address_file);
607exit_destroy_bank:
608	debugfs_remove(ab8500_bank_file);
609exit_destroy_reg:
610	debugfs_remove(ab8500_reg_file);
611exit_destroy_dir:
612	debugfs_remove(ab8500_dir);
613exit_no_debugfs:
614	dev_err(&plf->dev, "failed to create debugfs entries.\n");
615	return -ENOMEM;
616}
617
618static 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
629static 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
638static int __init ab8500_debug_init(void)
639{
640	return platform_driver_register(&ab8500_debug_driver);
641}
642
643static void __exit ab8500_debug_exit(void)
644{
645	platform_driver_unregister(&ab8500_debug_driver);
646}
647subsys_initcall(ab8500_debug_init);
648module_exit(ab8500_debug_exit);
649
650MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
651MODULE_DESCRIPTION("AB8500 DEBUG");
652MODULE_LICENSE("GPL v2");