blob: a653a0747b31d911990201088f4d3fb996d52f1f [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>
Jonas Aaberg2cf64e22012-05-31 07:57:07 +020083#include <linux/irq.h>
Mattias Wallin5814fc32010-09-13 16:05:04 +020084
85#include <linux/mfd/abx500.h>
Linus Walleij0cd5b6d02013-02-06 23:23:01 +010086#include <linux/mfd/abx500/ab8500.h>
John Beckett1478a312011-05-31 13:54:27 +010087#include <linux/mfd/abx500/ab8500-gpadc.h>
Mattias Wallin5814fc32010-09-13 16:05:04 +020088
carriere etienne0fbce762011-04-08 16:26:36 +020089#ifdef CONFIG_DEBUG_FS
90#include <linux/string.h>
91#include <linux/ctype.h>
92#endif
93
Mattias Wallin5814fc32010-09-13 16:05:04 +020094static u32 debug_bank;
95static u32 debug_address;
96
Lee Jones4b8ac082013-01-14 16:10:36 +000097static int irq_first;
98static int irq_last;
Linus Walleijddba25f2012-02-03 11:19:05 +010099static u32 *irq_count;
100static int num_irqs;
Mattias Wallin0b337e72010-11-19 17:55:11 +0100101
Linus Walleijddba25f2012-02-03 11:19:05 +0100102static struct device_attribute **dev_attr;
103static char **event_name;
Lee Jones4b8ac082013-01-14 16:10:36 +0000104
Lee Jones73482342013-02-26 10:06:55 +0000105static u8 avg_sample = SAMPLE_16;
106static u8 trig_edge = RISING_EDGE;
107static u8 conv_type = ADC_SW;
108static u8 trig_timer;
109
Mattias Wallin5814fc32010-09-13 16:05:04 +0200110/**
111 * struct ab8500_reg_range
112 * @first: the first address of the range
113 * @last: the last address of the range
114 * @perm: access permissions for the range
115 */
116struct ab8500_reg_range {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100117 u8 first;
118 u8 last;
119 u8 perm;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200120};
121
122/**
Lee Jones822672a2012-06-20 13:56:38 +0100123 * struct ab8500_prcmu_ranges
Mattias Wallin5814fc32010-09-13 16:05:04 +0200124 * @num_ranges: the number of ranges in the list
125 * @bankid: bank identifier
126 * @range: the list of register ranges
127 */
Lee Jones822672a2012-06-20 13:56:38 +0100128struct ab8500_prcmu_ranges {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100129 u8 num_ranges;
130 u8 bankid;
131 const struct ab8500_reg_range *range;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200132};
133
carriere etienne0fbce762011-04-08 16:26:36 +0200134/* hwreg- "mask" and "shift" entries ressources */
135struct hwreg_cfg {
136 u32 bank; /* target bank */
137 u32 addr; /* target address */
138 uint fmt; /* format */
139 uint mask; /* read/write mask, applied before any bit shift */
140 int shift; /* bit shift (read:right shift, write:left shift */
141};
142/* fmt bit #0: 0=hexa, 1=dec */
143#define REG_FMT_DEC(c) ((c)->fmt & 0x1)
144#define REG_FMT_HEX(c) (!REG_FMT_DEC(c))
145
146static struct hwreg_cfg hwreg_cfg = {
147 .addr = 0, /* default: invalid phys addr */
148 .fmt = 0, /* default: 32bit access, hex output */
149 .mask = 0xFFFFFFFF, /* default: no mask */
150 .shift = 0, /* default: no bit shift */
151};
152
Mattias Wallin5814fc32010-09-13 16:05:04 +0200153#define AB8500_NAME_STRING "ab8500"
John Beckett1478a312011-05-31 13:54:27 +0100154#define AB8500_ADC_NAME_STRING "gpadc"
Philippe Langlais40c064e2011-10-17 09:48:55 +0200155#define AB8500_NUM_BANKS 24
Mattias Wallin5814fc32010-09-13 16:05:04 +0200156
157#define AB8500_REV_REG 0x80
158
Lee Jones9581ae32012-07-06 16:11:50 +0200159static struct ab8500_prcmu_ranges *debug_ranges;
160
161struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100162 [0x0] = {
163 .num_ranges = 0,
Lee Jonesfad55a82013-01-14 17:17:34 +0000164 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100165 },
166 [AB8500_SYS_CTRL1_BLOCK] = {
167 .num_ranges = 3,
168 .range = (struct ab8500_reg_range[]) {
169 {
170 .first = 0x00,
171 .last = 0x02,
172 },
173 {
174 .first = 0x42,
175 .last = 0x42,
176 },
177 {
178 .first = 0x80,
179 .last = 0x81,
180 },
181 },
182 },
183 [AB8500_SYS_CTRL2_BLOCK] = {
184 .num_ranges = 4,
185 .range = (struct ab8500_reg_range[]) {
186 {
187 .first = 0x00,
188 .last = 0x0D,
189 },
190 {
191 .first = 0x0F,
192 .last = 0x17,
193 },
194 {
195 .first = 0x30,
196 .last = 0x30,
197 },
198 {
199 .first = 0x32,
200 .last = 0x33,
201 },
202 },
203 },
204 [AB8500_REGU_CTRL1] = {
205 .num_ranges = 3,
206 .range = (struct ab8500_reg_range[]) {
207 {
208 .first = 0x00,
209 .last = 0x00,
210 },
211 {
212 .first = 0x03,
213 .last = 0x10,
214 },
215 {
216 .first = 0x80,
217 .last = 0x84,
218 },
219 },
220 },
221 [AB8500_REGU_CTRL2] = {
222 .num_ranges = 5,
223 .range = (struct ab8500_reg_range[]) {
224 {
225 .first = 0x00,
226 .last = 0x15,
227 },
228 {
229 .first = 0x17,
230 .last = 0x19,
231 },
232 {
233 .first = 0x1B,
234 .last = 0x1D,
235 },
236 {
237 .first = 0x1F,
238 .last = 0x22,
239 },
240 {
241 .first = 0x40,
242 .last = 0x44,
243 },
244 /* 0x80-0x8B is SIM registers and should
245 * not be accessed from here */
246 },
247 },
248 [AB8500_USB] = {
249 .num_ranges = 2,
250 .range = (struct ab8500_reg_range[]) {
251 {
252 .first = 0x80,
253 .last = 0x83,
254 },
255 {
256 .first = 0x87,
257 .last = 0x8A,
258 },
259 },
260 },
261 [AB8500_TVOUT] = {
262 .num_ranges = 9,
263 .range = (struct ab8500_reg_range[]) {
264 {
265 .first = 0x00,
266 .last = 0x12,
267 },
268 {
269 .first = 0x15,
270 .last = 0x17,
271 },
272 {
273 .first = 0x19,
274 .last = 0x21,
275 },
276 {
277 .first = 0x27,
278 .last = 0x2C,
279 },
280 {
281 .first = 0x41,
282 .last = 0x41,
283 },
284 {
285 .first = 0x45,
286 .last = 0x5B,
287 },
288 {
289 .first = 0x5D,
290 .last = 0x5D,
291 },
292 {
293 .first = 0x69,
294 .last = 0x69,
295 },
296 {
297 .first = 0x80,
298 .last = 0x81,
299 },
300 },
301 },
302 [AB8500_DBI] = {
303 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000304 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100305 },
306 [AB8500_ECI_AV_ACC] = {
307 .num_ranges = 1,
308 .range = (struct ab8500_reg_range[]) {
309 {
310 .first = 0x80,
311 .last = 0x82,
312 },
313 },
314 },
315 [0x9] = {
316 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000317 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100318 },
319 [AB8500_GPADC] = {
320 .num_ranges = 1,
321 .range = (struct ab8500_reg_range[]) {
322 {
323 .first = 0x00,
324 .last = 0x08,
325 },
326 },
327 },
328 [AB8500_CHARGER] = {
Philippe Langlais40c064e2011-10-17 09:48:55 +0200329 .num_ranges = 9,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100330 .range = (struct ab8500_reg_range[]) {
331 {
332 .first = 0x00,
333 .last = 0x03,
334 },
335 {
336 .first = 0x05,
337 .last = 0x05,
338 },
339 {
340 .first = 0x40,
341 .last = 0x40,
342 },
343 {
344 .first = 0x42,
345 .last = 0x42,
346 },
347 {
348 .first = 0x44,
349 .last = 0x44,
350 },
351 {
352 .first = 0x50,
353 .last = 0x55,
354 },
355 {
356 .first = 0x80,
357 .last = 0x82,
358 },
359 {
360 .first = 0xC0,
361 .last = 0xC2,
362 },
Philippe Langlais40c064e2011-10-17 09:48:55 +0200363 {
364 .first = 0xf5,
Lee Jones9581ae32012-07-06 16:11:50 +0200365 .last = 0xf6,
Philippe Langlais40c064e2011-10-17 09:48:55 +0200366 },
Mattias Wallind7b9f322010-11-26 13:06:39 +0100367 },
368 },
369 [AB8500_GAS_GAUGE] = {
370 .num_ranges = 3,
371 .range = (struct ab8500_reg_range[]) {
372 {
373 .first = 0x00,
374 .last = 0x00,
375 },
376 {
377 .first = 0x07,
378 .last = 0x0A,
379 },
380 {
381 .first = 0x10,
382 .last = 0x14,
383 },
384 },
385 },
Philippe Langlais40c064e2011-10-17 09:48:55 +0200386 [AB8500_DEVELOPMENT] = {
387 .num_ranges = 1,
388 .range = (struct ab8500_reg_range[]) {
389 {
390 .first = 0x00,
391 .last = 0x00,
392 },
393 },
394 },
395 [AB8500_DEBUG] = {
396 .num_ranges = 1,
397 .range = (struct ab8500_reg_range[]) {
398 {
399 .first = 0x05,
400 .last = 0x07,
401 },
402 },
403 },
Mattias Wallind7b9f322010-11-26 13:06:39 +0100404 [AB8500_AUDIO] = {
405 .num_ranges = 1,
406 .range = (struct ab8500_reg_range[]) {
407 {
408 .first = 0x00,
409 .last = 0x6F,
410 },
411 },
412 },
413 [AB8500_INTERRUPT] = {
414 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000415 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100416 },
417 [AB8500_RTC] = {
418 .num_ranges = 1,
419 .range = (struct ab8500_reg_range[]) {
420 {
421 .first = 0x00,
422 .last = 0x0F,
423 },
424 },
425 },
426 [AB8500_MISC] = {
427 .num_ranges = 8,
428 .range = (struct ab8500_reg_range[]) {
429 {
430 .first = 0x00,
431 .last = 0x05,
432 },
433 {
434 .first = 0x10,
435 .last = 0x15,
436 },
437 {
438 .first = 0x20,
439 .last = 0x25,
440 },
441 {
442 .first = 0x30,
443 .last = 0x35,
444 },
445 {
446 .first = 0x40,
447 .last = 0x45,
448 },
449 {
450 .first = 0x50,
451 .last = 0x50,
452 },
453 {
454 .first = 0x60,
455 .last = 0x67,
456 },
457 {
458 .first = 0x80,
459 .last = 0x80,
460 },
461 },
462 },
463 [0x11] = {
464 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000465 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100466 },
467 [0x12] = {
468 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000469 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100470 },
471 [0x13] = {
472 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000473 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100474 },
475 [0x14] = {
476 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000477 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100478 },
479 [AB8500_OTP_EMUL] = {
480 .num_ranges = 1,
481 .range = (struct ab8500_reg_range[]) {
482 {
483 .first = 0x01,
484 .last = 0x0F,
485 },
486 },
487 },
Mattias Wallin5814fc32010-09-13 16:05:04 +0200488};
489
Lee Jones9581ae32012-07-06 16:11:50 +0200490struct ab8500_prcmu_ranges ab8505_debug_ranges[AB8500_NUM_BANKS] = {
491 [0x0] = {
492 .num_ranges = 0,
493 .range = NULL,
494 },
495 [AB8500_SYS_CTRL1_BLOCK] = {
496 .num_ranges = 5,
497 .range = (struct ab8500_reg_range[]) {
498 {
499 .first = 0x00,
500 .last = 0x04,
501 },
502 {
503 .first = 0x42,
504 .last = 0x42,
505 },
506 {
507 .first = 0x52,
508 .last = 0x52,
509 },
510 {
511 .first = 0x54,
512 .last = 0x57,
513 },
514 {
515 .first = 0x80,
516 .last = 0x83,
517 },
518 },
519 },
520 [AB8500_SYS_CTRL2_BLOCK] = {
521 .num_ranges = 5,
522 .range = (struct ab8500_reg_range[]) {
523 {
524 .first = 0x00,
525 .last = 0x0D,
526 },
527 {
528 .first = 0x0F,
529 .last = 0x17,
530 },
531 {
532 .first = 0x20,
533 .last = 0x20,
534 },
535 {
536 .first = 0x30,
537 .last = 0x30,
538 },
539 {
540 .first = 0x32,
541 .last = 0x3A,
542 },
543 },
544 },
545 [AB8500_REGU_CTRL1] = {
546 .num_ranges = 3,
547 .range = (struct ab8500_reg_range[]) {
548 {
549 .first = 0x00,
550 .last = 0x00,
551 },
552 {
553 .first = 0x03,
554 .last = 0x11,
555 },
556 {
557 .first = 0x80,
558 .last = 0x86,
559 },
560 },
561 },
562 [AB8500_REGU_CTRL2] = {
563 .num_ranges = 6,
564 .range = (struct ab8500_reg_range[]) {
565 {
566 .first = 0x00,
567 .last = 0x06,
568 },
569 {
570 .first = 0x08,
571 .last = 0x15,
572 },
573 {
574 .first = 0x17,
575 .last = 0x19,
576 },
577 {
578 .first = 0x1B,
579 .last = 0x1D,
580 },
581 {
582 .first = 0x1F,
583 .last = 0x30,
584 },
585 {
586 .first = 0x40,
587 .last = 0x48,
588 },
589 /* 0x80-0x8B is SIM registers and should
590 * not be accessed from here */
591 },
592 },
593 [AB8500_USB] = {
594 .num_ranges = 3,
595 .range = (struct ab8500_reg_range[]) {
596 {
597 .first = 0x80,
598 .last = 0x83,
599 },
600 {
601 .first = 0x87,
602 .last = 0x8A,
603 },
604 {
605 .first = 0x91,
606 .last = 0x94,
607 },
608 },
609 },
610 [AB8500_TVOUT] = {
611 .num_ranges = 0,
612 .range = NULL,
613 },
614 [AB8500_DBI] = {
615 .num_ranges = 0,
616 .range = NULL,
617 },
618 [AB8500_ECI_AV_ACC] = {
619 .num_ranges = 1,
620 .range = (struct ab8500_reg_range[]) {
621 {
622 .first = 0x80,
623 .last = 0x82,
624 },
625 },
626 },
627 [AB8500_RESERVED] = {
628 .num_ranges = 0,
629 .range = NULL,
630 },
631 [AB8500_GPADC] = {
632 .num_ranges = 1,
633 .range = (struct ab8500_reg_range[]) {
634 {
635 .first = 0x00,
636 .last = 0x08,
637 },
638 },
639 },
640 [AB8500_CHARGER] = {
641 .num_ranges = 9,
642 .range = (struct ab8500_reg_range[]) {
643 {
644 .first = 0x02,
645 .last = 0x03,
646 },
647 {
648 .first = 0x05,
649 .last = 0x05,
650 },
651 {
652 .first = 0x40,
653 .last = 0x44,
654 },
655 {
656 .first = 0x50,
657 .last = 0x57,
658 },
659 {
660 .first = 0x60,
661 .last = 0x60,
662 },
663 {
664 .first = 0xA0,
665 .last = 0xA7,
666 },
667 {
668 .first = 0xAF,
669 .last = 0xB2,
670 },
671 {
672 .first = 0xC0,
673 .last = 0xC2,
674 },
675 {
676 .first = 0xF5,
677 .last = 0xF5,
678 },
679 },
680 },
681 [AB8500_GAS_GAUGE] = {
682 .num_ranges = 3,
683 .range = (struct ab8500_reg_range[]) {
684 {
685 .first = 0x00,
686 .last = 0x00,
687 },
688 {
689 .first = 0x07,
690 .last = 0x0A,
691 },
692 {
693 .first = 0x10,
694 .last = 0x14,
695 },
696 },
697 },
698 [AB8500_AUDIO] = {
699 .num_ranges = 1,
700 .range = (struct ab8500_reg_range[]) {
701 {
702 .first = 0x00,
703 .last = 0x83,
704 },
705 },
706 },
707 [AB8500_INTERRUPT] = {
708 .num_ranges = 11,
709 .range = (struct ab8500_reg_range[]) {
710 {
711 .first = 0x00,
712 .last = 0x04,
713 },
714 {
715 .first = 0x06,
716 .last = 0x07,
717 },
718 {
719 .first = 0x09,
720 .last = 0x09,
721 },
722 {
723 .first = 0x0B,
724 .last = 0x0C,
725 },
726 {
727 .first = 0x12,
728 .last = 0x15,
729 },
730 {
731 .first = 0x18,
732 .last = 0x18,
733 },
734 /* Latch registers should not be read here */
735 {
736 .first = 0x40,
737 .last = 0x44,
738 },
739 {
740 .first = 0x46,
741 .last = 0x49,
742 },
743 {
744 .first = 0x4B,
745 .last = 0x4D,
746 },
747 {
748 .first = 0x52,
749 .last = 0x55,
750 },
751 {
752 .first = 0x58,
753 .last = 0x58,
754 },
755 /* LatchHier registers should not be read here */
756 },
757 },
758 [AB8500_RTC] = {
759 .num_ranges = 2,
760 .range = (struct ab8500_reg_range[]) {
761 {
762 .first = 0x00,
763 .last = 0x14,
764 },
765 {
766 .first = 0x16,
767 .last = 0x17,
768 },
769 },
770 },
771 [AB8500_MISC] = {
772 .num_ranges = 8,
773 .range = (struct ab8500_reg_range[]) {
774 {
775 .first = 0x00,
776 .last = 0x06,
777 },
778 {
779 .first = 0x10,
780 .last = 0x16,
781 },
782 {
783 .first = 0x20,
784 .last = 0x26,
785 },
786 {
787 .first = 0x30,
788 .last = 0x36,
789 },
790 {
791 .first = 0x40,
792 .last = 0x46,
793 },
794 {
795 .first = 0x50,
796 .last = 0x50,
797 },
798 {
799 .first = 0x60,
800 .last = 0x6B,
801 },
802 {
803 .first = 0x80,
804 .last = 0x82,
805 },
806 },
807 },
808 [AB8500_DEVELOPMENT] = {
809 .num_ranges = 2,
810 .range = (struct ab8500_reg_range[]) {
811 {
812 .first = 0x00,
813 .last = 0x00,
814 },
815 {
816 .first = 0x05,
817 .last = 0x05,
818 },
819 },
820 },
821 [AB8500_DEBUG] = {
822 .num_ranges = 1,
823 .range = (struct ab8500_reg_range[]) {
824 {
825 .first = 0x05,
826 .last = 0x07,
827 },
828 },
829 },
830 [AB8500_PROD_TEST] = {
831 .num_ranges = 0,
832 .range = NULL,
833 },
834 [AB8500_STE_TEST] = {
835 .num_ranges = 0,
836 .range = NULL,
837 },
838 [AB8500_OTP_EMUL] = {
839 .num_ranges = 1,
840 .range = (struct ab8500_reg_range[]) {
841 {
842 .first = 0x01,
843 .last = 0x15,
844 },
845 },
846 },
847};
848
Lee Jones4b8ac082013-01-14 16:10:36 +0000849static irqreturn_t ab8500_debug_handler(int irq, void *data)
850{
851 char buf[16];
852 struct kobject *kobj = (struct kobject *)data;
Mattias Wallin0b337e72010-11-19 17:55:11 +0100853 unsigned int irq_abb = irq - irq_first;
Lee Jones4b8ac082013-01-14 16:10:36 +0000854
Linus Walleijddba25f2012-02-03 11:19:05 +0100855 if (irq_abb < num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +0100856 irq_count[irq_abb]++;
Lee Jones4b8ac082013-01-14 16:10:36 +0000857 /*
858 * This makes it possible to use poll for events (POLLPRI | POLLERR)
Mattias Wallin0b337e72010-11-19 17:55:11 +0100859 * from userspace on sysfs file named <irq-nr>
Lee Jones4b8ac082013-01-14 16:10:36 +0000860 */
Mattias Wallin0b337e72010-11-19 17:55:11 +0100861 sprintf(buf, "%d", irq);
Lee Jones4b8ac082013-01-14 16:10:36 +0000862 sysfs_notify(kobj, NULL, buf);
863
864 return IRQ_HANDLED;
865}
866
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100867/* Prints to seq_file or log_buf */
868static int ab8500_registers_print(struct device *dev, u32 bank,
869 struct seq_file *s)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200870{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100871 unsigned int i;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200872
Mattias Wallind7b9f322010-11-26 13:06:39 +0100873 for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
874 u32 reg;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200875
Mattias Wallind7b9f322010-11-26 13:06:39 +0100876 for (reg = debug_ranges[bank].range[i].first;
877 reg <= debug_ranges[bank].range[i].last;
878 reg++) {
879 u8 value;
880 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200881
Mattias Wallind7b9f322010-11-26 13:06:39 +0100882 err = abx500_get_register_interruptible(dev,
883 (u8)bank, (u8)reg, &value);
884 if (err < 0) {
885 dev_err(dev, "ab->read fail %d\n", err);
886 return err;
887 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200888
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100889 if (s) {
Mattias Wallincfc08492012-05-28 15:53:58 +0200890 err = seq_printf(s, " [0x%02X/0x%02X]: 0x%02X\n",
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100891 bank, reg, value);
892 if (err < 0) {
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100893 /* Error is not returned here since
894 * the output is wanted in any case */
895 return 0;
896 }
897 } else {
Mattias Wallincfc08492012-05-28 15:53:58 +0200898 printk(KERN_INFO" [0x%02X/0x%02X]: 0x%02X\n",
899 bank, reg, value);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100900 }
901 }
902 }
903 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200904}
905
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100906static int ab8500_print_bank_registers(struct seq_file *s, void *p)
907{
908 struct device *dev = s->private;
909 u32 bank = debug_bank;
910
911 seq_printf(s, AB8500_NAME_STRING " register values:\n");
912
Mattias Wallincfc08492012-05-28 15:53:58 +0200913 seq_printf(s, " bank 0x%02X:\n", bank);
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100914
915 ab8500_registers_print(dev, bank, s);
916 return 0;
917}
918
Mattias Wallin5814fc32010-09-13 16:05:04 +0200919static int ab8500_registers_open(struct inode *inode, struct file *file)
920{
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100921 return single_open(file, ab8500_print_bank_registers, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200922}
923
924static const struct file_operations ab8500_registers_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100925 .open = ab8500_registers_open,
926 .read = seq_read,
927 .llseek = seq_lseek,
928 .release = single_release,
929 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +0200930};
931
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100932static int ab8500_print_all_banks(struct seq_file *s, void *p)
933{
934 struct device *dev = s->private;
935 unsigned int i;
936 int err;
937
938 seq_printf(s, AB8500_NAME_STRING " register values:\n");
939
940 for (i = 1; i < AB8500_NUM_BANKS; i++) {
Mattias Wallincfc08492012-05-28 15:53:58 +0200941 err = seq_printf(s, " bank 0x%02X:\n", i);
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100942
943 ab8500_registers_print(dev, i, s);
944 }
945 return 0;
946}
947
Mian Yousaf Kaukab1d843a62012-01-27 11:35:41 +0100948/* Dump registers to kernel log */
949void ab8500_dump_all_banks(struct device *dev)
950{
951 unsigned int i;
952
953 printk(KERN_INFO"ab8500 register values:\n");
954
955 for (i = 1; i < AB8500_NUM_BANKS; i++) {
Mattias Wallincfc08492012-05-28 15:53:58 +0200956 printk(KERN_INFO" bank 0x%02X:\n", i);
Mian Yousaf Kaukab1d843a62012-01-27 11:35:41 +0100957 ab8500_registers_print(dev, i, NULL);
958 }
959}
960
Lee Jones5ff90902013-02-12 14:35:28 +0000961/* Space for 500 registers. */
962#define DUMP_MAX_REGS 700
963struct ab8500_register_dump
964{
965 u8 bank;
966 u8 reg;
967 u8 value;
Lee Jones5ff90902013-02-12 14:35:28 +0000968} ab8500_complete_register_dump[DUMP_MAX_REGS];
969
970extern int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
971
972/* This shall only be called upon kernel panic! */
973void ab8500_dump_all_banks_to_mem(void)
974{
975 int i, r = 0;
976 u8 bank;
Jonas Aaberg222460c2012-06-18 10:35:28 +0200977 int err = 0;
Lee Jones5ff90902013-02-12 14:35:28 +0000978
979 pr_info("Saving all ABB registers at \"ab8500_complete_register_dump\" "
980 "for crash analyze.\n");
981
982 for (bank = 1; bank < AB8500_NUM_BANKS; bank++) {
983 for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
984 u8 reg;
985
986 for (reg = debug_ranges[bank].range[i].first;
987 reg <= debug_ranges[bank].range[i].last;
988 reg++) {
989 u8 value;
Lee Jones5ff90902013-02-12 14:35:28 +0000990
991 err = prcmu_abb_read(bank, reg, &value, 1);
992
Jonas Aaberg222460c2012-06-18 10:35:28 +0200993 if (err < 0)
994 goto out;
995
Lee Jones5ff90902013-02-12 14:35:28 +0000996 ab8500_complete_register_dump[r].bank = bank;
997 ab8500_complete_register_dump[r].reg = reg;
998 ab8500_complete_register_dump[r].value = value;
999
1000 r++;
1001
1002 if (r >= DUMP_MAX_REGS) {
1003 pr_err("%s: too many register to dump!\n",
1004 __func__);
Jonas Aaberg222460c2012-06-18 10:35:28 +02001005 err = -EINVAL;
1006 goto out;
Lee Jones5ff90902013-02-12 14:35:28 +00001007 }
1008 }
1009 }
1010 }
Jonas Aaberg222460c2012-06-18 10:35:28 +02001011out:
1012 if (err >= 0)
1013 pr_info("Saved all ABB registers.\n");
1014 else
1015 pr_info("Failed to save all ABB registers.\n");
Lee Jones5ff90902013-02-12 14:35:28 +00001016}
1017
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +01001018static int ab8500_all_banks_open(struct inode *inode, struct file *file)
1019{
1020 struct seq_file *s;
1021 int err;
1022
1023 err = single_open(file, ab8500_print_all_banks, inode->i_private);
1024 if (!err) {
1025 /* Default buf size in seq_read is not enough */
1026 s = (struct seq_file *)file->private_data;
1027 s->size = (PAGE_SIZE * 2);
1028 s->buf = kmalloc(s->size, GFP_KERNEL);
1029 if (!s->buf) {
1030 single_release(inode, file);
1031 err = -ENOMEM;
1032 }
1033 }
1034 return err;
1035}
1036
1037static const struct file_operations ab8500_all_banks_fops = {
1038 .open = ab8500_all_banks_open,
1039 .read = seq_read,
1040 .llseek = seq_lseek,
1041 .release = single_release,
1042 .owner = THIS_MODULE,
1043};
1044
Mattias Wallin5814fc32010-09-13 16:05:04 +02001045static int ab8500_bank_print(struct seq_file *s, void *p)
1046{
Mattias Wallincfc08492012-05-28 15:53:58 +02001047 return seq_printf(s, "0x%02X\n", debug_bank);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001048}
1049
1050static int ab8500_bank_open(struct inode *inode, struct file *file)
1051{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001052 return single_open(file, ab8500_bank_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001053}
1054
1055static ssize_t ab8500_bank_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +01001056 const char __user *user_buf,
1057 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +02001058{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001059 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +01001060 unsigned long user_bank;
1061 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001062
Mattias Wallind7b9f322010-11-26 13:06:39 +01001063 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +02001064 err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
Mattias Wallind7b9f322010-11-26 13:06:39 +01001065 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +02001066 return err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001067
Mattias Wallind7b9f322010-11-26 13:06:39 +01001068 if (user_bank >= AB8500_NUM_BANKS) {
1069 dev_err(dev, "debugfs error input > number of banks\n");
1070 return -EINVAL;
1071 }
Mattias Wallin5814fc32010-09-13 16:05:04 +02001072
Mattias Wallind7b9f322010-11-26 13:06:39 +01001073 debug_bank = user_bank;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001074
Peter Huewe8504d632011-06-06 22:43:32 +02001075 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001076}
1077
1078static int ab8500_address_print(struct seq_file *s, void *p)
1079{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001080 return seq_printf(s, "0x%02X\n", debug_address);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001081}
1082
1083static int ab8500_address_open(struct inode *inode, struct file *file)
1084{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001085 return single_open(file, ab8500_address_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001086}
1087
1088static ssize_t ab8500_address_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +01001089 const char __user *user_buf,
1090 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +02001091{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001092 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +01001093 unsigned long user_address;
1094 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001095
Mattias Wallind7b9f322010-11-26 13:06:39 +01001096 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +02001097 err = kstrtoul_from_user(user_buf, count, 0, &user_address);
Mattias Wallind7b9f322010-11-26 13:06:39 +01001098 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +02001099 return err;
1100
Mattias Wallind7b9f322010-11-26 13:06:39 +01001101 if (user_address > 0xff) {
1102 dev_err(dev, "debugfs error input > 0xff\n");
1103 return -EINVAL;
1104 }
1105 debug_address = user_address;
Peter Huewe8504d632011-06-06 22:43:32 +02001106 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001107}
1108
1109static int ab8500_val_print(struct seq_file *s, void *p)
1110{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001111 struct device *dev = s->private;
1112 int ret;
1113 u8 regvalue;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001114
Mattias Wallind7b9f322010-11-26 13:06:39 +01001115 ret = abx500_get_register_interruptible(dev,
1116 (u8)debug_bank, (u8)debug_address, &regvalue);
1117 if (ret < 0) {
1118 dev_err(dev, "abx500_get_reg fail %d, %d\n",
1119 ret, __LINE__);
1120 return -EINVAL;
1121 }
1122 seq_printf(s, "0x%02X\n", regvalue);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001123
Mattias Wallind7b9f322010-11-26 13:06:39 +01001124 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001125}
1126
1127static int ab8500_val_open(struct inode *inode, struct file *file)
1128{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001129 return single_open(file, ab8500_val_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001130}
1131
1132static ssize_t ab8500_val_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +01001133 const char __user *user_buf,
1134 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +02001135{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001136 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +01001137 unsigned long user_val;
1138 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001139
Mattias Wallind7b9f322010-11-26 13:06:39 +01001140 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +02001141 err = kstrtoul_from_user(user_buf, count, 0, &user_val);
Mattias Wallind7b9f322010-11-26 13:06:39 +01001142 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +02001143 return err;
1144
Mattias Wallind7b9f322010-11-26 13:06:39 +01001145 if (user_val > 0xff) {
1146 dev_err(dev, "debugfs error input > 0xff\n");
1147 return -EINVAL;
1148 }
1149 err = abx500_set_register_interruptible(dev,
1150 (u8)debug_bank, debug_address, (u8)user_val);
1151 if (err < 0) {
1152 printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
1153 return -EINVAL;
1154 }
Mattias Wallin5814fc32010-09-13 16:05:04 +02001155
Peter Huewe8504d632011-06-06 22:43:32 +02001156 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001157}
1158
carriere etienne0fbce762011-04-08 16:26:36 +02001159/*
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001160 * Interrupt status
1161 */
1162static u32 num_interrupts[AB8500_MAX_NR_IRQS];
Jonas Aaberg2cf64e22012-05-31 07:57:07 +02001163static u32 num_wake_interrupts[AB8500_MAX_NR_IRQS];
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001164static int num_interrupt_lines;
1165
Jonas Aaberg2cf64e22012-05-31 07:57:07 +02001166bool __attribute__((weak)) suspend_test_wake_cause_interrupt_is_mine(u32 my_int)
1167{
1168 return false;
1169}
1170
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001171void ab8500_debug_register_interrupt(int line)
1172{
Jonas Aaberg2cf64e22012-05-31 07:57:07 +02001173 if (line < num_interrupt_lines) {
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001174 num_interrupts[line]++;
Jonas Aaberg2cf64e22012-05-31 07:57:07 +02001175 if (suspend_test_wake_cause_interrupt_is_mine(IRQ_DB8500_AB8500))
1176 num_wake_interrupts[line]++;
1177 }
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001178}
1179
1180static int ab8500_interrupts_print(struct seq_file *s, void *p)
1181{
1182 int line;
1183
Jonas Aaberg2cf64e22012-05-31 07:57:07 +02001184 seq_printf(s, "name: number: number of: wake:\n");
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001185
Jonas Aaberg2cf64e22012-05-31 07:57:07 +02001186 for (line = 0; line < num_interrupt_lines; line++) {
1187 struct irq_desc *desc = irq_to_desc(line + irq_first);
1188 struct irqaction *action = desc->action;
1189
1190 seq_printf(s, "%3i: %6i %4i", line,
1191 num_interrupts[line],
1192 num_wake_interrupts[line]);
1193
1194 if (desc && desc->name)
1195 seq_printf(s, "-%-8s", desc->name);
1196 if (action) {
1197 seq_printf(s, " %s", action->name);
1198 while ((action = action->next) != NULL)
1199 seq_printf(s, ", %s", action->name);
1200 }
1201 seq_putc(s, '\n');
1202 }
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001203
1204 return 0;
1205}
1206
1207static int ab8500_interrupts_open(struct inode *inode, struct file *file)
1208{
1209 return single_open(file, ab8500_interrupts_print, inode->i_private);
1210}
1211
1212/*
carriere etienne0fbce762011-04-08 16:26:36 +02001213 * - HWREG DB8500 formated routines
1214 */
1215static int ab8500_hwreg_print(struct seq_file *s, void *d)
1216{
1217 struct device *dev = s->private;
1218 int ret;
1219 u8 regvalue;
1220
1221 ret = abx500_get_register_interruptible(dev,
1222 (u8)hwreg_cfg.bank, (u8)hwreg_cfg.addr, &regvalue);
1223 if (ret < 0) {
1224 dev_err(dev, "abx500_get_reg fail %d, %d\n",
1225 ret, __LINE__);
1226 return -EINVAL;
1227 }
1228
1229 if (hwreg_cfg.shift >= 0)
1230 regvalue >>= hwreg_cfg.shift;
1231 else
1232 regvalue <<= -hwreg_cfg.shift;
1233 regvalue &= hwreg_cfg.mask;
1234
1235 if (REG_FMT_DEC(&hwreg_cfg))
1236 seq_printf(s, "%d\n", regvalue);
1237 else
1238 seq_printf(s, "0x%02X\n", regvalue);
1239 return 0;
1240}
1241
1242static int ab8500_hwreg_open(struct inode *inode, struct file *file)
1243{
1244 return single_open(file, ab8500_hwreg_print, inode->i_private);
1245}
1246
Lee Jonesc7ebaee2013-02-26 14:03:33 +00001247#define AB8500_SUPPLY_CONTROL_CONFIG_1 0x01
1248#define AB8500_SUPPLY_CONTROL_REG 0x00
1249#define AB8500_FIRST_SIM_REG 0x80
1250#define AB8500_LAST_SIM_REG 0x8B
1251#define AB8505_LAST_SIM_REG 0x8C
1252
1253static int ab8500_print_modem_registers(struct seq_file *s, void *p)
1254{
1255 struct device *dev = s->private;
1256 struct ab8500 *ab8500;
1257 int err;
1258 u8 value;
1259 u8 orig_value;
1260 u32 bank = AB8500_REGU_CTRL2;
1261 u32 last_sim_reg = AB8500_LAST_SIM_REG;
1262 u32 reg;
1263
1264 ab8500 = dev_get_drvdata(dev->parent);
1265 dev_warn(dev, "WARNING! This operation can interfer with modem side\n"
1266 "and should only be done with care\n");
1267
1268 err = abx500_get_register_interruptible(dev,
1269 AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, &orig_value);
1270 if (err < 0) {
1271 dev_err(dev, "ab->read fail %d\n", err);
1272 return err;
1273 }
1274 /* Config 1 will allow APE side to read SIM registers */
1275 err = abx500_set_register_interruptible(dev,
1276 AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG,
1277 AB8500_SUPPLY_CONTROL_CONFIG_1);
1278 if (err < 0) {
1279 dev_err(dev, "ab->write fail %d\n", err);
1280 return err;
1281 }
1282
1283 seq_printf(s, " bank 0x%02X:\n", bank);
1284
1285 if (is_ab9540(ab8500) || is_ab8505(ab8500))
1286 last_sim_reg = AB8505_LAST_SIM_REG;
1287
1288 for (reg = AB8500_FIRST_SIM_REG; reg <= last_sim_reg; reg++) {
1289 err = abx500_get_register_interruptible(dev,
1290 bank, reg, &value);
1291 if (err < 0) {
1292 dev_err(dev, "ab->read fail %d\n", err);
1293 return err;
1294 }
1295 err = seq_printf(s, " [0x%02X/0x%02X]: 0x%02X\n",
1296 bank, reg, value);
1297 }
1298 err = abx500_set_register_interruptible(dev,
1299 AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, orig_value);
1300 if (err < 0) {
1301 dev_err(dev, "ab->write fail %d\n", err);
1302 return err;
1303 }
1304 return 0;
1305}
1306
1307static int ab8500_modem_open(struct inode *inode, struct file *file)
1308{
1309 return single_open(file, ab8500_print_modem_registers, inode->i_private);
1310}
1311
1312static const struct file_operations ab8500_modem_fops = {
1313 .open = ab8500_modem_open,
1314 .read = seq_read,
1315 .llseek = seq_lseek,
1316 .release = single_release,
1317 .owner = THIS_MODULE,
1318};
1319
John Beckett1478a312011-05-31 13:54:27 +01001320static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
1321{
1322 int bat_ctrl_raw;
1323 int bat_ctrl_convert;
1324 struct ab8500_gpadc *gpadc;
1325
Philippe Langlais8908c042012-04-18 15:52:59 +02001326 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001327 bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL,
1328 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001329 bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +00001330 BAT_CTRL, bat_ctrl_raw);
John Beckett1478a312011-05-31 13:54:27 +01001331
1332 return seq_printf(s, "%d,0x%X\n",
1333 bat_ctrl_convert, bat_ctrl_raw);
1334}
1335
1336static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
1337{
1338 return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private);
1339}
1340
1341static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
1342 .open = ab8500_gpadc_bat_ctrl_open,
1343 .read = seq_read,
1344 .llseek = seq_lseek,
1345 .release = single_release,
1346 .owner = THIS_MODULE,
1347};
1348
1349static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
1350{
1351 int btemp_ball_raw;
1352 int btemp_ball_convert;
1353 struct ab8500_gpadc *gpadc;
1354
Philippe Langlais8908c042012-04-18 15:52:59 +02001355 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001356 btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL,
1357 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001358 btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
Lee Jones73482342013-02-26 10:06:55 +00001359 btemp_ball_raw);
John Beckett1478a312011-05-31 13:54:27 +01001360
1361 return seq_printf(s,
1362 "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw);
1363}
1364
1365static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
1366 struct file *file)
1367{
1368 return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private);
1369}
1370
1371static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
1372 .open = ab8500_gpadc_btemp_ball_open,
1373 .read = seq_read,
1374 .llseek = seq_lseek,
1375 .release = single_release,
1376 .owner = THIS_MODULE,
1377};
1378
1379static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p)
1380{
1381 int main_charger_v_raw;
1382 int main_charger_v_convert;
1383 struct ab8500_gpadc *gpadc;
1384
Philippe Langlais8908c042012-04-18 15:52:59 +02001385 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001386 main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V,
1387 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001388 main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +00001389 MAIN_CHARGER_V, main_charger_v_raw);
John Beckett1478a312011-05-31 13:54:27 +01001390
1391 return seq_printf(s, "%d,0x%X\n",
1392 main_charger_v_convert, main_charger_v_raw);
1393}
1394
1395static int ab8500_gpadc_main_charger_v_open(struct inode *inode,
1396 struct file *file)
1397{
1398 return single_open(file, ab8500_gpadc_main_charger_v_print,
1399 inode->i_private);
1400}
1401
1402static const struct file_operations ab8500_gpadc_main_charger_v_fops = {
1403 .open = ab8500_gpadc_main_charger_v_open,
1404 .read = seq_read,
1405 .llseek = seq_lseek,
1406 .release = single_release,
1407 .owner = THIS_MODULE,
1408};
1409
1410static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p)
1411{
1412 int acc_detect1_raw;
1413 int acc_detect1_convert;
1414 struct ab8500_gpadc *gpadc;
1415
Philippe Langlais8908c042012-04-18 15:52:59 +02001416 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001417 acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1,
1418 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001419 acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1,
Lee Jones73482342013-02-26 10:06:55 +00001420 acc_detect1_raw);
John Beckett1478a312011-05-31 13:54:27 +01001421
1422 return seq_printf(s, "%d,0x%X\n",
1423 acc_detect1_convert, acc_detect1_raw);
1424}
1425
1426static int ab8500_gpadc_acc_detect1_open(struct inode *inode,
1427 struct file *file)
1428{
1429 return single_open(file, ab8500_gpadc_acc_detect1_print,
1430 inode->i_private);
1431}
1432
1433static const struct file_operations ab8500_gpadc_acc_detect1_fops = {
1434 .open = ab8500_gpadc_acc_detect1_open,
1435 .read = seq_read,
1436 .llseek = seq_lseek,
1437 .release = single_release,
1438 .owner = THIS_MODULE,
1439};
1440
1441static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p)
1442{
1443 int acc_detect2_raw;
1444 int acc_detect2_convert;
1445 struct ab8500_gpadc *gpadc;
1446
Philippe Langlais8908c042012-04-18 15:52:59 +02001447 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001448 acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2,
1449 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001450 acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +00001451 ACC_DETECT2, acc_detect2_raw);
John Beckett1478a312011-05-31 13:54:27 +01001452
1453 return seq_printf(s, "%d,0x%X\n",
1454 acc_detect2_convert, acc_detect2_raw);
1455}
1456
1457static int ab8500_gpadc_acc_detect2_open(struct inode *inode,
1458 struct file *file)
1459{
1460 return single_open(file, ab8500_gpadc_acc_detect2_print,
1461 inode->i_private);
1462}
1463
1464static const struct file_operations ab8500_gpadc_acc_detect2_fops = {
1465 .open = ab8500_gpadc_acc_detect2_open,
1466 .read = seq_read,
1467 .llseek = seq_lseek,
1468 .release = single_release,
1469 .owner = THIS_MODULE,
1470};
1471
1472static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p)
1473{
1474 int aux1_raw;
1475 int aux1_convert;
1476 struct ab8500_gpadc *gpadc;
1477
Philippe Langlais8908c042012-04-18 15:52:59 +02001478 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001479 aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1,
1480 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001481 aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1,
Lee Jones73482342013-02-26 10:06:55 +00001482 aux1_raw);
John Beckett1478a312011-05-31 13:54:27 +01001483
1484 return seq_printf(s, "%d,0x%X\n",
1485 aux1_convert, aux1_raw);
1486}
1487
1488static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file)
1489{
1490 return single_open(file, ab8500_gpadc_aux1_print, inode->i_private);
1491}
1492
1493static const struct file_operations ab8500_gpadc_aux1_fops = {
1494 .open = ab8500_gpadc_aux1_open,
1495 .read = seq_read,
1496 .llseek = seq_lseek,
1497 .release = single_release,
1498 .owner = THIS_MODULE,
1499};
1500
1501static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p)
1502{
1503 int aux2_raw;
1504 int aux2_convert;
1505 struct ab8500_gpadc *gpadc;
1506
Philippe Langlais8908c042012-04-18 15:52:59 +02001507 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001508 aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2,
1509 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001510 aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2,
Lee Jones73482342013-02-26 10:06:55 +00001511 aux2_raw);
John Beckett1478a312011-05-31 13:54:27 +01001512
1513 return seq_printf(s, "%d,0x%X\n",
1514 aux2_convert, aux2_raw);
1515}
1516
1517static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file)
1518{
1519 return single_open(file, ab8500_gpadc_aux2_print, inode->i_private);
1520}
1521
1522static const struct file_operations ab8500_gpadc_aux2_fops = {
1523 .open = ab8500_gpadc_aux2_open,
1524 .read = seq_read,
1525 .llseek = seq_lseek,
1526 .release = single_release,
1527 .owner = THIS_MODULE,
1528};
1529
1530static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
1531{
1532 int main_bat_v_raw;
1533 int main_bat_v_convert;
1534 struct ab8500_gpadc *gpadc;
1535
Philippe Langlais8908c042012-04-18 15:52:59 +02001536 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001537 main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V,
1538 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001539 main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
Lee Jones73482342013-02-26 10:06:55 +00001540 main_bat_v_raw);
John Beckett1478a312011-05-31 13:54:27 +01001541
1542 return seq_printf(s, "%d,0x%X\n",
1543 main_bat_v_convert, main_bat_v_raw);
1544}
1545
1546static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
1547 struct file *file)
1548{
1549 return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private);
1550}
1551
1552static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
1553 .open = ab8500_gpadc_main_bat_v_open,
1554 .read = seq_read,
1555 .llseek = seq_lseek,
1556 .release = single_release,
1557 .owner = THIS_MODULE,
1558};
1559
1560static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p)
1561{
1562 int vbus_v_raw;
1563 int vbus_v_convert;
1564 struct ab8500_gpadc *gpadc;
1565
Philippe Langlais8908c042012-04-18 15:52:59 +02001566 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001567 vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V,
1568 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001569 vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V,
Lee Jones73482342013-02-26 10:06:55 +00001570 vbus_v_raw);
John Beckett1478a312011-05-31 13:54:27 +01001571
1572 return seq_printf(s, "%d,0x%X\n",
1573 vbus_v_convert, vbus_v_raw);
1574}
1575
1576static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file)
1577{
1578 return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private);
1579}
1580
1581static const struct file_operations ab8500_gpadc_vbus_v_fops = {
1582 .open = ab8500_gpadc_vbus_v_open,
1583 .read = seq_read,
1584 .llseek = seq_lseek,
1585 .release = single_release,
1586 .owner = THIS_MODULE,
1587};
1588
1589static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p)
1590{
1591 int main_charger_c_raw;
1592 int main_charger_c_convert;
1593 struct ab8500_gpadc *gpadc;
1594
Philippe Langlais8908c042012-04-18 15:52:59 +02001595 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001596 main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C,
1597 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001598 main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +00001599 MAIN_CHARGER_C, main_charger_c_raw);
John Beckett1478a312011-05-31 13:54:27 +01001600
1601 return seq_printf(s, "%d,0x%X\n",
1602 main_charger_c_convert, main_charger_c_raw);
1603}
1604
1605static int ab8500_gpadc_main_charger_c_open(struct inode *inode,
1606 struct file *file)
1607{
1608 return single_open(file, ab8500_gpadc_main_charger_c_print,
1609 inode->i_private);
1610}
1611
1612static const struct file_operations ab8500_gpadc_main_charger_c_fops = {
1613 .open = ab8500_gpadc_main_charger_c_open,
1614 .read = seq_read,
1615 .llseek = seq_lseek,
1616 .release = single_release,
1617 .owner = THIS_MODULE,
1618};
1619
1620static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p)
1621{
1622 int usb_charger_c_raw;
1623 int usb_charger_c_convert;
1624 struct ab8500_gpadc *gpadc;
1625
Philippe Langlais8908c042012-04-18 15:52:59 +02001626 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001627 usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C,
1628 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001629 usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +00001630 USB_CHARGER_C, usb_charger_c_raw);
John Beckett1478a312011-05-31 13:54:27 +01001631
1632 return seq_printf(s, "%d,0x%X\n",
1633 usb_charger_c_convert, usb_charger_c_raw);
1634}
1635
1636static int ab8500_gpadc_usb_charger_c_open(struct inode *inode,
1637 struct file *file)
1638{
1639 return single_open(file, ab8500_gpadc_usb_charger_c_print,
1640 inode->i_private);
1641}
1642
1643static const struct file_operations ab8500_gpadc_usb_charger_c_fops = {
1644 .open = ab8500_gpadc_usb_charger_c_open,
1645 .read = seq_read,
1646 .llseek = seq_lseek,
1647 .release = single_release,
1648 .owner = THIS_MODULE,
1649};
1650
1651static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
1652{
1653 int bk_bat_v_raw;
1654 int bk_bat_v_convert;
1655 struct ab8500_gpadc *gpadc;
1656
Philippe Langlais8908c042012-04-18 15:52:59 +02001657 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001658 bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V,
1659 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001660 bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +00001661 BK_BAT_V, bk_bat_v_raw);
John Beckett1478a312011-05-31 13:54:27 +01001662
1663 return seq_printf(s, "%d,0x%X\n",
1664 bk_bat_v_convert, bk_bat_v_raw);
1665}
1666
1667static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
1668{
1669 return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private);
1670}
1671
1672static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
1673 .open = ab8500_gpadc_bk_bat_v_open,
1674 .read = seq_read,
1675 .llseek = seq_lseek,
1676 .release = single_release,
1677 .owner = THIS_MODULE,
1678};
1679
1680static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
1681{
1682 int die_temp_raw;
1683 int die_temp_convert;
1684 struct ab8500_gpadc *gpadc;
1685
Philippe Langlais8908c042012-04-18 15:52:59 +02001686 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001687 die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP,
1688 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001689 die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP,
Lee Jones73482342013-02-26 10:06:55 +00001690 die_temp_raw);
John Beckett1478a312011-05-31 13:54:27 +01001691
1692 return seq_printf(s, "%d,0x%X\n",
1693 die_temp_convert, die_temp_raw);
1694}
1695
1696static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
1697{
1698 return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private);
1699}
1700
1701static const struct file_operations ab8500_gpadc_die_temp_fops = {
1702 .open = ab8500_gpadc_die_temp_open,
1703 .read = seq_read,
1704 .llseek = seq_lseek,
1705 .release = single_release,
1706 .owner = THIS_MODULE,
1707};
1708
Lee Jonesbc6b4132013-02-26 14:02:31 +00001709static int ab8540_gpadc_xtal_temp_print(struct seq_file *s, void *p)
1710{
1711 int xtal_temp_raw;
1712 int xtal_temp_convert;
1713 struct ab8500_gpadc *gpadc;
1714
1715 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1716 xtal_temp_raw = ab8500_gpadc_read_raw(gpadc, XTAL_TEMP,
1717 avg_sample, trig_edge, trig_timer, conv_type);
1718 xtal_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, XTAL_TEMP,
1719 xtal_temp_raw);
1720
1721 return seq_printf(s, "%d,0x%X\n",
1722 xtal_temp_convert, xtal_temp_raw);
1723}
1724
1725static int ab8540_gpadc_xtal_temp_open(struct inode *inode, struct file *file)
1726{
1727 return single_open(file, ab8540_gpadc_xtal_temp_print,
1728 inode->i_private);
1729}
1730
1731static const struct file_operations ab8540_gpadc_xtal_temp_fops = {
1732 .open = ab8540_gpadc_xtal_temp_open,
1733 .read = seq_read,
1734 .llseek = seq_lseek,
1735 .release = single_release,
1736 .owner = THIS_MODULE,
1737};
1738
1739static int ab8540_gpadc_vbat_true_meas_print(struct seq_file *s, void *p)
1740{
1741 int vbat_true_meas_raw;
1742 int vbat_true_meas_convert;
1743 struct ab8500_gpadc *gpadc;
1744
1745 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1746 vbat_true_meas_raw = ab8500_gpadc_read_raw(gpadc, VBAT_TRUE_MEAS,
1747 avg_sample, trig_edge, trig_timer, conv_type);
1748 vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
1749 vbat_true_meas_raw);
1750
1751 return seq_printf(s, "%d,0x%X\n",
1752 vbat_true_meas_convert, vbat_true_meas_raw);
1753}
1754
1755static int ab8540_gpadc_vbat_true_meas_open(struct inode *inode,
1756 struct file *file)
1757{
1758 return single_open(file, ab8540_gpadc_vbat_true_meas_print,
1759 inode->i_private);
1760}
1761
1762static const struct file_operations ab8540_gpadc_vbat_true_meas_fops = {
1763 .open = ab8540_gpadc_vbat_true_meas_open,
1764 .read = seq_read,
1765 .llseek = seq_lseek,
1766 .release = single_release,
1767 .owner = THIS_MODULE,
1768};
1769
1770static int ab8540_gpadc_bat_ctrl_and_ibat_print(struct seq_file *s, void *p)
1771{
1772 int bat_ctrl_raw;
1773 int bat_ctrl_convert;
1774 int ibat_raw;
1775 int ibat_convert;
1776 struct ab8500_gpadc *gpadc;
1777
1778 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1779 bat_ctrl_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_CTRL_AND_IBAT,
1780 avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw);
1781
1782 bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, BAT_CTRL,
1783 bat_ctrl_raw);
1784 ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
1785 ibat_raw);
1786
1787 return seq_printf(s, "%d,0x%X\n" "%d,0x%X\n",
1788 bat_ctrl_convert, bat_ctrl_raw,
1789 ibat_convert, ibat_raw);
1790}
1791
1792static int ab8540_gpadc_bat_ctrl_and_ibat_open(struct inode *inode,
1793 struct file *file)
1794{
1795 return single_open(file, ab8540_gpadc_bat_ctrl_and_ibat_print,
1796 inode->i_private);
1797}
1798
1799static const struct file_operations ab8540_gpadc_bat_ctrl_and_ibat_fops = {
1800 .open = ab8540_gpadc_bat_ctrl_and_ibat_open,
1801 .read = seq_read,
1802 .llseek = seq_lseek,
1803 .release = single_release,
1804 .owner = THIS_MODULE,
1805};
1806
1807static int ab8540_gpadc_vbat_meas_and_ibat_print(struct seq_file *s, void *p)
1808{
1809 int vbat_meas_raw;
1810 int vbat_meas_convert;
1811 int ibat_raw;
1812 int ibat_convert;
1813 struct ab8500_gpadc *gpadc;
1814
1815 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1816 vbat_meas_raw = ab8500_gpadc_double_read_raw(gpadc, VBAT_MEAS_AND_IBAT,
1817 avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw);
1818 vbat_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
1819 vbat_meas_raw);
1820 ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
1821 ibat_raw);
1822
1823 return seq_printf(s, "%d,0x%X\n" "%d,0x%X\n",
1824 vbat_meas_convert, vbat_meas_raw,
1825 ibat_convert, ibat_raw);
1826}
1827
1828static int ab8540_gpadc_vbat_meas_and_ibat_open(struct inode *inode,
1829 struct file *file)
1830{
1831 return single_open(file, ab8540_gpadc_vbat_meas_and_ibat_print,
1832 inode->i_private);
1833}
1834
1835static const struct file_operations ab8540_gpadc_vbat_meas_and_ibat_fops = {
1836 .open = ab8540_gpadc_vbat_meas_and_ibat_open,
1837 .read = seq_read,
1838 .llseek = seq_lseek,
1839 .release = single_release,
1840 .owner = THIS_MODULE,
1841};
1842
1843static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s, void *p)
1844{
1845 int vbat_true_meas_raw;
1846 int vbat_true_meas_convert;
1847 int ibat_raw;
1848 int ibat_convert;
1849 struct ab8500_gpadc *gpadc;
1850
1851 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1852 vbat_true_meas_raw = ab8500_gpadc_double_read_raw(gpadc,
1853 VBAT_TRUE_MEAS_AND_IBAT, avg_sample, trig_edge,
1854 trig_timer, conv_type, &ibat_raw);
1855 vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc,
1856 VBAT_TRUE_MEAS, vbat_true_meas_raw);
1857 ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
1858 ibat_raw);
1859
1860 return seq_printf(s, "%d,0x%X\n" "%d,0x%X\n",
1861 vbat_true_meas_convert, vbat_true_meas_raw,
1862 ibat_convert, ibat_raw);
1863}
1864
1865static int ab8540_gpadc_vbat_true_meas_and_ibat_open(struct inode *inode,
1866 struct file *file)
1867{
1868 return single_open(file, ab8540_gpadc_vbat_true_meas_and_ibat_print,
1869 inode->i_private);
1870}
1871
1872static const struct file_operations ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
1873 .open = ab8540_gpadc_vbat_true_meas_and_ibat_open,
1874 .read = seq_read,
1875 .llseek = seq_lseek,
1876 .release = single_release,
1877 .owner = THIS_MODULE,
1878};
1879
1880static int ab8540_gpadc_bat_temp_and_ibat_print(struct seq_file *s, void *p)
1881{
1882 int bat_temp_raw;
1883 int bat_temp_convert;
1884 int ibat_raw;
1885 int ibat_convert;
1886 struct ab8500_gpadc *gpadc;
1887
1888 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1889 bat_temp_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_TEMP_AND_IBAT,
1890 avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw);
1891 bat_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
1892 bat_temp_raw);
1893 ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL,
1894 ibat_raw);
1895
1896 return seq_printf(s, "%d,0x%X\n" "%d,0x%X\n",
1897 bat_temp_convert, bat_temp_raw,
1898 ibat_convert, ibat_raw);
1899}
1900
1901static int ab8540_gpadc_bat_temp_and_ibat_open(struct inode *inode,
1902 struct file *file)
1903{
1904 return single_open(file, ab8540_gpadc_bat_temp_and_ibat_print,
1905 inode->i_private);
1906}
1907
1908static const struct file_operations ab8540_gpadc_bat_temp_and_ibat_fops = {
1909 .open = ab8540_gpadc_bat_temp_and_ibat_open,
1910 .read = seq_read,
1911 .llseek = seq_lseek,
1912 .release = single_release,
1913 .owner = THIS_MODULE,
1914};
1915
1916static int ab8540_gpadc_otp_cal_print(struct seq_file *s, void *p)
1917{
1918 struct ab8500_gpadc *gpadc;
1919 u16 vmain_l, vmain_h, btemp_l, btemp_h;
1920 u16 vbat_l, vbat_h, ibat_l, ibat_h;
1921
1922 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1923 ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h,
1924 &vbat_l, &vbat_h, &ibat_l, &ibat_h);
1925 return seq_printf(s, "VMAIN_L:0x%X\n"
1926 "VMAIN_H:0x%X\n"
1927 "BTEMP_L:0x%X\n"
1928 "BTEMP_H:0x%X\n"
1929 "VBAT_L:0x%X\n"
1930 "VBAT_H:0x%X\n"
1931 "IBAT_L:0x%X\n"
1932 "IBAT_H:0x%X\n"
1933 ,
1934 vmain_l,
1935 vmain_h,
1936 btemp_l,
1937 btemp_h,
1938 vbat_l,
1939 vbat_h,
1940 ibat_l,
1941 ibat_h);
1942}
1943
1944static int ab8540_gpadc_otp_cal_open(struct inode *inode, struct file *file)
1945{
1946 return single_open(file, ab8540_gpadc_otp_cal_print, inode->i_private);
1947}
1948
1949static const struct file_operations ab8540_gpadc_otp_calib_fops = {
1950 .open = ab8540_gpadc_otp_cal_open,
1951 .read = seq_read,
1952 .llseek = seq_lseek,
1953 .release = single_release,
1954 .owner = THIS_MODULE,
1955};
1956
Lee Jones73482342013-02-26 10:06:55 +00001957static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p)
1958{
1959 return seq_printf(s, "%d\n", avg_sample);
1960}
1961
1962static int ab8500_gpadc_avg_sample_open(struct inode *inode, struct file *file)
1963{
1964 return single_open(file, ab8500_gpadc_avg_sample_print,
1965 inode->i_private);
1966}
1967
1968static ssize_t ab8500_gpadc_avg_sample_write(struct file *file,
1969 const char __user *user_buf,
1970 size_t count, loff_t *ppos)
1971{
1972 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1973 char buf[32];
1974 int buf_size;
1975 unsigned long user_avg_sample;
1976 int err;
1977
1978 /* Get userspace string and assure termination */
1979 buf_size = min(count, (sizeof(buf) - 1));
1980 if (copy_from_user(buf, user_buf, buf_size))
1981 return -EFAULT;
1982 buf[buf_size] = 0;
1983
1984 err = strict_strtoul(buf, 0, &user_avg_sample);
1985 if (err)
1986 return -EINVAL;
1987 if ((user_avg_sample == SAMPLE_1) || (user_avg_sample == SAMPLE_4)
1988 || (user_avg_sample == SAMPLE_8)
1989 || (user_avg_sample == SAMPLE_16)) {
1990 avg_sample = (u8) user_avg_sample;
1991 } else {
1992 dev_err(dev, "debugfs error input: "
1993 "should be egal to 1, 4, 8 or 16\n");
1994 return -EINVAL;
1995 }
1996 return buf_size;
1997}
1998
1999static const struct file_operations ab8500_gpadc_avg_sample_fops = {
2000 .open = ab8500_gpadc_avg_sample_open,
2001 .read = seq_read,
2002 .write = ab8500_gpadc_avg_sample_write,
2003 .llseek = seq_lseek,
2004 .release = single_release,
2005 .owner = THIS_MODULE,
2006};
2007
2008static int ab8500_gpadc_trig_edge_print(struct seq_file *s, void *p)
2009{
2010 return seq_printf(s, "%d\n", trig_edge);
2011}
2012
2013static int ab8500_gpadc_trig_edge_open(struct inode *inode, struct file *file)
2014{
2015 return single_open(file, ab8500_gpadc_trig_edge_print,
2016 inode->i_private);
2017}
2018
2019static ssize_t ab8500_gpadc_trig_edge_write(struct file *file,
2020 const char __user *user_buf,
2021 size_t count, loff_t *ppos)
2022{
2023 struct device *dev = ((struct seq_file *)(file->private_data))->private;
2024 char buf[32];
2025 int buf_size;
2026 unsigned long user_trig_edge;
2027 int err;
2028
2029 /* Get userspace string and assure termination */
2030 buf_size = min(count, (sizeof(buf) - 1));
2031 if (copy_from_user(buf, user_buf, buf_size))
2032 return -EFAULT;
2033 buf[buf_size] = 0;
2034
2035 err = strict_strtoul(buf, 0, &user_trig_edge);
2036 if (err)
2037 return -EINVAL;
2038 if ((user_trig_edge == RISING_EDGE)
2039 || (user_trig_edge == FALLING_EDGE)) {
2040 trig_edge = (u8) user_trig_edge;
2041 } else {
2042 dev_err(dev, "Wrong input:\n"
2043 "Enter 0. Rising edge\n"
2044 "Enter 1. Falling edge\n");
2045 return -EINVAL;
2046 }
2047 return buf_size;
2048}
2049
2050static const struct file_operations ab8500_gpadc_trig_edge_fops = {
2051 .open = ab8500_gpadc_trig_edge_open,
2052 .read = seq_read,
2053 .write = ab8500_gpadc_trig_edge_write,
2054 .llseek = seq_lseek,
2055 .release = single_release,
2056 .owner = THIS_MODULE,
2057};
2058
2059static int ab8500_gpadc_trig_timer_print(struct seq_file *s, void *p)
2060{
2061 return seq_printf(s, "%d\n", trig_timer);
2062}
2063
2064static int ab8500_gpadc_trig_timer_open(struct inode *inode, struct file *file)
2065{
2066 return single_open(file, ab8500_gpadc_trig_timer_print,
2067 inode->i_private);
2068}
2069
2070static ssize_t ab8500_gpadc_trig_timer_write(struct file *file,
2071 const char __user *user_buf,
2072 size_t count, loff_t *ppos)
2073{
2074 struct device *dev = ((struct seq_file *)(file->private_data))->private;
2075 char buf[32];
2076 int buf_size;
2077 unsigned long user_trig_timer;
2078 int err;
2079
2080 /* Get userspace string and assure termination */
2081 buf_size = min(count, (sizeof(buf) - 1));
2082 if (copy_from_user(buf, user_buf, buf_size))
2083 return -EFAULT;
2084 buf[buf_size] = 0;
2085
2086 err = strict_strtoul(buf, 0, &user_trig_timer);
2087 if (err)
2088 return -EINVAL;
2089 if ((user_trig_timer >= 0) && (user_trig_timer <= 255)) {
2090 trig_timer = (u8) user_trig_timer;
2091 } else {
2092 dev_err(dev, "debugfs error input: "
2093 "should be beetween 0 to 255\n");
2094 return -EINVAL;
2095 }
2096 return buf_size;
2097}
2098
2099static const struct file_operations ab8500_gpadc_trig_timer_fops = {
2100 .open = ab8500_gpadc_trig_timer_open,
2101 .read = seq_read,
2102 .write = ab8500_gpadc_trig_timer_write,
2103 .llseek = seq_lseek,
2104 .release = single_release,
2105 .owner = THIS_MODULE,
2106};
2107
2108static int ab8500_gpadc_conv_type_print(struct seq_file *s, void *p)
2109{
2110 return seq_printf(s, "%d\n", conv_type);
2111}
2112
2113static int ab8500_gpadc_conv_type_open(struct inode *inode, struct file *file)
2114{
2115 return single_open(file, ab8500_gpadc_conv_type_print,
2116 inode->i_private);
2117}
2118
2119static ssize_t ab8500_gpadc_conv_type_write(struct file *file,
2120 const char __user *user_buf,
2121 size_t count, loff_t *ppos)
2122{
2123 struct device *dev = ((struct seq_file *)(file->private_data))->private;
2124 char buf[32];
2125 int buf_size;
2126 unsigned long user_conv_type;
2127 int err;
2128
2129 /* Get userspace string and assure termination */
2130 buf_size = min(count, (sizeof(buf) - 1));
2131 if (copy_from_user(buf, user_buf, buf_size))
2132 return -EFAULT;
2133 buf[buf_size] = 0;
2134
2135 err = strict_strtoul(buf, 0, &user_conv_type);
2136 if (err)
2137 return -EINVAL;
2138 if ((user_conv_type == ADC_SW)
2139 || (user_conv_type == ADC_HW)) {
2140 conv_type = (u8) user_conv_type;
2141 } else {
2142 dev_err(dev, "Wrong input:\n"
2143 "Enter 0. ADC SW conversion\n"
2144 "Enter 1. ADC HW conversion\n");
2145 return -EINVAL;
2146 }
2147 return buf_size;
2148}
2149
2150static const struct file_operations ab8500_gpadc_conv_type_fops = {
2151 .open = ab8500_gpadc_conv_type_open,
2152 .read = seq_read,
2153 .write = ab8500_gpadc_conv_type_write,
2154 .llseek = seq_lseek,
2155 .release = single_release,
2156 .owner = THIS_MODULE,
2157};
2158
carriere etienne0fbce762011-04-08 16:26:36 +02002159/*
2160 * return length of an ASCII numerical value, 0 is string is not a
2161 * numerical value.
2162 * string shall start at value 1st char.
2163 * string can be tailed with \0 or space or newline chars only.
2164 * value can be decimal or hexadecimal (prefixed 0x or 0X).
2165 */
2166static int strval_len(char *b)
2167{
2168 char *s = b;
2169 if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) {
2170 s += 2;
2171 for (; *s && (*s != ' ') && (*s != '\n'); s++) {
2172 if (!isxdigit(*s))
2173 return 0;
2174 }
2175 } else {
2176 if (*s == '-')
2177 s++;
2178 for (; *s && (*s != ' ') && (*s != '\n'); s++) {
2179 if (!isdigit(*s))
2180 return 0;
2181 }
2182 }
2183 return (int) (s-b);
2184}
2185
2186/*
2187 * parse hwreg input data.
2188 * update global hwreg_cfg only if input data syntax is ok.
2189 */
2190static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
2191 struct device *dev)
2192{
2193 uint write, val = 0;
2194 u8 regvalue;
2195 int ret;
2196 struct hwreg_cfg loc = {
2197 .bank = 0, /* default: invalid phys addr */
2198 .addr = 0, /* default: invalid phys addr */
2199 .fmt = 0, /* default: 32bit access, hex output */
2200 .mask = 0xFFFFFFFF, /* default: no mask */
2201 .shift = 0, /* default: no bit shift */
2202 };
2203
2204 /* read or write ? */
2205 if (!strncmp(b, "read ", 5)) {
2206 write = 0;
2207 b += 5;
2208 } else if (!strncmp(b, "write ", 6)) {
2209 write = 1;
2210 b += 6;
2211 } else
2212 return -EINVAL;
2213
2214 /* OPTIONS -l|-w|-b -s -m -o */
2215 while ((*b == ' ') || (*b == '-')) {
2216 if (*(b-1) != ' ') {
2217 b++;
2218 continue;
2219 }
2220 if ((!strncmp(b, "-d ", 3)) ||
2221 (!strncmp(b, "-dec ", 5))) {
2222 b += (*(b+2) == ' ') ? 3 : 5;
2223 loc.fmt |= (1<<0);
2224 } else if ((!strncmp(b, "-h ", 3)) ||
2225 (!strncmp(b, "-hex ", 5))) {
2226 b += (*(b+2) == ' ') ? 3 : 5;
2227 loc.fmt &= ~(1<<0);
2228 } else if ((!strncmp(b, "-m ", 3)) ||
2229 (!strncmp(b, "-mask ", 6))) {
2230 b += (*(b+2) == ' ') ? 3 : 6;
2231 if (strval_len(b) == 0)
2232 return -EINVAL;
2233 loc.mask = simple_strtoul(b, &b, 0);
2234 } else if ((!strncmp(b, "-s ", 3)) ||
2235 (!strncmp(b, "-shift ", 7))) {
2236 b += (*(b+2) == ' ') ? 3 : 7;
2237 if (strval_len(b) == 0)
2238 return -EINVAL;
2239 loc.shift = simple_strtol(b, &b, 0);
2240 } else {
2241 return -EINVAL;
2242 }
2243 }
2244 /* get arg BANK and ADDRESS */
2245 if (strval_len(b) == 0)
2246 return -EINVAL;
2247 loc.bank = simple_strtoul(b, &b, 0);
2248 while (*b == ' ')
2249 b++;
2250 if (strval_len(b) == 0)
2251 return -EINVAL;
2252 loc.addr = simple_strtoul(b, &b, 0);
2253
2254 if (write) {
2255 while (*b == ' ')
2256 b++;
2257 if (strval_len(b) == 0)
2258 return -EINVAL;
2259 val = simple_strtoul(b, &b, 0);
2260 }
2261
2262 /* args are ok, update target cfg (mainly for read) */
2263 *cfg = loc;
2264
2265#ifdef ABB_HWREG_DEBUG
2266 pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d"
2267 "value=0x%X\n", (write) ? "write" : "read",
2268 REG_FMT_DEC(cfg) ? "decimal" : "hexa",
2269 cfg->addr, cfg->mask, cfg->shift, val);
2270#endif
2271
2272 if (!write)
2273 return 0;
2274
2275 ret = abx500_get_register_interruptible(dev,
2276 (u8)cfg->bank, (u8)cfg->addr, &regvalue);
2277 if (ret < 0) {
2278 dev_err(dev, "abx500_get_reg fail %d, %d\n",
2279 ret, __LINE__);
2280 return -EINVAL;
2281 }
2282
2283 if (cfg->shift >= 0) {
2284 regvalue &= ~(cfg->mask << (cfg->shift));
2285 val = (val & cfg->mask) << (cfg->shift);
2286 } else {
2287 regvalue &= ~(cfg->mask >> (-cfg->shift));
2288 val = (val & cfg->mask) >> (-cfg->shift);
2289 }
2290 val = val | regvalue;
2291
2292 ret = abx500_set_register_interruptible(dev,
2293 (u8)cfg->bank, (u8)cfg->addr, (u8)val);
2294 if (ret < 0) {
2295 pr_err("abx500_set_reg failed %d, %d", ret, __LINE__);
2296 return -EINVAL;
2297 }
2298
2299 return 0;
2300}
2301
2302static ssize_t ab8500_hwreg_write(struct file *file,
2303 const char __user *user_buf, size_t count, loff_t *ppos)
2304{
2305 struct device *dev = ((struct seq_file *)(file->private_data))->private;
2306 char buf[128];
2307 int buf_size, ret;
2308
2309 /* Get userspace string and assure termination */
2310 buf_size = min(count, (sizeof(buf)-1));
2311 if (copy_from_user(buf, user_buf, buf_size))
2312 return -EFAULT;
2313 buf[buf_size] = 0;
2314
2315 /* get args and process */
2316 ret = hwreg_common_write(buf, &hwreg_cfg, dev);
2317 return (ret) ? ret : buf_size;
2318}
2319
2320/*
2321 * - irq subscribe/unsubscribe stuff
2322 */
Lee Jones4b8ac082013-01-14 16:10:36 +00002323static int ab8500_subscribe_unsubscribe_print(struct seq_file *s, void *p)
2324{
2325 seq_printf(s, "%d\n", irq_first);
2326
2327 return 0;
2328}
2329
2330static int ab8500_subscribe_unsubscribe_open(struct inode *inode,
2331 struct file *file)
2332{
2333 return single_open(file, ab8500_subscribe_unsubscribe_print,
2334 inode->i_private);
2335}
2336
2337/*
Mattias Wallin0b337e72010-11-19 17:55:11 +01002338 * Userspace should use poll() on this file. When an event occur
Lee Jones4b8ac082013-01-14 16:10:36 +00002339 * the blocking poll will be released.
2340 */
2341static ssize_t show_irq(struct device *dev,
2342 struct device_attribute *attr, char *buf)
2343{
Mattias Wallin0b337e72010-11-19 17:55:11 +01002344 unsigned long name;
2345 unsigned int irq_index;
2346 int err;
Lee Jones4b8ac082013-01-14 16:10:36 +00002347
Mattias Wallin0b337e72010-11-19 17:55:11 +01002348 err = strict_strtoul(attr->attr.name, 0, &name);
2349 if (err)
2350 return err;
2351
2352 irq_index = name - irq_first;
Linus Walleijddba25f2012-02-03 11:19:05 +01002353 if (irq_index >= num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +01002354 return -EINVAL;
2355 else
2356 return sprintf(buf, "%u\n", irq_count[irq_index]);
2357}
Lee Jones4b8ac082013-01-14 16:10:36 +00002358
2359static ssize_t ab8500_subscribe_write(struct file *file,
2360 const char __user *user_buf,
2361 size_t count, loff_t *ppos)
2362{
2363 struct device *dev = ((struct seq_file *)(file->private_data))->private;
2364 char buf[32];
2365 int buf_size;
2366 unsigned long user_val;
2367 int err;
Mattias Wallin0b337e72010-11-19 17:55:11 +01002368 unsigned int irq_index;
Lee Jones4b8ac082013-01-14 16:10:36 +00002369
2370 /* Get userspace string and assure termination */
2371 buf_size = min(count, (sizeof(buf)-1));
2372 if (copy_from_user(buf, user_buf, buf_size))
2373 return -EFAULT;
2374 buf[buf_size] = 0;
2375
2376 err = strict_strtoul(buf, 0, &user_val);
2377 if (err)
2378 return -EINVAL;
2379 if (user_val < irq_first) {
2380 dev_err(dev, "debugfs error input < %d\n", irq_first);
2381 return -EINVAL;
2382 }
2383 if (user_val > irq_last) {
2384 dev_err(dev, "debugfs error input > %d\n", irq_last);
2385 return -EINVAL;
2386 }
2387
Mattias Wallin0b337e72010-11-19 17:55:11 +01002388 irq_index = user_val - irq_first;
Linus Walleijddba25f2012-02-03 11:19:05 +01002389 if (irq_index >= num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +01002390 return -EINVAL;
2391
Lee Jones4b8ac082013-01-14 16:10:36 +00002392 /*
Mattias Wallin0b337e72010-11-19 17:55:11 +01002393 * This will create a sysfs file named <irq-nr> which userspace can
Lee Jones4b8ac082013-01-14 16:10:36 +00002394 * use to select or poll and get the AB8500 events
2395 */
Mattias Wallin0b337e72010-11-19 17:55:11 +01002396 dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute),
2397 GFP_KERNEL);
2398 event_name[irq_index] = kmalloc(buf_size, GFP_KERNEL);
2399 sprintf(event_name[irq_index], "%lu", user_val);
2400 dev_attr[irq_index]->show = show_irq;
2401 dev_attr[irq_index]->store = NULL;
2402 dev_attr[irq_index]->attr.name = event_name[irq_index];
2403 dev_attr[irq_index]->attr.mode = S_IRUGO;
2404 err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr);
Lee Jones4b8ac082013-01-14 16:10:36 +00002405 if (err < 0) {
2406 printk(KERN_ERR "sysfs_create_file failed %d\n", err);
2407 return err;
2408 }
2409
2410 err = request_threaded_irq(user_val, NULL, ab8500_debug_handler,
2411 IRQF_SHARED | IRQF_NO_SUSPEND,
2412 "ab8500-debug", &dev->kobj);
2413 if (err < 0) {
2414 printk(KERN_ERR "request_threaded_irq failed %d, %lu\n",
2415 err, user_val);
Mattias Wallin0b337e72010-11-19 17:55:11 +01002416 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
Lee Jones4b8ac082013-01-14 16:10:36 +00002417 return err;
2418 }
2419
2420 return buf_size;
2421}
2422
2423static ssize_t ab8500_unsubscribe_write(struct file *file,
2424 const char __user *user_buf,
2425 size_t count, loff_t *ppos)
2426{
2427 struct device *dev = ((struct seq_file *)(file->private_data))->private;
2428 char buf[32];
2429 int buf_size;
2430 unsigned long user_val;
2431 int err;
Mattias Wallin0b337e72010-11-19 17:55:11 +01002432 unsigned int irq_index;
Lee Jones4b8ac082013-01-14 16:10:36 +00002433
2434 /* Get userspace string and assure termination */
2435 buf_size = min(count, (sizeof(buf)-1));
2436 if (copy_from_user(buf, user_buf, buf_size))
2437 return -EFAULT;
2438 buf[buf_size] = 0;
2439
2440 err = strict_strtoul(buf, 0, &user_val);
2441 if (err)
2442 return -EINVAL;
2443 if (user_val < irq_first) {
2444 dev_err(dev, "debugfs error input < %d\n", irq_first);
2445 return -EINVAL;
2446 }
2447 if (user_val > irq_last) {
2448 dev_err(dev, "debugfs error input > %d\n", irq_last);
2449 return -EINVAL;
2450 }
2451
Mattias Wallin0b337e72010-11-19 17:55:11 +01002452 irq_index = user_val - irq_first;
Linus Walleijddba25f2012-02-03 11:19:05 +01002453 if (irq_index >= num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +01002454 return -EINVAL;
Lee Jones4b8ac082013-01-14 16:10:36 +00002455
Mattias Wallin0b337e72010-11-19 17:55:11 +01002456 /* Set irq count to 0 when unsubscribe */
2457 irq_count[irq_index] = 0;
2458
2459 if (dev_attr[irq_index])
2460 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
2461
2462
2463 free_irq(user_val, &dev->kobj);
2464 kfree(event_name[irq_index]);
2465 kfree(dev_attr[irq_index]);
Lee Jones4b8ac082013-01-14 16:10:36 +00002466
2467 return buf_size;
2468}
2469
carriere etienne0fbce762011-04-08 16:26:36 +02002470/*
2471 * - several deubgfs nodes fops
2472 */
2473
Mattias Wallin5814fc32010-09-13 16:05:04 +02002474static const struct file_operations ab8500_bank_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01002475 .open = ab8500_bank_open,
2476 .write = ab8500_bank_write,
2477 .read = seq_read,
2478 .llseek = seq_lseek,
2479 .release = single_release,
2480 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02002481};
2482
2483static const struct file_operations ab8500_address_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01002484 .open = ab8500_address_open,
2485 .write = ab8500_address_write,
2486 .read = seq_read,
2487 .llseek = seq_lseek,
2488 .release = single_release,
2489 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02002490};
2491
2492static const struct file_operations ab8500_val_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01002493 .open = ab8500_val_open,
2494 .write = ab8500_val_write,
2495 .read = seq_read,
2496 .llseek = seq_lseek,
2497 .release = single_release,
2498 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02002499};
2500
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01002501static const struct file_operations ab8500_interrupts_fops = {
2502 .open = ab8500_interrupts_open,
2503 .read = seq_read,
2504 .llseek = seq_lseek,
2505 .release = single_release,
2506 .owner = THIS_MODULE,
2507};
2508
Lee Jones4b8ac082013-01-14 16:10:36 +00002509static const struct file_operations ab8500_subscribe_fops = {
2510 .open = ab8500_subscribe_unsubscribe_open,
2511 .write = ab8500_subscribe_write,
2512 .read = seq_read,
2513 .llseek = seq_lseek,
2514 .release = single_release,
2515 .owner = THIS_MODULE,
2516};
2517
2518static const struct file_operations ab8500_unsubscribe_fops = {
2519 .open = ab8500_subscribe_unsubscribe_open,
2520 .write = ab8500_unsubscribe_write,
2521 .read = seq_read,
2522 .llseek = seq_lseek,
2523 .release = single_release,
2524 .owner = THIS_MODULE,
2525};
2526
carriere etienne0fbce762011-04-08 16:26:36 +02002527static const struct file_operations ab8500_hwreg_fops = {
2528 .open = ab8500_hwreg_open,
2529 .write = ab8500_hwreg_write,
2530 .read = seq_read,
2531 .llseek = seq_lseek,
2532 .release = single_release,
2533 .owner = THIS_MODULE,
2534};
2535
Mattias Wallin5814fc32010-09-13 16:05:04 +02002536static struct dentry *ab8500_dir;
John Beckett1478a312011-05-31 13:54:27 +01002537static struct dentry *ab8500_gpadc_dir;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002538
Bill Pembertonf791be42012-11-19 13:23:04 -05002539static int ab8500_debug_probe(struct platform_device *plf)
Mattias Wallin5814fc32010-09-13 16:05:04 +02002540{
carriere etienne0fbce762011-04-08 16:26:36 +02002541 struct dentry *file;
Linus Walleijddba25f2012-02-03 11:19:05 +01002542 int ret = -ENOMEM;
2543 struct ab8500 *ab8500;
Mattias Wallind7b9f322010-11-26 13:06:39 +01002544 debug_bank = AB8500_MISC;
2545 debug_address = AB8500_REV_REG & 0x00FF;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002546
Linus Walleijddba25f2012-02-03 11:19:05 +01002547 ab8500 = dev_get_drvdata(plf->dev.parent);
2548 num_irqs = ab8500->mask_size;
2549
Ashok G70bad042012-02-28 10:21:00 +05302550 irq_count = kzalloc(sizeof(*irq_count)*num_irqs, GFP_KERNEL);
Linus Walleijddba25f2012-02-03 11:19:05 +01002551 if (!irq_count)
2552 return -ENOMEM;
2553
2554 dev_attr = kzalloc(sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
2555 if (!dev_attr)
2556 goto out_freeirq_count;
2557
2558 event_name = kzalloc(sizeof(*event_name)*num_irqs, GFP_KERNEL);
2559 if (!event_name)
2560 goto out_freedev_attr;
2561
Lee Jones4b8ac082013-01-14 16:10:36 +00002562 irq_first = platform_get_irq_byname(plf, "IRQ_FIRST");
2563 if (irq_first < 0) {
2564 dev_err(&plf->dev, "First irq not found, err %d\n",
John Beckett1478a312011-05-31 13:54:27 +01002565 irq_first);
Linus Walleijddba25f2012-02-03 11:19:05 +01002566 ret = irq_first;
2567 goto out_freeevent_name;
Lee Jones4b8ac082013-01-14 16:10:36 +00002568 }
2569
2570 irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
2571 if (irq_last < 0) {
2572 dev_err(&plf->dev, "Last irq not found, err %d\n",
John Beckett1478a312011-05-31 13:54:27 +01002573 irq_last);
Linus Walleijddba25f2012-02-03 11:19:05 +01002574 ret = irq_last;
Jonas Aaberg2cf64e22012-05-31 07:57:07 +02002575 goto out_freeevent_name;
Lee Jones4b8ac082013-01-14 16:10:36 +00002576 }
2577
Mattias Wallind7b9f322010-11-26 13:06:39 +01002578 ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
2579 if (!ab8500_dir)
carriere etienne0fbce762011-04-08 16:26:36 +02002580 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002581
John Beckett1478a312011-05-31 13:54:27 +01002582 ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING,
2583 ab8500_dir);
2584 if (!ab8500_gpadc_dir)
2585 goto err;
2586
2587 file = debugfs_create_file("all-bank-registers", S_IRUGO,
2588 ab8500_dir, &plf->dev, &ab8500_registers_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02002589 if (!file)
2590 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002591
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +01002592 file = debugfs_create_file("all-banks", S_IRUGO,
2593 ab8500_dir, &plf->dev, &ab8500_all_banks_fops);
2594 if (!file)
2595 goto err;
2596
John Beckett1478a312011-05-31 13:54:27 +01002597 file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR),
2598 ab8500_dir, &plf->dev, &ab8500_bank_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02002599 if (!file)
2600 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002601
John Beckett1478a312011-05-31 13:54:27 +01002602 file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR),
2603 ab8500_dir, &plf->dev, &ab8500_address_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02002604 if (!file)
2605 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002606
John Beckett1478a312011-05-31 13:54:27 +01002607 file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR),
2608 ab8500_dir, &plf->dev, &ab8500_val_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02002609 if (!file)
2610 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002611
John Beckett1478a312011-05-31 13:54:27 +01002612 file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR),
2613 ab8500_dir, &plf->dev, &ab8500_subscribe_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02002614 if (!file)
2615 goto err;
Lee Jones4b8ac082013-01-14 16:10:36 +00002616
Lee Jones9581ae32012-07-06 16:11:50 +02002617 if (is_ab8500(ab8500)) {
2618 debug_ranges = ab8500_debug_ranges;
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01002619 num_interrupt_lines = AB8500_NR_IRQS;
Lee Jones9581ae32012-07-06 16:11:50 +02002620 } else if (is_ab8505(ab8500)) {
2621 debug_ranges = ab8505_debug_ranges;
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01002622 num_interrupt_lines = AB8505_NR_IRQS;
Lee Jones9581ae32012-07-06 16:11:50 +02002623 } else if (is_ab9540(ab8500)) {
2624 debug_ranges = ab8505_debug_ranges;
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01002625 num_interrupt_lines = AB9540_NR_IRQS;
Lee Jones9581ae32012-07-06 16:11:50 +02002626 } else if (is_ab8540(ab8500)) {
2627 debug_ranges = ab8505_debug_ranges;
Lee Jonese436ddf2013-02-26 10:09:41 +00002628 num_interrupt_lines = AB8540_NR_IRQS;
Lee Jones9581ae32012-07-06 16:11:50 +02002629 }
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01002630
2631 file = debugfs_create_file("interrupts", (S_IRUGO),
2632 ab8500_dir, &plf->dev, &ab8500_interrupts_fops);
2633 if (!file)
2634 goto err;
2635
John Beckett1478a312011-05-31 13:54:27 +01002636 file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR),
2637 ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02002638 if (!file)
2639 goto err;
2640
John Beckett1478a312011-05-31 13:54:27 +01002641 file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR),
2642 ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
2643 if (!file)
2644 goto err;
2645
Lee Jonesc7ebaee2013-02-26 14:03:33 +00002646 file = debugfs_create_file("all-modem-registers", (S_IRUGO | S_IWUGO),
2647 ab8500_dir, &plf->dev, &ab8500_modem_fops);
2648 if (!file)
2649 goto err;
2650
John Beckett1478a312011-05-31 13:54:27 +01002651 file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR),
2652 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops);
2653 if (!file)
2654 goto err;
2655
2656 file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR),
2657 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops);
2658 if (!file)
2659 goto err;
2660
2661 file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR),
2662 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops);
2663 if (!file)
2664 goto err;
2665
2666 file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR),
2667 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops);
2668 if (!file)
2669 goto err;
2670
2671 file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR),
2672 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops);
2673 if (!file)
2674 goto err;
2675
2676 file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR),
2677 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops);
2678 if (!file)
2679 goto err;
2680
2681 file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR),
2682 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops);
2683 if (!file)
2684 goto err;
2685
2686 file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR),
2687 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops);
2688 if (!file)
2689 goto err;
2690
2691 file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR),
2692 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops);
2693 if (!file)
2694 goto err;
2695
2696 file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR),
2697 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops);
2698 if (!file)
2699 goto err;
2700
2701 file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR),
2702 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
2703 if (!file)
2704 goto err;
2705
2706 file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR),
2707 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops);
2708 if (!file)
2709 goto err;
2710
2711 file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR),
2712 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02002713 if (!file)
2714 goto err;
Lee Jonesbc6b4132013-02-26 14:02:31 +00002715 if (is_ab8540(ab8500)) {
2716 file = debugfs_create_file("xtal_temp", (S_IRUGO | S_IWUGO),
2717 ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_xtal_temp_fops);
2718 if (!file)
2719 goto err;
2720 file = debugfs_create_file("vbattruemeas", (S_IRUGO | S_IWUGO),
2721 ab8500_gpadc_dir, &plf->dev,
2722 &ab8540_gpadc_vbat_true_meas_fops);
2723 if (!file)
2724 goto err;
2725 file = debugfs_create_file("batctrl_and_ibat",
2726 (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
2727 &plf->dev, &ab8540_gpadc_bat_ctrl_and_ibat_fops);
2728 if (!file)
2729 goto err;
2730 file = debugfs_create_file("vbatmeas_and_ibat",
2731 (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
2732 &plf->dev,
2733 &ab8540_gpadc_vbat_meas_and_ibat_fops);
2734 if (!file)
2735 goto err;
2736 file = debugfs_create_file("vbattruemeas_and_ibat",
2737 (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
2738 &plf->dev,
2739 &ab8540_gpadc_vbat_true_meas_and_ibat_fops);
2740 if (!file)
2741 goto err;
2742 file = debugfs_create_file("battemp_and_ibat",
2743 (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
2744 &plf->dev, &ab8540_gpadc_bat_temp_and_ibat_fops);
2745 if (!file)
2746 goto err;
2747 file = debugfs_create_file("otp_calib", (S_IRUGO | S_IWUGO),
2748 ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_otp_calib_fops);
2749 if (!file)
2750 goto err;
2751 }
Lee Jones73482342013-02-26 10:06:55 +00002752 file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUGO),
2753 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_avg_sample_fops);
2754 if (!file)
2755 goto err;
2756
2757 file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUGO),
2758 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_edge_fops);
2759 if (!file)
2760 goto err;
2761
2762 file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUGO),
2763 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_timer_fops);
2764 if (!file)
2765 goto err;
2766
2767 file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUGO),
2768 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_conv_type_fops);
2769 if (!file)
2770 goto err;
2771
Mattias Wallind7b9f322010-11-26 13:06:39 +01002772 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002773
carriere etienne0fbce762011-04-08 16:26:36 +02002774err:
2775 if (ab8500_dir)
2776 debugfs_remove_recursive(ab8500_dir);
Mattias Wallind7b9f322010-11-26 13:06:39 +01002777 dev_err(&plf->dev, "failed to create debugfs entries.\n");
Linus Walleijddba25f2012-02-03 11:19:05 +01002778out_freeevent_name:
2779 kfree(event_name);
2780out_freedev_attr:
2781 kfree(dev_attr);
2782out_freeirq_count:
2783 kfree(irq_count);
2784
2785 return ret;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002786}
2787
Bill Pemberton4740f732012-11-19 13:26:01 -05002788static int ab8500_debug_remove(struct platform_device *plf)
Mattias Wallin5814fc32010-09-13 16:05:04 +02002789{
carriere etienne0fbce762011-04-08 16:26:36 +02002790 debugfs_remove_recursive(ab8500_dir);
Linus Walleijddba25f2012-02-03 11:19:05 +01002791 kfree(event_name);
2792 kfree(dev_attr);
2793 kfree(irq_count);
2794
Mattias Wallind7b9f322010-11-26 13:06:39 +01002795 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002796}
2797
2798static struct platform_driver ab8500_debug_driver = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01002799 .driver = {
2800 .name = "ab8500-debug",
2801 .owner = THIS_MODULE,
2802 },
2803 .probe = ab8500_debug_probe,
Bill Pemberton84449212012-11-19 13:20:24 -05002804 .remove = ab8500_debug_remove
Mattias Wallin5814fc32010-09-13 16:05:04 +02002805};
2806
2807static int __init ab8500_debug_init(void)
2808{
Mattias Wallind7b9f322010-11-26 13:06:39 +01002809 return platform_driver_register(&ab8500_debug_driver);
Mattias Wallin5814fc32010-09-13 16:05:04 +02002810}
2811
2812static void __exit ab8500_debug_exit(void)
2813{
Mattias Wallind7b9f322010-11-26 13:06:39 +01002814 platform_driver_unregister(&ab8500_debug_driver);
Mattias Wallin5814fc32010-09-13 16:05:04 +02002815}
2816subsys_initcall(ab8500_debug_init);
2817module_exit(ab8500_debug_exit);
2818
2819MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
2820MODULE_DESCRIPTION("AB8500 DEBUG");
2821MODULE_LICENSE("GPL v2");