Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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	unsigned long user_bank;
423	int err;
424
425	/* Get userspace string and assure termination */
426	err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
427	if (err)
428		return err;
429
430	if (user_bank >= AB8500_NUM_BANKS) {
431		dev_err(dev, "debugfs error input > number of banks\n");
432		return -EINVAL;
433	}
434
435	debug_bank = user_bank;
436
437	return count;
438}
439
440static int ab8500_address_print(struct seq_file *s, void *p)
441{
442	return seq_printf(s, "0x%02X\n", debug_address);
443}
444
445static int ab8500_address_open(struct inode *inode, struct file *file)
446{
447	return single_open(file, ab8500_address_print, inode->i_private);
448}
449
450static ssize_t ab8500_address_write(struct file *file,
451	const char __user *user_buf,
452	size_t count, loff_t *ppos)
453{
454	struct device *dev = ((struct seq_file *)(file->private_data))->private;
455	unsigned long user_address;
456	int err;
457
458	/* Get userspace string and assure termination */
459	err = kstrtoul_from_user(user_buf, count, 0, &user_address);
460	if (err)
461		return err;
462
463	if (user_address > 0xff) {
464		dev_err(dev, "debugfs error input > 0xff\n");
465		return -EINVAL;
466	}
467	debug_address = user_address;
468	return count;
469}
470
471static int ab8500_val_print(struct seq_file *s, void *p)
472{
473	struct device *dev = s->private;
474	int ret;
475	u8 regvalue;
476
477	ret = abx500_get_register_interruptible(dev,
478		(u8)debug_bank, (u8)debug_address, &regvalue);
479	if (ret < 0) {
480		dev_err(dev, "abx500_get_reg fail %d, %d\n",
481			ret, __LINE__);
482		return -EINVAL;
483	}
484	seq_printf(s, "0x%02X\n", regvalue);
485
486	return 0;
487}
488
489static int ab8500_val_open(struct inode *inode, struct file *file)
490{
491	return single_open(file, ab8500_val_print, inode->i_private);
492}
493
494static ssize_t ab8500_val_write(struct file *file,
495	const char __user *user_buf,
496	size_t count, loff_t *ppos)
497{
498	struct device *dev = ((struct seq_file *)(file->private_data))->private;
499	unsigned long user_val;
500	int err;
501
502	/* Get userspace string and assure termination */
503	err = kstrtoul_from_user(user_buf, count, 0, &user_val);
504	if (err)
505		return err;
506
507	if (user_val > 0xff) {
508		dev_err(dev, "debugfs error input > 0xff\n");
509		return -EINVAL;
510	}
511	err = abx500_set_register_interruptible(dev,
512		(u8)debug_bank, debug_address, (u8)user_val);
513	if (err < 0) {
514		printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
515		return -EINVAL;
516	}
517
518	return count;
519}
520
521static const struct file_operations ab8500_bank_fops = {
522	.open = ab8500_bank_open,
523	.write = ab8500_bank_write,
524	.read = seq_read,
525	.llseek = seq_lseek,
526	.release = single_release,
527	.owner = THIS_MODULE,
528};
529
530static const struct file_operations ab8500_address_fops = {
531	.open = ab8500_address_open,
532	.write = ab8500_address_write,
533	.read = seq_read,
534	.llseek = seq_lseek,
535	.release = single_release,
536	.owner = THIS_MODULE,
537};
538
539static const struct file_operations ab8500_val_fops = {
540	.open = ab8500_val_open,
541	.write = ab8500_val_write,
542	.read = seq_read,
543	.llseek = seq_lseek,
544	.release = single_release,
545	.owner = THIS_MODULE,
546};
547
548static struct dentry *ab8500_dir;
549static struct dentry *ab8500_reg_file;
550static struct dentry *ab8500_bank_file;
551static struct dentry *ab8500_address_file;
552static struct dentry *ab8500_val_file;
553
554static int __devinit ab8500_debug_probe(struct platform_device *plf)
555{
556	debug_bank = AB8500_MISC;
557	debug_address = AB8500_REV_REG & 0x00FF;
558
559	ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
560	if (!ab8500_dir)
561		goto exit_no_debugfs;
562
563	ab8500_reg_file = debugfs_create_file("all-bank-registers",
564		S_IRUGO, ab8500_dir, &plf->dev, &ab8500_registers_fops);
565	if (!ab8500_reg_file)
566		goto exit_destroy_dir;
567
568	ab8500_bank_file = debugfs_create_file("register-bank",
569		(S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_bank_fops);
570	if (!ab8500_bank_file)
571		goto exit_destroy_reg;
572
573	ab8500_address_file = debugfs_create_file("register-address",
574		(S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev,
575		&ab8500_address_fops);
576	if (!ab8500_address_file)
577		goto exit_destroy_bank;
578
579	ab8500_val_file = debugfs_create_file("register-value",
580		(S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops);
581	if (!ab8500_val_file)
582		goto exit_destroy_address;
583
584	return 0;
585
586exit_destroy_address:
587	debugfs_remove(ab8500_address_file);
588exit_destroy_bank:
589	debugfs_remove(ab8500_bank_file);
590exit_destroy_reg:
591	debugfs_remove(ab8500_reg_file);
592exit_destroy_dir:
593	debugfs_remove(ab8500_dir);
594exit_no_debugfs:
595	dev_err(&plf->dev, "failed to create debugfs entries.\n");
596	return -ENOMEM;
597}
598
599static int __devexit ab8500_debug_remove(struct platform_device *plf)
600{
601	debugfs_remove(ab8500_val_file);
602	debugfs_remove(ab8500_address_file);
603	debugfs_remove(ab8500_bank_file);
604	debugfs_remove(ab8500_reg_file);
605	debugfs_remove(ab8500_dir);
606
607	return 0;
608}
609
610static struct platform_driver ab8500_debug_driver = {
611	.driver = {
612		.name = "ab8500-debug",
613		.owner = THIS_MODULE,
614	},
615	.probe  = ab8500_debug_probe,
616	.remove = __devexit_p(ab8500_debug_remove)
617};
618
619static int __init ab8500_debug_init(void)
620{
621	return platform_driver_register(&ab8500_debug_driver);
622}
623
624static void __exit ab8500_debug_exit(void)
625{
626	platform_driver_unregister(&ab8500_debug_driver);
627}
628subsys_initcall(ab8500_debug_init);
629module_exit(ab8500_debug_exit);
630
631MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
632MODULE_DESCRIPTION("AB8500 DEBUG");
633MODULE_LICENSE("GPL v2");