blob: ba25f95e16776ba35fe73d9b13a8352406ca486c [file] [log] [blame]
Mattias Wallin5814fc32010-09-13 16:05:04 +02001/*
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 */
carriere etienne0fbce762011-04-08 16:26:36 +02007/*
8 * AB8500 register access
9 * ======================
10 *
11 * read:
12 * # echo BANK > <debugfs>/ab8500/register-bank
13 * # echo ADDR > <debugfs>/ab8500/register-address
14 * # cat <debugfs>/ab8500/register-value
15 *
16 * write:
17 * # echo BANK > <debugfs>/ab8500/register-bank
18 * # echo ADDR > <debugfs>/ab8500/register-address
19 * # echo VALUE > <debugfs>/ab8500/register-value
20 *
21 * read all registers from a bank:
22 * # echo BANK > <debugfs>/ab8500/register-bank
23 * # cat <debugfs>/ab8500/all-bank-register
24 *
25 * BANK target AB8500 register bank
26 * ADDR target AB8500 register address
27 * VALUE decimal or 0x-prefixed hexadecimal
28 *
29 *
30 * User Space notification on AB8500 IRQ
31 * =====================================
32 *
33 * Allows user space entity to be notified when target AB8500 IRQ occurs.
34 * When subscribed, a sysfs entry is created in ab8500.i2c platform device.
35 * One can pool this file to get target IRQ occurence information.
36 *
37 * subscribe to an AB8500 IRQ:
38 * # echo IRQ > <debugfs>/ab8500/irq-subscribe
39 *
40 * unsubscribe from an AB8500 IRQ:
41 * # echo IRQ > <debugfs>/ab8500/irq-unsubscribe
42 *
43 *
44 * AB8500 register formated read/write access
45 * ==========================================
46 *
47 * Read: read data, data>>SHIFT, data&=MASK, output data
48 * [0xABCDEF98] shift=12 mask=0xFFF => 0x00000CDE
49 * Write: read data, data &= ~(MASK<<SHIFT), data |= (VALUE<<SHIFT), write data
50 * [0xABCDEF98] shift=12 mask=0xFFF value=0x123 => [0xAB123F98]
51 *
52 * Usage:
53 * # echo "CMD [OPTIONS] BANK ADRESS [VALUE]" > $debugfs/ab8500/hwreg
54 *
55 * CMD read read access
56 * write write access
57 *
58 * BANK target reg bank
59 * ADDRESS target reg address
60 * VALUE (write) value to be updated
61 *
62 * OPTIONS
63 * -d|-dec (read) output in decimal
64 * -h|-hexa (read) output in 0x-hexa (default)
65 * -l|-w|-b 32bit (default), 16bit or 8bit reg access
66 * -m|-mask MASK 0x-hexa mask (default 0xFFFFFFFF)
67 * -s|-shift SHIFT bit shift value (read:left, write:right)
68 * -o|-offset OFFSET address offset to add to ADDRESS value
69 *
70 * Warning: bit shift operation is applied to bit-mask.
71 * Warning: bit shift direction depends on read or right command.
72 */
Mattias Wallin5814fc32010-09-13 16:05:04 +020073
74#include <linux/seq_file.h>
75#include <linux/uaccess.h>
76#include <linux/fs.h>
Paul Gortmaker4e36dd32011-07-03 15:13:27 -040077#include <linux/module.h>
Mattias Wallin5814fc32010-09-13 16:05:04 +020078#include <linux/debugfs.h>
79#include <linux/platform_device.h>
Lee Jones4b8ac082013-01-14 16:10:36 +000080#include <linux/interrupt.h>
81#include <linux/kobject.h>
82#include <linux/slab.h>
Mattias Wallin5814fc32010-09-13 16:05:04 +020083
84#include <linux/mfd/abx500.h>
John Beckett1478a312011-05-31 13:54:27 +010085#include <linux/mfd/abx500/ab8500-gpadc.h>
Mattias Wallin5814fc32010-09-13 16:05:04 +020086
carriere etienne0fbce762011-04-08 16:26:36 +020087#ifdef CONFIG_DEBUG_FS
88#include <linux/string.h>
89#include <linux/ctype.h>
90#endif
91
Mattias Wallin5814fc32010-09-13 16:05:04 +020092static u32 debug_bank;
93static u32 debug_address;
94
Lee Jones4b8ac082013-01-14 16:10:36 +000095static int irq_first;
96static int irq_last;
Linus Walleijddba25f2012-02-03 11:19:05 +010097static u32 *irq_count;
98static int num_irqs;
Mattias Wallin0b337e72010-11-19 17:55:11 +010099
Linus Walleijddba25f2012-02-03 11:19:05 +0100100static struct device_attribute **dev_attr;
101static char **event_name;
Lee Jones4b8ac082013-01-14 16:10:36 +0000102
Mattias Wallin5814fc32010-09-13 16:05:04 +0200103/**
104 * struct ab8500_reg_range
105 * @first: the first address of the range
106 * @last: the last address of the range
107 * @perm: access permissions for the range
108 */
109struct ab8500_reg_range {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100110 u8 first;
111 u8 last;
112 u8 perm;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200113};
114
115/**
Lee Jones822672a2012-06-20 13:56:38 +0100116 * struct ab8500_prcmu_ranges
Mattias Wallin5814fc32010-09-13 16:05:04 +0200117 * @num_ranges: the number of ranges in the list
118 * @bankid: bank identifier
119 * @range: the list of register ranges
120 */
Lee Jones822672a2012-06-20 13:56:38 +0100121struct ab8500_prcmu_ranges {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100122 u8 num_ranges;
123 u8 bankid;
124 const struct ab8500_reg_range *range;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200125};
126
carriere etienne0fbce762011-04-08 16:26:36 +0200127/* hwreg- "mask" and "shift" entries ressources */
128struct hwreg_cfg {
129 u32 bank; /* target bank */
130 u32 addr; /* target address */
131 uint fmt; /* format */
132 uint mask; /* read/write mask, applied before any bit shift */
133 int shift; /* bit shift (read:right shift, write:left shift */
134};
135/* fmt bit #0: 0=hexa, 1=dec */
136#define REG_FMT_DEC(c) ((c)->fmt & 0x1)
137#define REG_FMT_HEX(c) (!REG_FMT_DEC(c))
138
139static struct hwreg_cfg hwreg_cfg = {
140 .addr = 0, /* default: invalid phys addr */
141 .fmt = 0, /* default: 32bit access, hex output */
142 .mask = 0xFFFFFFFF, /* default: no mask */
143 .shift = 0, /* default: no bit shift */
144};
145
Mattias Wallin5814fc32010-09-13 16:05:04 +0200146#define AB8500_NAME_STRING "ab8500"
John Beckett1478a312011-05-31 13:54:27 +0100147#define AB8500_ADC_NAME_STRING "gpadc"
Philippe Langlais40c064e2011-10-17 09:48:55 +0200148#define AB8500_NUM_BANKS 24
Mattias Wallin5814fc32010-09-13 16:05:04 +0200149
150#define AB8500_REV_REG 0x80
151
Lee Jones822672a2012-06-20 13:56:38 +0100152static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100153 [0x0] = {
154 .num_ranges = 0,
Lee Jonesfad55a82013-01-14 17:17:34 +0000155 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100156 },
157 [AB8500_SYS_CTRL1_BLOCK] = {
158 .num_ranges = 3,
159 .range = (struct ab8500_reg_range[]) {
160 {
161 .first = 0x00,
162 .last = 0x02,
163 },
164 {
165 .first = 0x42,
166 .last = 0x42,
167 },
168 {
169 .first = 0x80,
170 .last = 0x81,
171 },
172 },
173 },
174 [AB8500_SYS_CTRL2_BLOCK] = {
175 .num_ranges = 4,
176 .range = (struct ab8500_reg_range[]) {
177 {
178 .first = 0x00,
179 .last = 0x0D,
180 },
181 {
182 .first = 0x0F,
183 .last = 0x17,
184 },
185 {
186 .first = 0x30,
187 .last = 0x30,
188 },
189 {
190 .first = 0x32,
191 .last = 0x33,
192 },
193 },
194 },
195 [AB8500_REGU_CTRL1] = {
196 .num_ranges = 3,
197 .range = (struct ab8500_reg_range[]) {
198 {
199 .first = 0x00,
200 .last = 0x00,
201 },
202 {
203 .first = 0x03,
204 .last = 0x10,
205 },
206 {
207 .first = 0x80,
208 .last = 0x84,
209 },
210 },
211 },
212 [AB8500_REGU_CTRL2] = {
213 .num_ranges = 5,
214 .range = (struct ab8500_reg_range[]) {
215 {
216 .first = 0x00,
217 .last = 0x15,
218 },
219 {
220 .first = 0x17,
221 .last = 0x19,
222 },
223 {
224 .first = 0x1B,
225 .last = 0x1D,
226 },
227 {
228 .first = 0x1F,
229 .last = 0x22,
230 },
231 {
232 .first = 0x40,
233 .last = 0x44,
234 },
235 /* 0x80-0x8B is SIM registers and should
236 * not be accessed from here */
237 },
238 },
239 [AB8500_USB] = {
240 .num_ranges = 2,
241 .range = (struct ab8500_reg_range[]) {
242 {
243 .first = 0x80,
244 .last = 0x83,
245 },
246 {
247 .first = 0x87,
248 .last = 0x8A,
249 },
250 },
251 },
252 [AB8500_TVOUT] = {
253 .num_ranges = 9,
254 .range = (struct ab8500_reg_range[]) {
255 {
256 .first = 0x00,
257 .last = 0x12,
258 },
259 {
260 .first = 0x15,
261 .last = 0x17,
262 },
263 {
264 .first = 0x19,
265 .last = 0x21,
266 },
267 {
268 .first = 0x27,
269 .last = 0x2C,
270 },
271 {
272 .first = 0x41,
273 .last = 0x41,
274 },
275 {
276 .first = 0x45,
277 .last = 0x5B,
278 },
279 {
280 .first = 0x5D,
281 .last = 0x5D,
282 },
283 {
284 .first = 0x69,
285 .last = 0x69,
286 },
287 {
288 .first = 0x80,
289 .last = 0x81,
290 },
291 },
292 },
293 [AB8500_DBI] = {
294 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000295 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100296 },
297 [AB8500_ECI_AV_ACC] = {
298 .num_ranges = 1,
299 .range = (struct ab8500_reg_range[]) {
300 {
301 .first = 0x80,
302 .last = 0x82,
303 },
304 },
305 },
306 [0x9] = {
307 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000308 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100309 },
310 [AB8500_GPADC] = {
311 .num_ranges = 1,
312 .range = (struct ab8500_reg_range[]) {
313 {
314 .first = 0x00,
315 .last = 0x08,
316 },
317 },
318 },
319 [AB8500_CHARGER] = {
Philippe Langlais40c064e2011-10-17 09:48:55 +0200320 .num_ranges = 9,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100321 .range = (struct ab8500_reg_range[]) {
322 {
323 .first = 0x00,
324 .last = 0x03,
325 },
326 {
327 .first = 0x05,
328 .last = 0x05,
329 },
330 {
331 .first = 0x40,
332 .last = 0x40,
333 },
334 {
335 .first = 0x42,
336 .last = 0x42,
337 },
338 {
339 .first = 0x44,
340 .last = 0x44,
341 },
342 {
343 .first = 0x50,
344 .last = 0x55,
345 },
346 {
347 .first = 0x80,
348 .last = 0x82,
349 },
350 {
351 .first = 0xC0,
352 .last = 0xC2,
353 },
Philippe Langlais40c064e2011-10-17 09:48:55 +0200354 {
355 .first = 0xf5,
356 .last = 0xf6,
357 },
Mattias Wallind7b9f322010-11-26 13:06:39 +0100358 },
359 },
360 [AB8500_GAS_GAUGE] = {
361 .num_ranges = 3,
362 .range = (struct ab8500_reg_range[]) {
363 {
364 .first = 0x00,
365 .last = 0x00,
366 },
367 {
368 .first = 0x07,
369 .last = 0x0A,
370 },
371 {
372 .first = 0x10,
373 .last = 0x14,
374 },
375 },
376 },
Philippe Langlais40c064e2011-10-17 09:48:55 +0200377 [AB8500_DEVELOPMENT] = {
378 .num_ranges = 1,
379 .range = (struct ab8500_reg_range[]) {
380 {
381 .first = 0x00,
382 .last = 0x00,
383 },
384 },
385 },
386 [AB8500_DEBUG] = {
387 .num_ranges = 1,
388 .range = (struct ab8500_reg_range[]) {
389 {
390 .first = 0x05,
391 .last = 0x07,
392 },
393 },
394 },
Mattias Wallind7b9f322010-11-26 13:06:39 +0100395 [AB8500_AUDIO] = {
396 .num_ranges = 1,
397 .range = (struct ab8500_reg_range[]) {
398 {
399 .first = 0x00,
400 .last = 0x6F,
401 },
402 },
403 },
404 [AB8500_INTERRUPT] = {
405 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000406 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100407 },
408 [AB8500_RTC] = {
409 .num_ranges = 1,
410 .range = (struct ab8500_reg_range[]) {
411 {
412 .first = 0x00,
413 .last = 0x0F,
414 },
415 },
416 },
417 [AB8500_MISC] = {
418 .num_ranges = 8,
419 .range = (struct ab8500_reg_range[]) {
420 {
421 .first = 0x00,
422 .last = 0x05,
423 },
424 {
425 .first = 0x10,
426 .last = 0x15,
427 },
428 {
429 .first = 0x20,
430 .last = 0x25,
431 },
432 {
433 .first = 0x30,
434 .last = 0x35,
435 },
436 {
437 .first = 0x40,
438 .last = 0x45,
439 },
440 {
441 .first = 0x50,
442 .last = 0x50,
443 },
444 {
445 .first = 0x60,
446 .last = 0x67,
447 },
448 {
449 .first = 0x80,
450 .last = 0x80,
451 },
452 },
453 },
454 [0x11] = {
455 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000456 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100457 },
458 [0x12] = {
459 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000460 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100461 },
462 [0x13] = {
463 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000464 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100465 },
466 [0x14] = {
467 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000468 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100469 },
470 [AB8500_OTP_EMUL] = {
471 .num_ranges = 1,
472 .range = (struct ab8500_reg_range[]) {
473 {
474 .first = 0x01,
475 .last = 0x0F,
476 },
477 },
478 },
Mattias Wallin5814fc32010-09-13 16:05:04 +0200479};
480
Lee Jones4b8ac082013-01-14 16:10:36 +0000481static irqreturn_t ab8500_debug_handler(int irq, void *data)
482{
483 char buf[16];
484 struct kobject *kobj = (struct kobject *)data;
Mattias Wallin0b337e72010-11-19 17:55:11 +0100485 unsigned int irq_abb = irq - irq_first;
Lee Jones4b8ac082013-01-14 16:10:36 +0000486
Linus Walleijddba25f2012-02-03 11:19:05 +0100487 if (irq_abb < num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +0100488 irq_count[irq_abb]++;
Lee Jones4b8ac082013-01-14 16:10:36 +0000489 /*
490 * This makes it possible to use poll for events (POLLPRI | POLLERR)
Mattias Wallin0b337e72010-11-19 17:55:11 +0100491 * from userspace on sysfs file named <irq-nr>
Lee Jones4b8ac082013-01-14 16:10:36 +0000492 */
Mattias Wallin0b337e72010-11-19 17:55:11 +0100493 sprintf(buf, "%d", irq);
Lee Jones4b8ac082013-01-14 16:10:36 +0000494 sysfs_notify(kobj, NULL, buf);
495
496 return IRQ_HANDLED;
497}
498
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100499/* Prints to seq_file or log_buf */
500static int ab8500_registers_print(struct device *dev, u32 bank,
501 struct seq_file *s)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200502{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100503 unsigned int i;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200504
Mattias Wallind7b9f322010-11-26 13:06:39 +0100505 for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
506 u32 reg;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200507
Mattias Wallind7b9f322010-11-26 13:06:39 +0100508 for (reg = debug_ranges[bank].range[i].first;
509 reg <= debug_ranges[bank].range[i].last;
510 reg++) {
511 u8 value;
512 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200513
Mattias Wallind7b9f322010-11-26 13:06:39 +0100514 err = abx500_get_register_interruptible(dev,
515 (u8)bank, (u8)reg, &value);
516 if (err < 0) {
517 dev_err(dev, "ab->read fail %d\n", err);
518 return err;
519 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200520
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100521 if (s) {
522 err = seq_printf(s, " [%u/0x%02X]: 0x%02X\n",
523 bank, reg, value);
524 if (err < 0) {
525 dev_err(dev,
526 "seq_printf overflow bank=%d reg=%d\n",
527 bank, reg);
528 /* Error is not returned here since
529 * the output is wanted in any case */
530 return 0;
531 }
532 } else {
533 printk(KERN_INFO" [%u/0x%02X]: 0x%02X\n", bank,
534 reg, value);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100535 }
536 }
537 }
538 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200539}
540
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100541static int ab8500_print_bank_registers(struct seq_file *s, void *p)
542{
543 struct device *dev = s->private;
544 u32 bank = debug_bank;
545
546 seq_printf(s, AB8500_NAME_STRING " register values:\n");
547
548 seq_printf(s, " bank %u:\n", bank);
549
550 ab8500_registers_print(dev, bank, s);
551 return 0;
552}
553
Mattias Wallin5814fc32010-09-13 16:05:04 +0200554static int ab8500_registers_open(struct inode *inode, struct file *file)
555{
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100556 return single_open(file, ab8500_print_bank_registers, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200557}
558
559static const struct file_operations ab8500_registers_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100560 .open = ab8500_registers_open,
561 .read = seq_read,
562 .llseek = seq_lseek,
563 .release = single_release,
564 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +0200565};
566
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100567static int ab8500_print_all_banks(struct seq_file *s, void *p)
568{
569 struct device *dev = s->private;
570 unsigned int i;
571 int err;
572
573 seq_printf(s, AB8500_NAME_STRING " register values:\n");
574
575 for (i = 1; i < AB8500_NUM_BANKS; i++) {
576 err = seq_printf(s, " bank %u:\n", i);
577 if (err < 0)
578 dev_err(dev, "seq_printf overflow, bank=%d\n", i);
579
580 ab8500_registers_print(dev, i, s);
581 }
582 return 0;
583}
584
Mian Yousaf Kaukab1d843a62012-01-27 11:35:41 +0100585/* Dump registers to kernel log */
586void ab8500_dump_all_banks(struct device *dev)
587{
588 unsigned int i;
589
590 printk(KERN_INFO"ab8500 register values:\n");
591
592 for (i = 1; i < AB8500_NUM_BANKS; i++) {
593 printk(KERN_INFO" bank %u:\n", i);
594 ab8500_registers_print(dev, i, NULL);
595 }
596}
597
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100598static int ab8500_all_banks_open(struct inode *inode, struct file *file)
599{
600 struct seq_file *s;
601 int err;
602
603 err = single_open(file, ab8500_print_all_banks, inode->i_private);
604 if (!err) {
605 /* Default buf size in seq_read is not enough */
606 s = (struct seq_file *)file->private_data;
607 s->size = (PAGE_SIZE * 2);
608 s->buf = kmalloc(s->size, GFP_KERNEL);
609 if (!s->buf) {
610 single_release(inode, file);
611 err = -ENOMEM;
612 }
613 }
614 return err;
615}
616
617static const struct file_operations ab8500_all_banks_fops = {
618 .open = ab8500_all_banks_open,
619 .read = seq_read,
620 .llseek = seq_lseek,
621 .release = single_release,
622 .owner = THIS_MODULE,
623};
624
Mattias Wallin5814fc32010-09-13 16:05:04 +0200625static int ab8500_bank_print(struct seq_file *s, void *p)
626{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100627 return seq_printf(s, "%d\n", debug_bank);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200628}
629
630static int ab8500_bank_open(struct inode *inode, struct file *file)
631{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100632 return single_open(file, ab8500_bank_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200633}
634
635static ssize_t ab8500_bank_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100636 const char __user *user_buf,
637 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200638{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100639 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +0100640 unsigned long user_bank;
641 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200642
Mattias Wallind7b9f322010-11-26 13:06:39 +0100643 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +0200644 err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100645 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +0200646 return err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200647
Mattias Wallind7b9f322010-11-26 13:06:39 +0100648 if (user_bank >= AB8500_NUM_BANKS) {
649 dev_err(dev, "debugfs error input > number of banks\n");
650 return -EINVAL;
651 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200652
Mattias Wallind7b9f322010-11-26 13:06:39 +0100653 debug_bank = user_bank;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200654
Peter Huewe8504d632011-06-06 22:43:32 +0200655 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200656}
657
658static int ab8500_address_print(struct seq_file *s, void *p)
659{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100660 return seq_printf(s, "0x%02X\n", debug_address);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200661}
662
663static int ab8500_address_open(struct inode *inode, struct file *file)
664{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100665 return single_open(file, ab8500_address_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200666}
667
668static ssize_t ab8500_address_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100669 const char __user *user_buf,
670 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200671{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100672 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +0100673 unsigned long user_address;
674 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200675
Mattias Wallind7b9f322010-11-26 13:06:39 +0100676 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +0200677 err = kstrtoul_from_user(user_buf, count, 0, &user_address);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100678 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +0200679 return err;
680
Mattias Wallind7b9f322010-11-26 13:06:39 +0100681 if (user_address > 0xff) {
682 dev_err(dev, "debugfs error input > 0xff\n");
683 return -EINVAL;
684 }
685 debug_address = user_address;
Peter Huewe8504d632011-06-06 22:43:32 +0200686 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200687}
688
689static int ab8500_val_print(struct seq_file *s, void *p)
690{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100691 struct device *dev = s->private;
692 int ret;
693 u8 regvalue;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200694
Mattias Wallind7b9f322010-11-26 13:06:39 +0100695 ret = abx500_get_register_interruptible(dev,
696 (u8)debug_bank, (u8)debug_address, &regvalue);
697 if (ret < 0) {
698 dev_err(dev, "abx500_get_reg fail %d, %d\n",
699 ret, __LINE__);
700 return -EINVAL;
701 }
702 seq_printf(s, "0x%02X\n", regvalue);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200703
Mattias Wallind7b9f322010-11-26 13:06:39 +0100704 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200705}
706
707static int ab8500_val_open(struct inode *inode, struct file *file)
708{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100709 return single_open(file, ab8500_val_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200710}
711
712static ssize_t ab8500_val_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100713 const char __user *user_buf,
714 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200715{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100716 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +0100717 unsigned long user_val;
718 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200719
Mattias Wallind7b9f322010-11-26 13:06:39 +0100720 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +0200721 err = kstrtoul_from_user(user_buf, count, 0, &user_val);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100722 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +0200723 return err;
724
Mattias Wallind7b9f322010-11-26 13:06:39 +0100725 if (user_val > 0xff) {
726 dev_err(dev, "debugfs error input > 0xff\n");
727 return -EINVAL;
728 }
729 err = abx500_set_register_interruptible(dev,
730 (u8)debug_bank, debug_address, (u8)user_val);
731 if (err < 0) {
732 printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
733 return -EINVAL;
734 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200735
Peter Huewe8504d632011-06-06 22:43:32 +0200736 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200737}
738
carriere etienne0fbce762011-04-08 16:26:36 +0200739/*
Bengt Jonsson8f0eb432012-02-14 13:01:00 +0100740 * Interrupt status
741 */
742static u32 num_interrupts[AB8500_MAX_NR_IRQS];
743static int num_interrupt_lines;
744
745void ab8500_debug_register_interrupt(int line)
746{
747 if (line < num_interrupt_lines)
748 num_interrupts[line]++;
749}
750
751static int ab8500_interrupts_print(struct seq_file *s, void *p)
752{
753 int line;
754
755 seq_printf(s, "irq: number of\n");
756
757 for (line = 0; line < num_interrupt_lines; line++)
758 seq_printf(s, "%3i: %6i\n", line, num_interrupts[line]);
759
760 return 0;
761}
762
763static int ab8500_interrupts_open(struct inode *inode, struct file *file)
764{
765 return single_open(file, ab8500_interrupts_print, inode->i_private);
766}
767
768/*
carriere etienne0fbce762011-04-08 16:26:36 +0200769 * - HWREG DB8500 formated routines
770 */
771static int ab8500_hwreg_print(struct seq_file *s, void *d)
772{
773 struct device *dev = s->private;
774 int ret;
775 u8 regvalue;
776
777 ret = abx500_get_register_interruptible(dev,
778 (u8)hwreg_cfg.bank, (u8)hwreg_cfg.addr, &regvalue);
779 if (ret < 0) {
780 dev_err(dev, "abx500_get_reg fail %d, %d\n",
781 ret, __LINE__);
782 return -EINVAL;
783 }
784
785 if (hwreg_cfg.shift >= 0)
786 regvalue >>= hwreg_cfg.shift;
787 else
788 regvalue <<= -hwreg_cfg.shift;
789 regvalue &= hwreg_cfg.mask;
790
791 if (REG_FMT_DEC(&hwreg_cfg))
792 seq_printf(s, "%d\n", regvalue);
793 else
794 seq_printf(s, "0x%02X\n", regvalue);
795 return 0;
796}
797
798static int ab8500_hwreg_open(struct inode *inode, struct file *file)
799{
800 return single_open(file, ab8500_hwreg_print, inode->i_private);
801}
802
John Beckett1478a312011-05-31 13:54:27 +0100803static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
804{
805 int bat_ctrl_raw;
806 int bat_ctrl_convert;
807 struct ab8500_gpadc *gpadc;
808
Philippe Langlais8908c042012-04-18 15:52:59 +0200809 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +0100810 bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL);
811 bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc,
812 BAT_CTRL, bat_ctrl_raw);
813
814 return seq_printf(s, "%d,0x%X\n",
815 bat_ctrl_convert, bat_ctrl_raw);
816}
817
818static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
819{
820 return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private);
821}
822
823static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
824 .open = ab8500_gpadc_bat_ctrl_open,
825 .read = seq_read,
826 .llseek = seq_lseek,
827 .release = single_release,
828 .owner = THIS_MODULE,
829};
830
831static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
832{
833 int btemp_ball_raw;
834 int btemp_ball_convert;
835 struct ab8500_gpadc *gpadc;
836
Philippe Langlais8908c042012-04-18 15:52:59 +0200837 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +0100838 btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL);
839 btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
840 btemp_ball_raw);
841
842 return seq_printf(s,
843 "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw);
844}
845
846static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
847 struct file *file)
848{
849 return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private);
850}
851
852static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
853 .open = ab8500_gpadc_btemp_ball_open,
854 .read = seq_read,
855 .llseek = seq_lseek,
856 .release = single_release,
857 .owner = THIS_MODULE,
858};
859
860static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p)
861{
862 int main_charger_v_raw;
863 int main_charger_v_convert;
864 struct ab8500_gpadc *gpadc;
865
Philippe Langlais8908c042012-04-18 15:52:59 +0200866 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +0100867 main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V);
868 main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
869 MAIN_CHARGER_V, main_charger_v_raw);
870
871 return seq_printf(s, "%d,0x%X\n",
872 main_charger_v_convert, main_charger_v_raw);
873}
874
875static int ab8500_gpadc_main_charger_v_open(struct inode *inode,
876 struct file *file)
877{
878 return single_open(file, ab8500_gpadc_main_charger_v_print,
879 inode->i_private);
880}
881
882static const struct file_operations ab8500_gpadc_main_charger_v_fops = {
883 .open = ab8500_gpadc_main_charger_v_open,
884 .read = seq_read,
885 .llseek = seq_lseek,
886 .release = single_release,
887 .owner = THIS_MODULE,
888};
889
890static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p)
891{
892 int acc_detect1_raw;
893 int acc_detect1_convert;
894 struct ab8500_gpadc *gpadc;
895
Philippe Langlais8908c042012-04-18 15:52:59 +0200896 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +0100897 acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1);
898 acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1,
899 acc_detect1_raw);
900
901 return seq_printf(s, "%d,0x%X\n",
902 acc_detect1_convert, acc_detect1_raw);
903}
904
905static int ab8500_gpadc_acc_detect1_open(struct inode *inode,
906 struct file *file)
907{
908 return single_open(file, ab8500_gpadc_acc_detect1_print,
909 inode->i_private);
910}
911
912static const struct file_operations ab8500_gpadc_acc_detect1_fops = {
913 .open = ab8500_gpadc_acc_detect1_open,
914 .read = seq_read,
915 .llseek = seq_lseek,
916 .release = single_release,
917 .owner = THIS_MODULE,
918};
919
920static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p)
921{
922 int acc_detect2_raw;
923 int acc_detect2_convert;
924 struct ab8500_gpadc *gpadc;
925
Philippe Langlais8908c042012-04-18 15:52:59 +0200926 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +0100927 acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2);
928 acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc,
929 ACC_DETECT2, acc_detect2_raw);
930
931 return seq_printf(s, "%d,0x%X\n",
932 acc_detect2_convert, acc_detect2_raw);
933}
934
935static int ab8500_gpadc_acc_detect2_open(struct inode *inode,
936 struct file *file)
937{
938 return single_open(file, ab8500_gpadc_acc_detect2_print,
939 inode->i_private);
940}
941
942static const struct file_operations ab8500_gpadc_acc_detect2_fops = {
943 .open = ab8500_gpadc_acc_detect2_open,
944 .read = seq_read,
945 .llseek = seq_lseek,
946 .release = single_release,
947 .owner = THIS_MODULE,
948};
949
950static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p)
951{
952 int aux1_raw;
953 int aux1_convert;
954 struct ab8500_gpadc *gpadc;
955
Philippe Langlais8908c042012-04-18 15:52:59 +0200956 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +0100957 aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1);
958 aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1,
959 aux1_raw);
960
961 return seq_printf(s, "%d,0x%X\n",
962 aux1_convert, aux1_raw);
963}
964
965static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file)
966{
967 return single_open(file, ab8500_gpadc_aux1_print, inode->i_private);
968}
969
970static const struct file_operations ab8500_gpadc_aux1_fops = {
971 .open = ab8500_gpadc_aux1_open,
972 .read = seq_read,
973 .llseek = seq_lseek,
974 .release = single_release,
975 .owner = THIS_MODULE,
976};
977
978static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p)
979{
980 int aux2_raw;
981 int aux2_convert;
982 struct ab8500_gpadc *gpadc;
983
Philippe Langlais8908c042012-04-18 15:52:59 +0200984 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +0100985 aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2);
986 aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2,
987 aux2_raw);
988
989 return seq_printf(s, "%d,0x%X\n",
990 aux2_convert, aux2_raw);
991}
992
993static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file)
994{
995 return single_open(file, ab8500_gpadc_aux2_print, inode->i_private);
996}
997
998static const struct file_operations ab8500_gpadc_aux2_fops = {
999 .open = ab8500_gpadc_aux2_open,
1000 .read = seq_read,
1001 .llseek = seq_lseek,
1002 .release = single_release,
1003 .owner = THIS_MODULE,
1004};
1005
1006static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
1007{
1008 int main_bat_v_raw;
1009 int main_bat_v_convert;
1010 struct ab8500_gpadc *gpadc;
1011
Philippe Langlais8908c042012-04-18 15:52:59 +02001012 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +01001013 main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V);
1014 main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
1015 main_bat_v_raw);
1016
1017 return seq_printf(s, "%d,0x%X\n",
1018 main_bat_v_convert, main_bat_v_raw);
1019}
1020
1021static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
1022 struct file *file)
1023{
1024 return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private);
1025}
1026
1027static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
1028 .open = ab8500_gpadc_main_bat_v_open,
1029 .read = seq_read,
1030 .llseek = seq_lseek,
1031 .release = single_release,
1032 .owner = THIS_MODULE,
1033};
1034
1035static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p)
1036{
1037 int vbus_v_raw;
1038 int vbus_v_convert;
1039 struct ab8500_gpadc *gpadc;
1040
Philippe Langlais8908c042012-04-18 15:52:59 +02001041 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +01001042 vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V);
1043 vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V,
1044 vbus_v_raw);
1045
1046 return seq_printf(s, "%d,0x%X\n",
1047 vbus_v_convert, vbus_v_raw);
1048}
1049
1050static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file)
1051{
1052 return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private);
1053}
1054
1055static const struct file_operations ab8500_gpadc_vbus_v_fops = {
1056 .open = ab8500_gpadc_vbus_v_open,
1057 .read = seq_read,
1058 .llseek = seq_lseek,
1059 .release = single_release,
1060 .owner = THIS_MODULE,
1061};
1062
1063static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p)
1064{
1065 int main_charger_c_raw;
1066 int main_charger_c_convert;
1067 struct ab8500_gpadc *gpadc;
1068
Philippe Langlais8908c042012-04-18 15:52:59 +02001069 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +01001070 main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C);
1071 main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
1072 MAIN_CHARGER_C, main_charger_c_raw);
1073
1074 return seq_printf(s, "%d,0x%X\n",
1075 main_charger_c_convert, main_charger_c_raw);
1076}
1077
1078static int ab8500_gpadc_main_charger_c_open(struct inode *inode,
1079 struct file *file)
1080{
1081 return single_open(file, ab8500_gpadc_main_charger_c_print,
1082 inode->i_private);
1083}
1084
1085static const struct file_operations ab8500_gpadc_main_charger_c_fops = {
1086 .open = ab8500_gpadc_main_charger_c_open,
1087 .read = seq_read,
1088 .llseek = seq_lseek,
1089 .release = single_release,
1090 .owner = THIS_MODULE,
1091};
1092
1093static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p)
1094{
1095 int usb_charger_c_raw;
1096 int usb_charger_c_convert;
1097 struct ab8500_gpadc *gpadc;
1098
Philippe Langlais8908c042012-04-18 15:52:59 +02001099 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +01001100 usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C);
1101 usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
1102 USB_CHARGER_C, usb_charger_c_raw);
1103
1104 return seq_printf(s, "%d,0x%X\n",
1105 usb_charger_c_convert, usb_charger_c_raw);
1106}
1107
1108static int ab8500_gpadc_usb_charger_c_open(struct inode *inode,
1109 struct file *file)
1110{
1111 return single_open(file, ab8500_gpadc_usb_charger_c_print,
1112 inode->i_private);
1113}
1114
1115static const struct file_operations ab8500_gpadc_usb_charger_c_fops = {
1116 .open = ab8500_gpadc_usb_charger_c_open,
1117 .read = seq_read,
1118 .llseek = seq_lseek,
1119 .release = single_release,
1120 .owner = THIS_MODULE,
1121};
1122
1123static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
1124{
1125 int bk_bat_v_raw;
1126 int bk_bat_v_convert;
1127 struct ab8500_gpadc *gpadc;
1128
Philippe Langlais8908c042012-04-18 15:52:59 +02001129 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +01001130 bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V);
1131 bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
1132 BK_BAT_V, bk_bat_v_raw);
1133
1134 return seq_printf(s, "%d,0x%X\n",
1135 bk_bat_v_convert, bk_bat_v_raw);
1136}
1137
1138static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
1139{
1140 return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private);
1141}
1142
1143static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
1144 .open = ab8500_gpadc_bk_bat_v_open,
1145 .read = seq_read,
1146 .llseek = seq_lseek,
1147 .release = single_release,
1148 .owner = THIS_MODULE,
1149};
1150
1151static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
1152{
1153 int die_temp_raw;
1154 int die_temp_convert;
1155 struct ab8500_gpadc *gpadc;
1156
Philippe Langlais8908c042012-04-18 15:52:59 +02001157 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
John Beckett1478a312011-05-31 13:54:27 +01001158 die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP);
1159 die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP,
1160 die_temp_raw);
1161
1162 return seq_printf(s, "%d,0x%X\n",
1163 die_temp_convert, die_temp_raw);
1164}
1165
1166static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
1167{
1168 return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private);
1169}
1170
1171static const struct file_operations ab8500_gpadc_die_temp_fops = {
1172 .open = ab8500_gpadc_die_temp_open,
1173 .read = seq_read,
1174 .llseek = seq_lseek,
1175 .release = single_release,
1176 .owner = THIS_MODULE,
1177};
1178
carriere etienne0fbce762011-04-08 16:26:36 +02001179/*
1180 * return length of an ASCII numerical value, 0 is string is not a
1181 * numerical value.
1182 * string shall start at value 1st char.
1183 * string can be tailed with \0 or space or newline chars only.
1184 * value can be decimal or hexadecimal (prefixed 0x or 0X).
1185 */
1186static int strval_len(char *b)
1187{
1188 char *s = b;
1189 if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) {
1190 s += 2;
1191 for (; *s && (*s != ' ') && (*s != '\n'); s++) {
1192 if (!isxdigit(*s))
1193 return 0;
1194 }
1195 } else {
1196 if (*s == '-')
1197 s++;
1198 for (; *s && (*s != ' ') && (*s != '\n'); s++) {
1199 if (!isdigit(*s))
1200 return 0;
1201 }
1202 }
1203 return (int) (s-b);
1204}
1205
1206/*
1207 * parse hwreg input data.
1208 * update global hwreg_cfg only if input data syntax is ok.
1209 */
1210static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
1211 struct device *dev)
1212{
1213 uint write, val = 0;
1214 u8 regvalue;
1215 int ret;
1216 struct hwreg_cfg loc = {
1217 .bank = 0, /* default: invalid phys addr */
1218 .addr = 0, /* default: invalid phys addr */
1219 .fmt = 0, /* default: 32bit access, hex output */
1220 .mask = 0xFFFFFFFF, /* default: no mask */
1221 .shift = 0, /* default: no bit shift */
1222 };
1223
1224 /* read or write ? */
1225 if (!strncmp(b, "read ", 5)) {
1226 write = 0;
1227 b += 5;
1228 } else if (!strncmp(b, "write ", 6)) {
1229 write = 1;
1230 b += 6;
1231 } else
1232 return -EINVAL;
1233
1234 /* OPTIONS -l|-w|-b -s -m -o */
1235 while ((*b == ' ') || (*b == '-')) {
1236 if (*(b-1) != ' ') {
1237 b++;
1238 continue;
1239 }
1240 if ((!strncmp(b, "-d ", 3)) ||
1241 (!strncmp(b, "-dec ", 5))) {
1242 b += (*(b+2) == ' ') ? 3 : 5;
1243 loc.fmt |= (1<<0);
1244 } else if ((!strncmp(b, "-h ", 3)) ||
1245 (!strncmp(b, "-hex ", 5))) {
1246 b += (*(b+2) == ' ') ? 3 : 5;
1247 loc.fmt &= ~(1<<0);
1248 } else if ((!strncmp(b, "-m ", 3)) ||
1249 (!strncmp(b, "-mask ", 6))) {
1250 b += (*(b+2) == ' ') ? 3 : 6;
1251 if (strval_len(b) == 0)
1252 return -EINVAL;
1253 loc.mask = simple_strtoul(b, &b, 0);
1254 } else if ((!strncmp(b, "-s ", 3)) ||
1255 (!strncmp(b, "-shift ", 7))) {
1256 b += (*(b+2) == ' ') ? 3 : 7;
1257 if (strval_len(b) == 0)
1258 return -EINVAL;
1259 loc.shift = simple_strtol(b, &b, 0);
1260 } else {
1261 return -EINVAL;
1262 }
1263 }
1264 /* get arg BANK and ADDRESS */
1265 if (strval_len(b) == 0)
1266 return -EINVAL;
1267 loc.bank = simple_strtoul(b, &b, 0);
1268 while (*b == ' ')
1269 b++;
1270 if (strval_len(b) == 0)
1271 return -EINVAL;
1272 loc.addr = simple_strtoul(b, &b, 0);
1273
1274 if (write) {
1275 while (*b == ' ')
1276 b++;
1277 if (strval_len(b) == 0)
1278 return -EINVAL;
1279 val = simple_strtoul(b, &b, 0);
1280 }
1281
1282 /* args are ok, update target cfg (mainly for read) */
1283 *cfg = loc;
1284
1285#ifdef ABB_HWREG_DEBUG
1286 pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d"
1287 "value=0x%X\n", (write) ? "write" : "read",
1288 REG_FMT_DEC(cfg) ? "decimal" : "hexa",
1289 cfg->addr, cfg->mask, cfg->shift, val);
1290#endif
1291
1292 if (!write)
1293 return 0;
1294
1295 ret = abx500_get_register_interruptible(dev,
1296 (u8)cfg->bank, (u8)cfg->addr, &regvalue);
1297 if (ret < 0) {
1298 dev_err(dev, "abx500_get_reg fail %d, %d\n",
1299 ret, __LINE__);
1300 return -EINVAL;
1301 }
1302
1303 if (cfg->shift >= 0) {
1304 regvalue &= ~(cfg->mask << (cfg->shift));
1305 val = (val & cfg->mask) << (cfg->shift);
1306 } else {
1307 regvalue &= ~(cfg->mask >> (-cfg->shift));
1308 val = (val & cfg->mask) >> (-cfg->shift);
1309 }
1310 val = val | regvalue;
1311
1312 ret = abx500_set_register_interruptible(dev,
1313 (u8)cfg->bank, (u8)cfg->addr, (u8)val);
1314 if (ret < 0) {
1315 pr_err("abx500_set_reg failed %d, %d", ret, __LINE__);
1316 return -EINVAL;
1317 }
1318
1319 return 0;
1320}
1321
1322static ssize_t ab8500_hwreg_write(struct file *file,
1323 const char __user *user_buf, size_t count, loff_t *ppos)
1324{
1325 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1326 char buf[128];
1327 int buf_size, ret;
1328
1329 /* Get userspace string and assure termination */
1330 buf_size = min(count, (sizeof(buf)-1));
1331 if (copy_from_user(buf, user_buf, buf_size))
1332 return -EFAULT;
1333 buf[buf_size] = 0;
1334
1335 /* get args and process */
1336 ret = hwreg_common_write(buf, &hwreg_cfg, dev);
1337 return (ret) ? ret : buf_size;
1338}
1339
1340/*
1341 * - irq subscribe/unsubscribe stuff
1342 */
Lee Jones4b8ac082013-01-14 16:10:36 +00001343static int ab8500_subscribe_unsubscribe_print(struct seq_file *s, void *p)
1344{
1345 seq_printf(s, "%d\n", irq_first);
1346
1347 return 0;
1348}
1349
1350static int ab8500_subscribe_unsubscribe_open(struct inode *inode,
1351 struct file *file)
1352{
1353 return single_open(file, ab8500_subscribe_unsubscribe_print,
1354 inode->i_private);
1355}
1356
1357/*
Mattias Wallin0b337e72010-11-19 17:55:11 +01001358 * Userspace should use poll() on this file. When an event occur
Lee Jones4b8ac082013-01-14 16:10:36 +00001359 * the blocking poll will be released.
1360 */
1361static ssize_t show_irq(struct device *dev,
1362 struct device_attribute *attr, char *buf)
1363{
Mattias Wallin0b337e72010-11-19 17:55:11 +01001364 unsigned long name;
1365 unsigned int irq_index;
1366 int err;
Lee Jones4b8ac082013-01-14 16:10:36 +00001367
Mattias Wallin0b337e72010-11-19 17:55:11 +01001368 err = strict_strtoul(attr->attr.name, 0, &name);
1369 if (err)
1370 return err;
1371
1372 irq_index = name - irq_first;
Linus Walleijddba25f2012-02-03 11:19:05 +01001373 if (irq_index >= num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +01001374 return -EINVAL;
1375 else
1376 return sprintf(buf, "%u\n", irq_count[irq_index]);
1377}
Lee Jones4b8ac082013-01-14 16:10:36 +00001378
1379static ssize_t ab8500_subscribe_write(struct file *file,
1380 const char __user *user_buf,
1381 size_t count, loff_t *ppos)
1382{
1383 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1384 char buf[32];
1385 int buf_size;
1386 unsigned long user_val;
1387 int err;
Mattias Wallin0b337e72010-11-19 17:55:11 +01001388 unsigned int irq_index;
Lee Jones4b8ac082013-01-14 16:10:36 +00001389
1390 /* Get userspace string and assure termination */
1391 buf_size = min(count, (sizeof(buf)-1));
1392 if (copy_from_user(buf, user_buf, buf_size))
1393 return -EFAULT;
1394 buf[buf_size] = 0;
1395
1396 err = strict_strtoul(buf, 0, &user_val);
1397 if (err)
1398 return -EINVAL;
1399 if (user_val < irq_first) {
1400 dev_err(dev, "debugfs error input < %d\n", irq_first);
1401 return -EINVAL;
1402 }
1403 if (user_val > irq_last) {
1404 dev_err(dev, "debugfs error input > %d\n", irq_last);
1405 return -EINVAL;
1406 }
1407
Mattias Wallin0b337e72010-11-19 17:55:11 +01001408 irq_index = user_val - irq_first;
Linus Walleijddba25f2012-02-03 11:19:05 +01001409 if (irq_index >= num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +01001410 return -EINVAL;
1411
Lee Jones4b8ac082013-01-14 16:10:36 +00001412 /*
Mattias Wallin0b337e72010-11-19 17:55:11 +01001413 * This will create a sysfs file named <irq-nr> which userspace can
Lee Jones4b8ac082013-01-14 16:10:36 +00001414 * use to select or poll and get the AB8500 events
1415 */
Mattias Wallin0b337e72010-11-19 17:55:11 +01001416 dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute),
1417 GFP_KERNEL);
1418 event_name[irq_index] = kmalloc(buf_size, GFP_KERNEL);
1419 sprintf(event_name[irq_index], "%lu", user_val);
1420 dev_attr[irq_index]->show = show_irq;
1421 dev_attr[irq_index]->store = NULL;
1422 dev_attr[irq_index]->attr.name = event_name[irq_index];
1423 dev_attr[irq_index]->attr.mode = S_IRUGO;
1424 err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr);
Lee Jones4b8ac082013-01-14 16:10:36 +00001425 if (err < 0) {
1426 printk(KERN_ERR "sysfs_create_file failed %d\n", err);
1427 return err;
1428 }
1429
1430 err = request_threaded_irq(user_val, NULL, ab8500_debug_handler,
1431 IRQF_SHARED | IRQF_NO_SUSPEND,
1432 "ab8500-debug", &dev->kobj);
1433 if (err < 0) {
1434 printk(KERN_ERR "request_threaded_irq failed %d, %lu\n",
1435 err, user_val);
Mattias Wallin0b337e72010-11-19 17:55:11 +01001436 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
Lee Jones4b8ac082013-01-14 16:10:36 +00001437 return err;
1438 }
1439
1440 return buf_size;
1441}
1442
1443static ssize_t ab8500_unsubscribe_write(struct file *file,
1444 const char __user *user_buf,
1445 size_t count, loff_t *ppos)
1446{
1447 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1448 char buf[32];
1449 int buf_size;
1450 unsigned long user_val;
1451 int err;
Mattias Wallin0b337e72010-11-19 17:55:11 +01001452 unsigned int irq_index;
Lee Jones4b8ac082013-01-14 16:10:36 +00001453
1454 /* Get userspace string and assure termination */
1455 buf_size = min(count, (sizeof(buf)-1));
1456 if (copy_from_user(buf, user_buf, buf_size))
1457 return -EFAULT;
1458 buf[buf_size] = 0;
1459
1460 err = strict_strtoul(buf, 0, &user_val);
1461 if (err)
1462 return -EINVAL;
1463 if (user_val < irq_first) {
1464 dev_err(dev, "debugfs error input < %d\n", irq_first);
1465 return -EINVAL;
1466 }
1467 if (user_val > irq_last) {
1468 dev_err(dev, "debugfs error input > %d\n", irq_last);
1469 return -EINVAL;
1470 }
1471
Mattias Wallin0b337e72010-11-19 17:55:11 +01001472 irq_index = user_val - irq_first;
Linus Walleijddba25f2012-02-03 11:19:05 +01001473 if (irq_index >= num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +01001474 return -EINVAL;
Lee Jones4b8ac082013-01-14 16:10:36 +00001475
Mattias Wallin0b337e72010-11-19 17:55:11 +01001476 /* Set irq count to 0 when unsubscribe */
1477 irq_count[irq_index] = 0;
1478
1479 if (dev_attr[irq_index])
1480 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
1481
1482
1483 free_irq(user_val, &dev->kobj);
1484 kfree(event_name[irq_index]);
1485 kfree(dev_attr[irq_index]);
Lee Jones4b8ac082013-01-14 16:10:36 +00001486
1487 return buf_size;
1488}
1489
carriere etienne0fbce762011-04-08 16:26:36 +02001490/*
1491 * - several deubgfs nodes fops
1492 */
1493
Mattias Wallin5814fc32010-09-13 16:05:04 +02001494static const struct file_operations ab8500_bank_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001495 .open = ab8500_bank_open,
1496 .write = ab8500_bank_write,
1497 .read = seq_read,
1498 .llseek = seq_lseek,
1499 .release = single_release,
1500 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001501};
1502
1503static const struct file_operations ab8500_address_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001504 .open = ab8500_address_open,
1505 .write = ab8500_address_write,
1506 .read = seq_read,
1507 .llseek = seq_lseek,
1508 .release = single_release,
1509 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001510};
1511
1512static const struct file_operations ab8500_val_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001513 .open = ab8500_val_open,
1514 .write = ab8500_val_write,
1515 .read = seq_read,
1516 .llseek = seq_lseek,
1517 .release = single_release,
1518 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001519};
1520
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001521static const struct file_operations ab8500_interrupts_fops = {
1522 .open = ab8500_interrupts_open,
1523 .read = seq_read,
1524 .llseek = seq_lseek,
1525 .release = single_release,
1526 .owner = THIS_MODULE,
1527};
1528
Lee Jones4b8ac082013-01-14 16:10:36 +00001529static const struct file_operations ab8500_subscribe_fops = {
1530 .open = ab8500_subscribe_unsubscribe_open,
1531 .write = ab8500_subscribe_write,
1532 .read = seq_read,
1533 .llseek = seq_lseek,
1534 .release = single_release,
1535 .owner = THIS_MODULE,
1536};
1537
1538static const struct file_operations ab8500_unsubscribe_fops = {
1539 .open = ab8500_subscribe_unsubscribe_open,
1540 .write = ab8500_unsubscribe_write,
1541 .read = seq_read,
1542 .llseek = seq_lseek,
1543 .release = single_release,
1544 .owner = THIS_MODULE,
1545};
1546
carriere etienne0fbce762011-04-08 16:26:36 +02001547static const struct file_operations ab8500_hwreg_fops = {
1548 .open = ab8500_hwreg_open,
1549 .write = ab8500_hwreg_write,
1550 .read = seq_read,
1551 .llseek = seq_lseek,
1552 .release = single_release,
1553 .owner = THIS_MODULE,
1554};
1555
Mattias Wallin5814fc32010-09-13 16:05:04 +02001556static struct dentry *ab8500_dir;
John Beckett1478a312011-05-31 13:54:27 +01001557static struct dentry *ab8500_gpadc_dir;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001558
Bill Pembertonf791be42012-11-19 13:23:04 -05001559static int ab8500_debug_probe(struct platform_device *plf)
Mattias Wallin5814fc32010-09-13 16:05:04 +02001560{
carriere etienne0fbce762011-04-08 16:26:36 +02001561 struct dentry *file;
Linus Walleijddba25f2012-02-03 11:19:05 +01001562 int ret = -ENOMEM;
1563 struct ab8500 *ab8500;
Mattias Wallind7b9f322010-11-26 13:06:39 +01001564 debug_bank = AB8500_MISC;
1565 debug_address = AB8500_REV_REG & 0x00FF;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001566
Linus Walleijddba25f2012-02-03 11:19:05 +01001567 ab8500 = dev_get_drvdata(plf->dev.parent);
1568 num_irqs = ab8500->mask_size;
1569
Ashok G70bad042012-02-28 10:21:00 +05301570 irq_count = kzalloc(sizeof(*irq_count)*num_irqs, GFP_KERNEL);
Linus Walleijddba25f2012-02-03 11:19:05 +01001571 if (!irq_count)
1572 return -ENOMEM;
1573
1574 dev_attr = kzalloc(sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
1575 if (!dev_attr)
1576 goto out_freeirq_count;
1577
1578 event_name = kzalloc(sizeof(*event_name)*num_irqs, GFP_KERNEL);
1579 if (!event_name)
1580 goto out_freedev_attr;
1581
Lee Jones4b8ac082013-01-14 16:10:36 +00001582 irq_first = platform_get_irq_byname(plf, "IRQ_FIRST");
1583 if (irq_first < 0) {
1584 dev_err(&plf->dev, "First irq not found, err %d\n",
John Beckett1478a312011-05-31 13:54:27 +01001585 irq_first);
Linus Walleijddba25f2012-02-03 11:19:05 +01001586 ret = irq_first;
1587 goto out_freeevent_name;
Lee Jones4b8ac082013-01-14 16:10:36 +00001588 }
1589
1590 irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
1591 if (irq_last < 0) {
1592 dev_err(&plf->dev, "Last irq not found, err %d\n",
John Beckett1478a312011-05-31 13:54:27 +01001593 irq_last);
Linus Walleijddba25f2012-02-03 11:19:05 +01001594 ret = irq_last;
1595 goto out_freeevent_name;
Lee Jones4b8ac082013-01-14 16:10:36 +00001596 }
1597
Mattias Wallind7b9f322010-11-26 13:06:39 +01001598 ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
1599 if (!ab8500_dir)
carriere etienne0fbce762011-04-08 16:26:36 +02001600 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001601
John Beckett1478a312011-05-31 13:54:27 +01001602 ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING,
1603 ab8500_dir);
1604 if (!ab8500_gpadc_dir)
1605 goto err;
1606
1607 file = debugfs_create_file("all-bank-registers", S_IRUGO,
1608 ab8500_dir, &plf->dev, &ab8500_registers_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001609 if (!file)
1610 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001611
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +01001612 file = debugfs_create_file("all-banks", S_IRUGO,
1613 ab8500_dir, &plf->dev, &ab8500_all_banks_fops);
1614 if (!file)
1615 goto err;
1616
John Beckett1478a312011-05-31 13:54:27 +01001617 file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR),
1618 ab8500_dir, &plf->dev, &ab8500_bank_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001619 if (!file)
1620 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001621
John Beckett1478a312011-05-31 13:54:27 +01001622 file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR),
1623 ab8500_dir, &plf->dev, &ab8500_address_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001624 if (!file)
1625 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001626
John Beckett1478a312011-05-31 13:54:27 +01001627 file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR),
1628 ab8500_dir, &plf->dev, &ab8500_val_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001629 if (!file)
1630 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001631
John Beckett1478a312011-05-31 13:54:27 +01001632 file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR),
1633 ab8500_dir, &plf->dev, &ab8500_subscribe_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001634 if (!file)
1635 goto err;
Lee Jones4b8ac082013-01-14 16:10:36 +00001636
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001637 if (is_ab8500(ab8500))
1638 num_interrupt_lines = AB8500_NR_IRQS;
1639 else if (is_ab8505(ab8500))
1640 num_interrupt_lines = AB8505_NR_IRQS;
1641 else if (is_ab9540(ab8500))
1642 num_interrupt_lines = AB9540_NR_IRQS;
1643
1644 file = debugfs_create_file("interrupts", (S_IRUGO),
1645 ab8500_dir, &plf->dev, &ab8500_interrupts_fops);
1646 if (!file)
1647 goto err;
1648
John Beckett1478a312011-05-31 13:54:27 +01001649 file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR),
1650 ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001651 if (!file)
1652 goto err;
1653
John Beckett1478a312011-05-31 13:54:27 +01001654 file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR),
1655 ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
1656 if (!file)
1657 goto err;
1658
1659 file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR),
1660 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops);
1661 if (!file)
1662 goto err;
1663
1664 file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR),
1665 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops);
1666 if (!file)
1667 goto err;
1668
1669 file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR),
1670 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops);
1671 if (!file)
1672 goto err;
1673
1674 file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR),
1675 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops);
1676 if (!file)
1677 goto err;
1678
1679 file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR),
1680 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops);
1681 if (!file)
1682 goto err;
1683
1684 file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR),
1685 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops);
1686 if (!file)
1687 goto err;
1688
1689 file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR),
1690 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops);
1691 if (!file)
1692 goto err;
1693
1694 file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR),
1695 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops);
1696 if (!file)
1697 goto err;
1698
1699 file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR),
1700 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops);
1701 if (!file)
1702 goto err;
1703
1704 file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR),
1705 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops);
1706 if (!file)
1707 goto err;
1708
1709 file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR),
1710 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
1711 if (!file)
1712 goto err;
1713
1714 file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR),
1715 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops);
1716 if (!file)
1717 goto err;
1718
1719 file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR),
1720 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001721 if (!file)
1722 goto err;
Lee Jones4b8ac082013-01-14 16:10:36 +00001723
Mattias Wallind7b9f322010-11-26 13:06:39 +01001724 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001725
carriere etienne0fbce762011-04-08 16:26:36 +02001726err:
1727 if (ab8500_dir)
1728 debugfs_remove_recursive(ab8500_dir);
Mattias Wallind7b9f322010-11-26 13:06:39 +01001729 dev_err(&plf->dev, "failed to create debugfs entries.\n");
Linus Walleijddba25f2012-02-03 11:19:05 +01001730out_freeevent_name:
1731 kfree(event_name);
1732out_freedev_attr:
1733 kfree(dev_attr);
1734out_freeirq_count:
1735 kfree(irq_count);
1736
1737 return ret;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001738}
1739
Bill Pemberton4740f732012-11-19 13:26:01 -05001740static int ab8500_debug_remove(struct platform_device *plf)
Mattias Wallin5814fc32010-09-13 16:05:04 +02001741{
carriere etienne0fbce762011-04-08 16:26:36 +02001742 debugfs_remove_recursive(ab8500_dir);
Linus Walleijddba25f2012-02-03 11:19:05 +01001743 kfree(event_name);
1744 kfree(dev_attr);
1745 kfree(irq_count);
1746
Mattias Wallind7b9f322010-11-26 13:06:39 +01001747 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001748}
1749
1750static struct platform_driver ab8500_debug_driver = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001751 .driver = {
1752 .name = "ab8500-debug",
1753 .owner = THIS_MODULE,
1754 },
1755 .probe = ab8500_debug_probe,
Bill Pemberton84449212012-11-19 13:20:24 -05001756 .remove = ab8500_debug_remove
Mattias Wallin5814fc32010-09-13 16:05:04 +02001757};
1758
1759static int __init ab8500_debug_init(void)
1760{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001761 return platform_driver_register(&ab8500_debug_driver);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001762}
1763
1764static void __exit ab8500_debug_exit(void)
1765{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001766 platform_driver_unregister(&ab8500_debug_driver);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001767}
1768subsys_initcall(ab8500_debug_init);
1769module_exit(ab8500_debug_exit);
1770
1771MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
1772MODULE_DESCRIPTION("AB8500 DEBUG");
1773MODULE_LICENSE("GPL v2");