blob: af6f774e658a303d76f5a81a1fb6dac5c3f705b1 [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;
Mattias Wallin0b337e72010-11-19 17:55:11 +010097static u32 irq_count[AB8500_NR_IRQS];
98
99static struct device_attribute *dev_attr[AB8500_NR_IRQS];
100static char *event_name[AB8500_NR_IRQS];
Lee Jones4b8ac082013-01-14 16:10:36 +0000101
Mattias Wallin5814fc32010-09-13 16:05:04 +0200102/**
103 * struct ab8500_reg_range
104 * @first: the first address of the range
105 * @last: the last address of the range
106 * @perm: access permissions for the range
107 */
108struct ab8500_reg_range {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100109 u8 first;
110 u8 last;
111 u8 perm;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200112};
113
114/**
Lee Jones822672a2012-06-20 13:56:38 +0100115 * struct ab8500_prcmu_ranges
Mattias Wallin5814fc32010-09-13 16:05:04 +0200116 * @num_ranges: the number of ranges in the list
117 * @bankid: bank identifier
118 * @range: the list of register ranges
119 */
Lee Jones822672a2012-06-20 13:56:38 +0100120struct ab8500_prcmu_ranges {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100121 u8 num_ranges;
122 u8 bankid;
123 const struct ab8500_reg_range *range;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200124};
125
carriere etienne0fbce762011-04-08 16:26:36 +0200126/* hwreg- "mask" and "shift" entries ressources */
127struct hwreg_cfg {
128 u32 bank; /* target bank */
129 u32 addr; /* target address */
130 uint fmt; /* format */
131 uint mask; /* read/write mask, applied before any bit shift */
132 int shift; /* bit shift (read:right shift, write:left shift */
133};
134/* fmt bit #0: 0=hexa, 1=dec */
135#define REG_FMT_DEC(c) ((c)->fmt & 0x1)
136#define REG_FMT_HEX(c) (!REG_FMT_DEC(c))
137
138static struct hwreg_cfg hwreg_cfg = {
139 .addr = 0, /* default: invalid phys addr */
140 .fmt = 0, /* default: 32bit access, hex output */
141 .mask = 0xFFFFFFFF, /* default: no mask */
142 .shift = 0, /* default: no bit shift */
143};
144
Mattias Wallin5814fc32010-09-13 16:05:04 +0200145#define AB8500_NAME_STRING "ab8500"
John Beckett1478a312011-05-31 13:54:27 +0100146#define AB8500_ADC_NAME_STRING "gpadc"
Philippe Langlais40c064e2011-10-17 09:48:55 +0200147#define AB8500_NUM_BANKS 24
Mattias Wallin5814fc32010-09-13 16:05:04 +0200148
149#define AB8500_REV_REG 0x80
150
Lee Jones822672a2012-06-20 13:56:38 +0100151static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100152 [0x0] = {
153 .num_ranges = 0,
Lee Jonesfad55a82013-01-14 17:17:34 +0000154 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100155 },
156 [AB8500_SYS_CTRL1_BLOCK] = {
157 .num_ranges = 3,
158 .range = (struct ab8500_reg_range[]) {
159 {
160 .first = 0x00,
161 .last = 0x02,
162 },
163 {
164 .first = 0x42,
165 .last = 0x42,
166 },
167 {
168 .first = 0x80,
169 .last = 0x81,
170 },
171 },
172 },
173 [AB8500_SYS_CTRL2_BLOCK] = {
174 .num_ranges = 4,
175 .range = (struct ab8500_reg_range[]) {
176 {
177 .first = 0x00,
178 .last = 0x0D,
179 },
180 {
181 .first = 0x0F,
182 .last = 0x17,
183 },
184 {
185 .first = 0x30,
186 .last = 0x30,
187 },
188 {
189 .first = 0x32,
190 .last = 0x33,
191 },
192 },
193 },
194 [AB8500_REGU_CTRL1] = {
195 .num_ranges = 3,
196 .range = (struct ab8500_reg_range[]) {
197 {
198 .first = 0x00,
199 .last = 0x00,
200 },
201 {
202 .first = 0x03,
203 .last = 0x10,
204 },
205 {
206 .first = 0x80,
207 .last = 0x84,
208 },
209 },
210 },
211 [AB8500_REGU_CTRL2] = {
212 .num_ranges = 5,
213 .range = (struct ab8500_reg_range[]) {
214 {
215 .first = 0x00,
216 .last = 0x15,
217 },
218 {
219 .first = 0x17,
220 .last = 0x19,
221 },
222 {
223 .first = 0x1B,
224 .last = 0x1D,
225 },
226 {
227 .first = 0x1F,
228 .last = 0x22,
229 },
230 {
231 .first = 0x40,
232 .last = 0x44,
233 },
234 /* 0x80-0x8B is SIM registers and should
235 * not be accessed from here */
236 },
237 },
238 [AB8500_USB] = {
239 .num_ranges = 2,
240 .range = (struct ab8500_reg_range[]) {
241 {
242 .first = 0x80,
243 .last = 0x83,
244 },
245 {
246 .first = 0x87,
247 .last = 0x8A,
248 },
249 },
250 },
251 [AB8500_TVOUT] = {
252 .num_ranges = 9,
253 .range = (struct ab8500_reg_range[]) {
254 {
255 .first = 0x00,
256 .last = 0x12,
257 },
258 {
259 .first = 0x15,
260 .last = 0x17,
261 },
262 {
263 .first = 0x19,
264 .last = 0x21,
265 },
266 {
267 .first = 0x27,
268 .last = 0x2C,
269 },
270 {
271 .first = 0x41,
272 .last = 0x41,
273 },
274 {
275 .first = 0x45,
276 .last = 0x5B,
277 },
278 {
279 .first = 0x5D,
280 .last = 0x5D,
281 },
282 {
283 .first = 0x69,
284 .last = 0x69,
285 },
286 {
287 .first = 0x80,
288 .last = 0x81,
289 },
290 },
291 },
292 [AB8500_DBI] = {
293 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000294 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100295 },
296 [AB8500_ECI_AV_ACC] = {
297 .num_ranges = 1,
298 .range = (struct ab8500_reg_range[]) {
299 {
300 .first = 0x80,
301 .last = 0x82,
302 },
303 },
304 },
305 [0x9] = {
306 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000307 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100308 },
309 [AB8500_GPADC] = {
310 .num_ranges = 1,
311 .range = (struct ab8500_reg_range[]) {
312 {
313 .first = 0x00,
314 .last = 0x08,
315 },
316 },
317 },
318 [AB8500_CHARGER] = {
Philippe Langlais40c064e2011-10-17 09:48:55 +0200319 .num_ranges = 9,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100320 .range = (struct ab8500_reg_range[]) {
321 {
322 .first = 0x00,
323 .last = 0x03,
324 },
325 {
326 .first = 0x05,
327 .last = 0x05,
328 },
329 {
330 .first = 0x40,
331 .last = 0x40,
332 },
333 {
334 .first = 0x42,
335 .last = 0x42,
336 },
337 {
338 .first = 0x44,
339 .last = 0x44,
340 },
341 {
342 .first = 0x50,
343 .last = 0x55,
344 },
345 {
346 .first = 0x80,
347 .last = 0x82,
348 },
349 {
350 .first = 0xC0,
351 .last = 0xC2,
352 },
Philippe Langlais40c064e2011-10-17 09:48:55 +0200353 {
354 .first = 0xf5,
355 .last = 0xf6,
356 },
Mattias Wallind7b9f322010-11-26 13:06:39 +0100357 },
358 },
359 [AB8500_GAS_GAUGE] = {
360 .num_ranges = 3,
361 .range = (struct ab8500_reg_range[]) {
362 {
363 .first = 0x00,
364 .last = 0x00,
365 },
366 {
367 .first = 0x07,
368 .last = 0x0A,
369 },
370 {
371 .first = 0x10,
372 .last = 0x14,
373 },
374 },
375 },
Philippe Langlais40c064e2011-10-17 09:48:55 +0200376 [AB8500_DEVELOPMENT] = {
377 .num_ranges = 1,
378 .range = (struct ab8500_reg_range[]) {
379 {
380 .first = 0x00,
381 .last = 0x00,
382 },
383 },
384 },
385 [AB8500_DEBUG] = {
386 .num_ranges = 1,
387 .range = (struct ab8500_reg_range[]) {
388 {
389 .first = 0x05,
390 .last = 0x07,
391 },
392 },
393 },
Mattias Wallind7b9f322010-11-26 13:06:39 +0100394 [AB8500_AUDIO] = {
395 .num_ranges = 1,
396 .range = (struct ab8500_reg_range[]) {
397 {
398 .first = 0x00,
399 .last = 0x6F,
400 },
401 },
402 },
403 [AB8500_INTERRUPT] = {
404 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000405 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100406 },
407 [AB8500_RTC] = {
408 .num_ranges = 1,
409 .range = (struct ab8500_reg_range[]) {
410 {
411 .first = 0x00,
412 .last = 0x0F,
413 },
414 },
415 },
416 [AB8500_MISC] = {
417 .num_ranges = 8,
418 .range = (struct ab8500_reg_range[]) {
419 {
420 .first = 0x00,
421 .last = 0x05,
422 },
423 {
424 .first = 0x10,
425 .last = 0x15,
426 },
427 {
428 .first = 0x20,
429 .last = 0x25,
430 },
431 {
432 .first = 0x30,
433 .last = 0x35,
434 },
435 {
436 .first = 0x40,
437 .last = 0x45,
438 },
439 {
440 .first = 0x50,
441 .last = 0x50,
442 },
443 {
444 .first = 0x60,
445 .last = 0x67,
446 },
447 {
448 .first = 0x80,
449 .last = 0x80,
450 },
451 },
452 },
453 [0x11] = {
454 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000455 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100456 },
457 [0x12] = {
458 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000459 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100460 },
461 [0x13] = {
462 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000463 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100464 },
465 [0x14] = {
466 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000467 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100468 },
469 [AB8500_OTP_EMUL] = {
470 .num_ranges = 1,
471 .range = (struct ab8500_reg_range[]) {
472 {
473 .first = 0x01,
474 .last = 0x0F,
475 },
476 },
477 },
Mattias Wallin5814fc32010-09-13 16:05:04 +0200478};
479
Lee Jones4b8ac082013-01-14 16:10:36 +0000480static irqreturn_t ab8500_debug_handler(int irq, void *data)
481{
482 char buf[16];
483 struct kobject *kobj = (struct kobject *)data;
Mattias Wallin0b337e72010-11-19 17:55:11 +0100484 unsigned int irq_abb = irq - irq_first;
Lee Jones4b8ac082013-01-14 16:10:36 +0000485
Mattias Wallin0b337e72010-11-19 17:55:11 +0100486 if (irq_abb < AB8500_NR_IRQS)
487 irq_count[irq_abb]++;
Lee Jones4b8ac082013-01-14 16:10:36 +0000488 /*
489 * This makes it possible to use poll for events (POLLPRI | POLLERR)
Mattias Wallin0b337e72010-11-19 17:55:11 +0100490 * from userspace on sysfs file named <irq-nr>
Lee Jones4b8ac082013-01-14 16:10:36 +0000491 */
Mattias Wallin0b337e72010-11-19 17:55:11 +0100492 sprintf(buf, "%d", irq);
Lee Jones4b8ac082013-01-14 16:10:36 +0000493 sysfs_notify(kobj, NULL, buf);
494
495 return IRQ_HANDLED;
496}
497
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100498/* Prints to seq_file or log_buf */
499static int ab8500_registers_print(struct device *dev, u32 bank,
500 struct seq_file *s)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200501{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100502 unsigned int i;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200503
Mattias Wallind7b9f322010-11-26 13:06:39 +0100504 for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
505 u32 reg;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200506
Mattias Wallind7b9f322010-11-26 13:06:39 +0100507 for (reg = debug_ranges[bank].range[i].first;
508 reg <= debug_ranges[bank].range[i].last;
509 reg++) {
510 u8 value;
511 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200512
Mattias Wallind7b9f322010-11-26 13:06:39 +0100513 err = abx500_get_register_interruptible(dev,
514 (u8)bank, (u8)reg, &value);
515 if (err < 0) {
516 dev_err(dev, "ab->read fail %d\n", err);
517 return err;
518 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200519
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100520 if (s) {
521 err = seq_printf(s, " [%u/0x%02X]: 0x%02X\n",
522 bank, reg, value);
523 if (err < 0) {
524 dev_err(dev,
525 "seq_printf overflow bank=%d reg=%d\n",
526 bank, reg);
527 /* Error is not returned here since
528 * the output is wanted in any case */
529 return 0;
530 }
531 } else {
532 printk(KERN_INFO" [%u/0x%02X]: 0x%02X\n", bank,
533 reg, value);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100534 }
535 }
536 }
537 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200538}
539
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100540static int ab8500_print_bank_registers(struct seq_file *s, void *p)
541{
542 struct device *dev = s->private;
543 u32 bank = debug_bank;
544
545 seq_printf(s, AB8500_NAME_STRING " register values:\n");
546
547 seq_printf(s, " bank %u:\n", bank);
548
549 ab8500_registers_print(dev, bank, s);
550 return 0;
551}
552
Mattias Wallin5814fc32010-09-13 16:05:04 +0200553static int ab8500_registers_open(struct inode *inode, struct file *file)
554{
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100555 return single_open(file, ab8500_print_bank_registers, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200556}
557
558static const struct file_operations ab8500_registers_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100559 .open = ab8500_registers_open,
560 .read = seq_read,
561 .llseek = seq_lseek,
562 .release = single_release,
563 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +0200564};
565
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100566static int ab8500_print_all_banks(struct seq_file *s, void *p)
567{
568 struct device *dev = s->private;
569 unsigned int i;
570 int err;
571
572 seq_printf(s, AB8500_NAME_STRING " register values:\n");
573
574 for (i = 1; i < AB8500_NUM_BANKS; i++) {
575 err = seq_printf(s, " bank %u:\n", i);
576 if (err < 0)
577 dev_err(dev, "seq_printf overflow, bank=%d\n", i);
578
579 ab8500_registers_print(dev, i, s);
580 }
581 return 0;
582}
583
Mian Yousaf Kaukab1d843a62012-01-27 11:35:41 +0100584/* Dump registers to kernel log */
585void ab8500_dump_all_banks(struct device *dev)
586{
587 unsigned int i;
588
589 printk(KERN_INFO"ab8500 register values:\n");
590
591 for (i = 1; i < AB8500_NUM_BANKS; i++) {
592 printk(KERN_INFO" bank %u:\n", i);
593 ab8500_registers_print(dev, i, NULL);
594 }
595}
596
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100597static int ab8500_all_banks_open(struct inode *inode, struct file *file)
598{
599 struct seq_file *s;
600 int err;
601
602 err = single_open(file, ab8500_print_all_banks, inode->i_private);
603 if (!err) {
604 /* Default buf size in seq_read is not enough */
605 s = (struct seq_file *)file->private_data;
606 s->size = (PAGE_SIZE * 2);
607 s->buf = kmalloc(s->size, GFP_KERNEL);
608 if (!s->buf) {
609 single_release(inode, file);
610 err = -ENOMEM;
611 }
612 }
613 return err;
614}
615
616static const struct file_operations ab8500_all_banks_fops = {
617 .open = ab8500_all_banks_open,
618 .read = seq_read,
619 .llseek = seq_lseek,
620 .release = single_release,
621 .owner = THIS_MODULE,
622};
623
Mattias Wallin5814fc32010-09-13 16:05:04 +0200624static int ab8500_bank_print(struct seq_file *s, void *p)
625{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100626 return seq_printf(s, "%d\n", debug_bank);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200627}
628
629static int ab8500_bank_open(struct inode *inode, struct file *file)
630{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100631 return single_open(file, ab8500_bank_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200632}
633
634static ssize_t ab8500_bank_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100635 const char __user *user_buf,
636 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200637{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100638 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +0100639 unsigned long user_bank;
640 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200641
Mattias Wallind7b9f322010-11-26 13:06:39 +0100642 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +0200643 err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100644 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +0200645 return err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200646
Mattias Wallind7b9f322010-11-26 13:06:39 +0100647 if (user_bank >= AB8500_NUM_BANKS) {
648 dev_err(dev, "debugfs error input > number of banks\n");
649 return -EINVAL;
650 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200651
Mattias Wallind7b9f322010-11-26 13:06:39 +0100652 debug_bank = user_bank;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200653
Peter Huewe8504d632011-06-06 22:43:32 +0200654 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200655}
656
657static int ab8500_address_print(struct seq_file *s, void *p)
658{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100659 return seq_printf(s, "0x%02X\n", debug_address);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200660}
661
662static int ab8500_address_open(struct inode *inode, struct file *file)
663{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100664 return single_open(file, ab8500_address_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200665}
666
667static ssize_t ab8500_address_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100668 const char __user *user_buf,
669 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200670{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100671 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +0100672 unsigned long user_address;
673 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200674
Mattias Wallind7b9f322010-11-26 13:06:39 +0100675 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +0200676 err = kstrtoul_from_user(user_buf, count, 0, &user_address);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100677 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +0200678 return err;
679
Mattias Wallind7b9f322010-11-26 13:06:39 +0100680 if (user_address > 0xff) {
681 dev_err(dev, "debugfs error input > 0xff\n");
682 return -EINVAL;
683 }
684 debug_address = user_address;
Peter Huewe8504d632011-06-06 22:43:32 +0200685 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200686}
687
688static int ab8500_val_print(struct seq_file *s, void *p)
689{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100690 struct device *dev = s->private;
691 int ret;
692 u8 regvalue;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200693
Mattias Wallind7b9f322010-11-26 13:06:39 +0100694 ret = abx500_get_register_interruptible(dev,
695 (u8)debug_bank, (u8)debug_address, &regvalue);
696 if (ret < 0) {
697 dev_err(dev, "abx500_get_reg fail %d, %d\n",
698 ret, __LINE__);
699 return -EINVAL;
700 }
701 seq_printf(s, "0x%02X\n", regvalue);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200702
Mattias Wallind7b9f322010-11-26 13:06:39 +0100703 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200704}
705
706static int ab8500_val_open(struct inode *inode, struct file *file)
707{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100708 return single_open(file, ab8500_val_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200709}
710
711static ssize_t ab8500_val_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100712 const char __user *user_buf,
713 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200714{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100715 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +0100716 unsigned long user_val;
717 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200718
Mattias Wallind7b9f322010-11-26 13:06:39 +0100719 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +0200720 err = kstrtoul_from_user(user_buf, count, 0, &user_val);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100721 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +0200722 return err;
723
Mattias Wallind7b9f322010-11-26 13:06:39 +0100724 if (user_val > 0xff) {
725 dev_err(dev, "debugfs error input > 0xff\n");
726 return -EINVAL;
727 }
728 err = abx500_set_register_interruptible(dev,
729 (u8)debug_bank, debug_address, (u8)user_val);
730 if (err < 0) {
731 printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
732 return -EINVAL;
733 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200734
Peter Huewe8504d632011-06-06 22:43:32 +0200735 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200736}
737
carriere etienne0fbce762011-04-08 16:26:36 +0200738/*
739 * - HWREG DB8500 formated routines
740 */
741static int ab8500_hwreg_print(struct seq_file *s, void *d)
742{
743 struct device *dev = s->private;
744 int ret;
745 u8 regvalue;
746
747 ret = abx500_get_register_interruptible(dev,
748 (u8)hwreg_cfg.bank, (u8)hwreg_cfg.addr, &regvalue);
749 if (ret < 0) {
750 dev_err(dev, "abx500_get_reg fail %d, %d\n",
751 ret, __LINE__);
752 return -EINVAL;
753 }
754
755 if (hwreg_cfg.shift >= 0)
756 regvalue >>= hwreg_cfg.shift;
757 else
758 regvalue <<= -hwreg_cfg.shift;
759 regvalue &= hwreg_cfg.mask;
760
761 if (REG_FMT_DEC(&hwreg_cfg))
762 seq_printf(s, "%d\n", regvalue);
763 else
764 seq_printf(s, "0x%02X\n", regvalue);
765 return 0;
766}
767
768static int ab8500_hwreg_open(struct inode *inode, struct file *file)
769{
770 return single_open(file, ab8500_hwreg_print, inode->i_private);
771}
772
John Beckett1478a312011-05-31 13:54:27 +0100773static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
774{
775 int bat_ctrl_raw;
776 int bat_ctrl_convert;
777 struct ab8500_gpadc *gpadc;
778
779 gpadc = ab8500_gpadc_get();
780 bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL);
781 bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc,
782 BAT_CTRL, bat_ctrl_raw);
783
784 return seq_printf(s, "%d,0x%X\n",
785 bat_ctrl_convert, bat_ctrl_raw);
786}
787
788static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
789{
790 return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private);
791}
792
793static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
794 .open = ab8500_gpadc_bat_ctrl_open,
795 .read = seq_read,
796 .llseek = seq_lseek,
797 .release = single_release,
798 .owner = THIS_MODULE,
799};
800
801static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
802{
803 int btemp_ball_raw;
804 int btemp_ball_convert;
805 struct ab8500_gpadc *gpadc;
806
807 gpadc = ab8500_gpadc_get();
808 btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL);
809 btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
810 btemp_ball_raw);
811
812 return seq_printf(s,
813 "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw);
814}
815
816static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
817 struct file *file)
818{
819 return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private);
820}
821
822static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
823 .open = ab8500_gpadc_btemp_ball_open,
824 .read = seq_read,
825 .llseek = seq_lseek,
826 .release = single_release,
827 .owner = THIS_MODULE,
828};
829
830static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p)
831{
832 int main_charger_v_raw;
833 int main_charger_v_convert;
834 struct ab8500_gpadc *gpadc;
835
836 gpadc = ab8500_gpadc_get();
837 main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V);
838 main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
839 MAIN_CHARGER_V, main_charger_v_raw);
840
841 return seq_printf(s, "%d,0x%X\n",
842 main_charger_v_convert, main_charger_v_raw);
843}
844
845static int ab8500_gpadc_main_charger_v_open(struct inode *inode,
846 struct file *file)
847{
848 return single_open(file, ab8500_gpadc_main_charger_v_print,
849 inode->i_private);
850}
851
852static const struct file_operations ab8500_gpadc_main_charger_v_fops = {
853 .open = ab8500_gpadc_main_charger_v_open,
854 .read = seq_read,
855 .llseek = seq_lseek,
856 .release = single_release,
857 .owner = THIS_MODULE,
858};
859
860static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p)
861{
862 int acc_detect1_raw;
863 int acc_detect1_convert;
864 struct ab8500_gpadc *gpadc;
865
866 gpadc = ab8500_gpadc_get();
867 acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1);
868 acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1,
869 acc_detect1_raw);
870
871 return seq_printf(s, "%d,0x%X\n",
872 acc_detect1_convert, acc_detect1_raw);
873}
874
875static int ab8500_gpadc_acc_detect1_open(struct inode *inode,
876 struct file *file)
877{
878 return single_open(file, ab8500_gpadc_acc_detect1_print,
879 inode->i_private);
880}
881
882static const struct file_operations ab8500_gpadc_acc_detect1_fops = {
883 .open = ab8500_gpadc_acc_detect1_open,
884 .read = seq_read,
885 .llseek = seq_lseek,
886 .release = single_release,
887 .owner = THIS_MODULE,
888};
889
890static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p)
891{
892 int acc_detect2_raw;
893 int acc_detect2_convert;
894 struct ab8500_gpadc *gpadc;
895
896 gpadc = ab8500_gpadc_get();
897 acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2);
898 acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc,
899 ACC_DETECT2, acc_detect2_raw);
900
901 return seq_printf(s, "%d,0x%X\n",
902 acc_detect2_convert, acc_detect2_raw);
903}
904
905static int ab8500_gpadc_acc_detect2_open(struct inode *inode,
906 struct file *file)
907{
908 return single_open(file, ab8500_gpadc_acc_detect2_print,
909 inode->i_private);
910}
911
912static const struct file_operations ab8500_gpadc_acc_detect2_fops = {
913 .open = ab8500_gpadc_acc_detect2_open,
914 .read = seq_read,
915 .llseek = seq_lseek,
916 .release = single_release,
917 .owner = THIS_MODULE,
918};
919
920static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p)
921{
922 int aux1_raw;
923 int aux1_convert;
924 struct ab8500_gpadc *gpadc;
925
926 gpadc = ab8500_gpadc_get();
927 aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1);
928 aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1,
929 aux1_raw);
930
931 return seq_printf(s, "%d,0x%X\n",
932 aux1_convert, aux1_raw);
933}
934
935static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file)
936{
937 return single_open(file, ab8500_gpadc_aux1_print, inode->i_private);
938}
939
940static const struct file_operations ab8500_gpadc_aux1_fops = {
941 .open = ab8500_gpadc_aux1_open,
942 .read = seq_read,
943 .llseek = seq_lseek,
944 .release = single_release,
945 .owner = THIS_MODULE,
946};
947
948static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p)
949{
950 int aux2_raw;
951 int aux2_convert;
952 struct ab8500_gpadc *gpadc;
953
954 gpadc = ab8500_gpadc_get();
955 aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2);
956 aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2,
957 aux2_raw);
958
959 return seq_printf(s, "%d,0x%X\n",
960 aux2_convert, aux2_raw);
961}
962
963static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file)
964{
965 return single_open(file, ab8500_gpadc_aux2_print, inode->i_private);
966}
967
968static const struct file_operations ab8500_gpadc_aux2_fops = {
969 .open = ab8500_gpadc_aux2_open,
970 .read = seq_read,
971 .llseek = seq_lseek,
972 .release = single_release,
973 .owner = THIS_MODULE,
974};
975
976static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
977{
978 int main_bat_v_raw;
979 int main_bat_v_convert;
980 struct ab8500_gpadc *gpadc;
981
982 gpadc = ab8500_gpadc_get();
983 main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V);
984 main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
985 main_bat_v_raw);
986
987 return seq_printf(s, "%d,0x%X\n",
988 main_bat_v_convert, main_bat_v_raw);
989}
990
991static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
992 struct file *file)
993{
994 return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private);
995}
996
997static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
998 .open = ab8500_gpadc_main_bat_v_open,
999 .read = seq_read,
1000 .llseek = seq_lseek,
1001 .release = single_release,
1002 .owner = THIS_MODULE,
1003};
1004
1005static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p)
1006{
1007 int vbus_v_raw;
1008 int vbus_v_convert;
1009 struct ab8500_gpadc *gpadc;
1010
1011 gpadc = ab8500_gpadc_get();
1012 vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V);
1013 vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V,
1014 vbus_v_raw);
1015
1016 return seq_printf(s, "%d,0x%X\n",
1017 vbus_v_convert, vbus_v_raw);
1018}
1019
1020static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file)
1021{
1022 return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private);
1023}
1024
1025static const struct file_operations ab8500_gpadc_vbus_v_fops = {
1026 .open = ab8500_gpadc_vbus_v_open,
1027 .read = seq_read,
1028 .llseek = seq_lseek,
1029 .release = single_release,
1030 .owner = THIS_MODULE,
1031};
1032
1033static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p)
1034{
1035 int main_charger_c_raw;
1036 int main_charger_c_convert;
1037 struct ab8500_gpadc *gpadc;
1038
1039 gpadc = ab8500_gpadc_get();
1040 main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C);
1041 main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
1042 MAIN_CHARGER_C, main_charger_c_raw);
1043
1044 return seq_printf(s, "%d,0x%X\n",
1045 main_charger_c_convert, main_charger_c_raw);
1046}
1047
1048static int ab8500_gpadc_main_charger_c_open(struct inode *inode,
1049 struct file *file)
1050{
1051 return single_open(file, ab8500_gpadc_main_charger_c_print,
1052 inode->i_private);
1053}
1054
1055static const struct file_operations ab8500_gpadc_main_charger_c_fops = {
1056 .open = ab8500_gpadc_main_charger_c_open,
1057 .read = seq_read,
1058 .llseek = seq_lseek,
1059 .release = single_release,
1060 .owner = THIS_MODULE,
1061};
1062
1063static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p)
1064{
1065 int usb_charger_c_raw;
1066 int usb_charger_c_convert;
1067 struct ab8500_gpadc *gpadc;
1068
1069 gpadc = ab8500_gpadc_get();
1070 usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C);
1071 usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
1072 USB_CHARGER_C, usb_charger_c_raw);
1073
1074 return seq_printf(s, "%d,0x%X\n",
1075 usb_charger_c_convert, usb_charger_c_raw);
1076}
1077
1078static int ab8500_gpadc_usb_charger_c_open(struct inode *inode,
1079 struct file *file)
1080{
1081 return single_open(file, ab8500_gpadc_usb_charger_c_print,
1082 inode->i_private);
1083}
1084
1085static const struct file_operations ab8500_gpadc_usb_charger_c_fops = {
1086 .open = ab8500_gpadc_usb_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_bk_bat_v_print(struct seq_file *s, void *p)
1094{
1095 int bk_bat_v_raw;
1096 int bk_bat_v_convert;
1097 struct ab8500_gpadc *gpadc;
1098
1099 gpadc = ab8500_gpadc_get();
1100 bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V);
1101 bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
1102 BK_BAT_V, bk_bat_v_raw);
1103
1104 return seq_printf(s, "%d,0x%X\n",
1105 bk_bat_v_convert, bk_bat_v_raw);
1106}
1107
1108static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
1109{
1110 return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private);
1111}
1112
1113static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
1114 .open = ab8500_gpadc_bk_bat_v_open,
1115 .read = seq_read,
1116 .llseek = seq_lseek,
1117 .release = single_release,
1118 .owner = THIS_MODULE,
1119};
1120
1121static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
1122{
1123 int die_temp_raw;
1124 int die_temp_convert;
1125 struct ab8500_gpadc *gpadc;
1126
1127 gpadc = ab8500_gpadc_get();
1128 die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP);
1129 die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP,
1130 die_temp_raw);
1131
1132 return seq_printf(s, "%d,0x%X\n",
1133 die_temp_convert, die_temp_raw);
1134}
1135
1136static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
1137{
1138 return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private);
1139}
1140
1141static const struct file_operations ab8500_gpadc_die_temp_fops = {
1142 .open = ab8500_gpadc_die_temp_open,
1143 .read = seq_read,
1144 .llseek = seq_lseek,
1145 .release = single_release,
1146 .owner = THIS_MODULE,
1147};
1148
carriere etienne0fbce762011-04-08 16:26:36 +02001149/*
1150 * return length of an ASCII numerical value, 0 is string is not a
1151 * numerical value.
1152 * string shall start at value 1st char.
1153 * string can be tailed with \0 or space or newline chars only.
1154 * value can be decimal or hexadecimal (prefixed 0x or 0X).
1155 */
1156static int strval_len(char *b)
1157{
1158 char *s = b;
1159 if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) {
1160 s += 2;
1161 for (; *s && (*s != ' ') && (*s != '\n'); s++) {
1162 if (!isxdigit(*s))
1163 return 0;
1164 }
1165 } else {
1166 if (*s == '-')
1167 s++;
1168 for (; *s && (*s != ' ') && (*s != '\n'); s++) {
1169 if (!isdigit(*s))
1170 return 0;
1171 }
1172 }
1173 return (int) (s-b);
1174}
1175
1176/*
1177 * parse hwreg input data.
1178 * update global hwreg_cfg only if input data syntax is ok.
1179 */
1180static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
1181 struct device *dev)
1182{
1183 uint write, val = 0;
1184 u8 regvalue;
1185 int ret;
1186 struct hwreg_cfg loc = {
1187 .bank = 0, /* default: invalid phys addr */
1188 .addr = 0, /* default: invalid phys addr */
1189 .fmt = 0, /* default: 32bit access, hex output */
1190 .mask = 0xFFFFFFFF, /* default: no mask */
1191 .shift = 0, /* default: no bit shift */
1192 };
1193
1194 /* read or write ? */
1195 if (!strncmp(b, "read ", 5)) {
1196 write = 0;
1197 b += 5;
1198 } else if (!strncmp(b, "write ", 6)) {
1199 write = 1;
1200 b += 6;
1201 } else
1202 return -EINVAL;
1203
1204 /* OPTIONS -l|-w|-b -s -m -o */
1205 while ((*b == ' ') || (*b == '-')) {
1206 if (*(b-1) != ' ') {
1207 b++;
1208 continue;
1209 }
1210 if ((!strncmp(b, "-d ", 3)) ||
1211 (!strncmp(b, "-dec ", 5))) {
1212 b += (*(b+2) == ' ') ? 3 : 5;
1213 loc.fmt |= (1<<0);
1214 } else if ((!strncmp(b, "-h ", 3)) ||
1215 (!strncmp(b, "-hex ", 5))) {
1216 b += (*(b+2) == ' ') ? 3 : 5;
1217 loc.fmt &= ~(1<<0);
1218 } else if ((!strncmp(b, "-m ", 3)) ||
1219 (!strncmp(b, "-mask ", 6))) {
1220 b += (*(b+2) == ' ') ? 3 : 6;
1221 if (strval_len(b) == 0)
1222 return -EINVAL;
1223 loc.mask = simple_strtoul(b, &b, 0);
1224 } else if ((!strncmp(b, "-s ", 3)) ||
1225 (!strncmp(b, "-shift ", 7))) {
1226 b += (*(b+2) == ' ') ? 3 : 7;
1227 if (strval_len(b) == 0)
1228 return -EINVAL;
1229 loc.shift = simple_strtol(b, &b, 0);
1230 } else {
1231 return -EINVAL;
1232 }
1233 }
1234 /* get arg BANK and ADDRESS */
1235 if (strval_len(b) == 0)
1236 return -EINVAL;
1237 loc.bank = simple_strtoul(b, &b, 0);
1238 while (*b == ' ')
1239 b++;
1240 if (strval_len(b) == 0)
1241 return -EINVAL;
1242 loc.addr = simple_strtoul(b, &b, 0);
1243
1244 if (write) {
1245 while (*b == ' ')
1246 b++;
1247 if (strval_len(b) == 0)
1248 return -EINVAL;
1249 val = simple_strtoul(b, &b, 0);
1250 }
1251
1252 /* args are ok, update target cfg (mainly for read) */
1253 *cfg = loc;
1254
1255#ifdef ABB_HWREG_DEBUG
1256 pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d"
1257 "value=0x%X\n", (write) ? "write" : "read",
1258 REG_FMT_DEC(cfg) ? "decimal" : "hexa",
1259 cfg->addr, cfg->mask, cfg->shift, val);
1260#endif
1261
1262 if (!write)
1263 return 0;
1264
1265 ret = abx500_get_register_interruptible(dev,
1266 (u8)cfg->bank, (u8)cfg->addr, &regvalue);
1267 if (ret < 0) {
1268 dev_err(dev, "abx500_get_reg fail %d, %d\n",
1269 ret, __LINE__);
1270 return -EINVAL;
1271 }
1272
1273 if (cfg->shift >= 0) {
1274 regvalue &= ~(cfg->mask << (cfg->shift));
1275 val = (val & cfg->mask) << (cfg->shift);
1276 } else {
1277 regvalue &= ~(cfg->mask >> (-cfg->shift));
1278 val = (val & cfg->mask) >> (-cfg->shift);
1279 }
1280 val = val | regvalue;
1281
1282 ret = abx500_set_register_interruptible(dev,
1283 (u8)cfg->bank, (u8)cfg->addr, (u8)val);
1284 if (ret < 0) {
1285 pr_err("abx500_set_reg failed %d, %d", ret, __LINE__);
1286 return -EINVAL;
1287 }
1288
1289 return 0;
1290}
1291
1292static ssize_t ab8500_hwreg_write(struct file *file,
1293 const char __user *user_buf, size_t count, loff_t *ppos)
1294{
1295 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1296 char buf[128];
1297 int buf_size, ret;
1298
1299 /* Get userspace string and assure termination */
1300 buf_size = min(count, (sizeof(buf)-1));
1301 if (copy_from_user(buf, user_buf, buf_size))
1302 return -EFAULT;
1303 buf[buf_size] = 0;
1304
1305 /* get args and process */
1306 ret = hwreg_common_write(buf, &hwreg_cfg, dev);
1307 return (ret) ? ret : buf_size;
1308}
1309
1310/*
1311 * - irq subscribe/unsubscribe stuff
1312 */
Lee Jones4b8ac082013-01-14 16:10:36 +00001313static int ab8500_subscribe_unsubscribe_print(struct seq_file *s, void *p)
1314{
1315 seq_printf(s, "%d\n", irq_first);
1316
1317 return 0;
1318}
1319
1320static int ab8500_subscribe_unsubscribe_open(struct inode *inode,
1321 struct file *file)
1322{
1323 return single_open(file, ab8500_subscribe_unsubscribe_print,
1324 inode->i_private);
1325}
1326
1327/*
Mattias Wallin0b337e72010-11-19 17:55:11 +01001328 * Userspace should use poll() on this file. When an event occur
Lee Jones4b8ac082013-01-14 16:10:36 +00001329 * the blocking poll will be released.
1330 */
1331static ssize_t show_irq(struct device *dev,
1332 struct device_attribute *attr, char *buf)
1333{
Mattias Wallin0b337e72010-11-19 17:55:11 +01001334 unsigned long name;
1335 unsigned int irq_index;
1336 int err;
Lee Jones4b8ac082013-01-14 16:10:36 +00001337
Mattias Wallin0b337e72010-11-19 17:55:11 +01001338 err = strict_strtoul(attr->attr.name, 0, &name);
1339 if (err)
1340 return err;
1341
1342 irq_index = name - irq_first;
1343 if (irq_index >= AB8500_NR_IRQS)
1344 return -EINVAL;
1345 else
1346 return sprintf(buf, "%u\n", irq_count[irq_index]);
1347}
Lee Jones4b8ac082013-01-14 16:10:36 +00001348
1349static ssize_t ab8500_subscribe_write(struct file *file,
1350 const char __user *user_buf,
1351 size_t count, loff_t *ppos)
1352{
1353 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1354 char buf[32];
1355 int buf_size;
1356 unsigned long user_val;
1357 int err;
Mattias Wallin0b337e72010-11-19 17:55:11 +01001358 unsigned int irq_index;
Lee Jones4b8ac082013-01-14 16:10:36 +00001359
1360 /* Get userspace string and assure termination */
1361 buf_size = min(count, (sizeof(buf)-1));
1362 if (copy_from_user(buf, user_buf, buf_size))
1363 return -EFAULT;
1364 buf[buf_size] = 0;
1365
1366 err = strict_strtoul(buf, 0, &user_val);
1367 if (err)
1368 return -EINVAL;
1369 if (user_val < irq_first) {
1370 dev_err(dev, "debugfs error input < %d\n", irq_first);
1371 return -EINVAL;
1372 }
1373 if (user_val > irq_last) {
1374 dev_err(dev, "debugfs error input > %d\n", irq_last);
1375 return -EINVAL;
1376 }
1377
Mattias Wallin0b337e72010-11-19 17:55:11 +01001378 irq_index = user_val - irq_first;
1379 if (irq_index >= AB8500_NR_IRQS)
1380 return -EINVAL;
1381
Lee Jones4b8ac082013-01-14 16:10:36 +00001382 /*
Mattias Wallin0b337e72010-11-19 17:55:11 +01001383 * This will create a sysfs file named <irq-nr> which userspace can
Lee Jones4b8ac082013-01-14 16:10:36 +00001384 * use to select or poll and get the AB8500 events
1385 */
Mattias Wallin0b337e72010-11-19 17:55:11 +01001386 dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute),
1387 GFP_KERNEL);
1388 event_name[irq_index] = kmalloc(buf_size, GFP_KERNEL);
1389 sprintf(event_name[irq_index], "%lu", user_val);
1390 dev_attr[irq_index]->show = show_irq;
1391 dev_attr[irq_index]->store = NULL;
1392 dev_attr[irq_index]->attr.name = event_name[irq_index];
1393 dev_attr[irq_index]->attr.mode = S_IRUGO;
1394 err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr);
Lee Jones4b8ac082013-01-14 16:10:36 +00001395 if (err < 0) {
1396 printk(KERN_ERR "sysfs_create_file failed %d\n", err);
1397 return err;
1398 }
1399
1400 err = request_threaded_irq(user_val, NULL, ab8500_debug_handler,
1401 IRQF_SHARED | IRQF_NO_SUSPEND,
1402 "ab8500-debug", &dev->kobj);
1403 if (err < 0) {
1404 printk(KERN_ERR "request_threaded_irq failed %d, %lu\n",
1405 err, user_val);
Mattias Wallin0b337e72010-11-19 17:55:11 +01001406 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
Lee Jones4b8ac082013-01-14 16:10:36 +00001407 return err;
1408 }
1409
1410 return buf_size;
1411}
1412
1413static ssize_t ab8500_unsubscribe_write(struct file *file,
1414 const char __user *user_buf,
1415 size_t count, loff_t *ppos)
1416{
1417 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1418 char buf[32];
1419 int buf_size;
1420 unsigned long user_val;
1421 int err;
Mattias Wallin0b337e72010-11-19 17:55:11 +01001422 unsigned int irq_index;
Lee Jones4b8ac082013-01-14 16:10:36 +00001423
1424 /* Get userspace string and assure termination */
1425 buf_size = min(count, (sizeof(buf)-1));
1426 if (copy_from_user(buf, user_buf, buf_size))
1427 return -EFAULT;
1428 buf[buf_size] = 0;
1429
1430 err = strict_strtoul(buf, 0, &user_val);
1431 if (err)
1432 return -EINVAL;
1433 if (user_val < irq_first) {
1434 dev_err(dev, "debugfs error input < %d\n", irq_first);
1435 return -EINVAL;
1436 }
1437 if (user_val > irq_last) {
1438 dev_err(dev, "debugfs error input > %d\n", irq_last);
1439 return -EINVAL;
1440 }
1441
Mattias Wallin0b337e72010-11-19 17:55:11 +01001442 irq_index = user_val - irq_first;
1443 if (irq_index >= AB8500_NR_IRQS)
1444 return -EINVAL;
Lee Jones4b8ac082013-01-14 16:10:36 +00001445
Mattias Wallin0b337e72010-11-19 17:55:11 +01001446 /* Set irq count to 0 when unsubscribe */
1447 irq_count[irq_index] = 0;
1448
1449 if (dev_attr[irq_index])
1450 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
1451
1452
1453 free_irq(user_val, &dev->kobj);
1454 kfree(event_name[irq_index]);
1455 kfree(dev_attr[irq_index]);
Lee Jones4b8ac082013-01-14 16:10:36 +00001456
1457 return buf_size;
1458}
1459
carriere etienne0fbce762011-04-08 16:26:36 +02001460/*
1461 * - several deubgfs nodes fops
1462 */
1463
Mattias Wallin5814fc32010-09-13 16:05:04 +02001464static const struct file_operations ab8500_bank_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001465 .open = ab8500_bank_open,
1466 .write = ab8500_bank_write,
1467 .read = seq_read,
1468 .llseek = seq_lseek,
1469 .release = single_release,
1470 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001471};
1472
1473static const struct file_operations ab8500_address_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001474 .open = ab8500_address_open,
1475 .write = ab8500_address_write,
1476 .read = seq_read,
1477 .llseek = seq_lseek,
1478 .release = single_release,
1479 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001480};
1481
1482static const struct file_operations ab8500_val_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001483 .open = ab8500_val_open,
1484 .write = ab8500_val_write,
1485 .read = seq_read,
1486 .llseek = seq_lseek,
1487 .release = single_release,
1488 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001489};
1490
Lee Jones4b8ac082013-01-14 16:10:36 +00001491static const struct file_operations ab8500_subscribe_fops = {
1492 .open = ab8500_subscribe_unsubscribe_open,
1493 .write = ab8500_subscribe_write,
1494 .read = seq_read,
1495 .llseek = seq_lseek,
1496 .release = single_release,
1497 .owner = THIS_MODULE,
1498};
1499
1500static const struct file_operations ab8500_unsubscribe_fops = {
1501 .open = ab8500_subscribe_unsubscribe_open,
1502 .write = ab8500_unsubscribe_write,
1503 .read = seq_read,
1504 .llseek = seq_lseek,
1505 .release = single_release,
1506 .owner = THIS_MODULE,
1507};
1508
carriere etienne0fbce762011-04-08 16:26:36 +02001509static const struct file_operations ab8500_hwreg_fops = {
1510 .open = ab8500_hwreg_open,
1511 .write = ab8500_hwreg_write,
1512 .read = seq_read,
1513 .llseek = seq_lseek,
1514 .release = single_release,
1515 .owner = THIS_MODULE,
1516};
1517
Mattias Wallin5814fc32010-09-13 16:05:04 +02001518static struct dentry *ab8500_dir;
John Beckett1478a312011-05-31 13:54:27 +01001519static struct dentry *ab8500_gpadc_dir;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001520
Bill Pembertonf791be42012-11-19 13:23:04 -05001521static int ab8500_debug_probe(struct platform_device *plf)
Mattias Wallin5814fc32010-09-13 16:05:04 +02001522{
carriere etienne0fbce762011-04-08 16:26:36 +02001523 struct dentry *file;
Mattias Wallind7b9f322010-11-26 13:06:39 +01001524 debug_bank = AB8500_MISC;
1525 debug_address = AB8500_REV_REG & 0x00FF;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001526
Lee Jones4b8ac082013-01-14 16:10:36 +00001527 irq_first = platform_get_irq_byname(plf, "IRQ_FIRST");
1528 if (irq_first < 0) {
1529 dev_err(&plf->dev, "First irq not found, err %d\n",
John Beckett1478a312011-05-31 13:54:27 +01001530 irq_first);
Lee Jones4b8ac082013-01-14 16:10:36 +00001531 return irq_first;
1532 }
1533
1534 irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
1535 if (irq_last < 0) {
1536 dev_err(&plf->dev, "Last irq not found, err %d\n",
John Beckett1478a312011-05-31 13:54:27 +01001537 irq_last);
Lee Jones4b8ac082013-01-14 16:10:36 +00001538 return irq_last;
1539 }
1540
Mattias Wallind7b9f322010-11-26 13:06:39 +01001541 ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
1542 if (!ab8500_dir)
carriere etienne0fbce762011-04-08 16:26:36 +02001543 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001544
John Beckett1478a312011-05-31 13:54:27 +01001545 ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING,
1546 ab8500_dir);
1547 if (!ab8500_gpadc_dir)
1548 goto err;
1549
1550 file = debugfs_create_file("all-bank-registers", S_IRUGO,
1551 ab8500_dir, &plf->dev, &ab8500_registers_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001552 if (!file)
1553 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001554
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +01001555 file = debugfs_create_file("all-banks", S_IRUGO,
1556 ab8500_dir, &plf->dev, &ab8500_all_banks_fops);
1557 if (!file)
1558 goto err;
1559
John Beckett1478a312011-05-31 13:54:27 +01001560 file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR),
1561 ab8500_dir, &plf->dev, &ab8500_bank_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001562 if (!file)
1563 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001564
John Beckett1478a312011-05-31 13:54:27 +01001565 file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR),
1566 ab8500_dir, &plf->dev, &ab8500_address_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001567 if (!file)
1568 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001569
John Beckett1478a312011-05-31 13:54:27 +01001570 file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR),
1571 ab8500_dir, &plf->dev, &ab8500_val_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001572 if (!file)
1573 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001574
John Beckett1478a312011-05-31 13:54:27 +01001575 file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR),
1576 ab8500_dir, &plf->dev, &ab8500_subscribe_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001577 if (!file)
1578 goto err;
Lee Jones4b8ac082013-01-14 16:10:36 +00001579
John Beckett1478a312011-05-31 13:54:27 +01001580 file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR),
1581 ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001582 if (!file)
1583 goto err;
1584
John Beckett1478a312011-05-31 13:54:27 +01001585 file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR),
1586 ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
1587 if (!file)
1588 goto err;
1589
1590 file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR),
1591 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops);
1592 if (!file)
1593 goto err;
1594
1595 file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR),
1596 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops);
1597 if (!file)
1598 goto err;
1599
1600 file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR),
1601 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops);
1602 if (!file)
1603 goto err;
1604
1605 file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR),
1606 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops);
1607 if (!file)
1608 goto err;
1609
1610 file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR),
1611 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops);
1612 if (!file)
1613 goto err;
1614
1615 file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR),
1616 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops);
1617 if (!file)
1618 goto err;
1619
1620 file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR),
1621 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops);
1622 if (!file)
1623 goto err;
1624
1625 file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR),
1626 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops);
1627 if (!file)
1628 goto err;
1629
1630 file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR),
1631 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops);
1632 if (!file)
1633 goto err;
1634
1635 file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR),
1636 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops);
1637 if (!file)
1638 goto err;
1639
1640 file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR),
1641 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
1642 if (!file)
1643 goto err;
1644
1645 file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR),
1646 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops);
1647 if (!file)
1648 goto err;
1649
1650 file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR),
1651 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001652 if (!file)
1653 goto err;
Lee Jones4b8ac082013-01-14 16:10:36 +00001654
Mattias Wallind7b9f322010-11-26 13:06:39 +01001655 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001656
carriere etienne0fbce762011-04-08 16:26:36 +02001657err:
1658 if (ab8500_dir)
1659 debugfs_remove_recursive(ab8500_dir);
Mattias Wallind7b9f322010-11-26 13:06:39 +01001660 dev_err(&plf->dev, "failed to create debugfs entries.\n");
1661 return -ENOMEM;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001662}
1663
Bill Pemberton4740f732012-11-19 13:26:01 -05001664static int ab8500_debug_remove(struct platform_device *plf)
Mattias Wallin5814fc32010-09-13 16:05:04 +02001665{
carriere etienne0fbce762011-04-08 16:26:36 +02001666 debugfs_remove_recursive(ab8500_dir);
Mattias Wallind7b9f322010-11-26 13:06:39 +01001667 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001668}
1669
1670static struct platform_driver ab8500_debug_driver = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001671 .driver = {
1672 .name = "ab8500-debug",
1673 .owner = THIS_MODULE,
1674 },
1675 .probe = ab8500_debug_probe,
Bill Pemberton84449212012-11-19 13:20:24 -05001676 .remove = ab8500_debug_remove
Mattias Wallin5814fc32010-09-13 16:05:04 +02001677};
1678
1679static int __init ab8500_debug_init(void)
1680{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001681 return platform_driver_register(&ab8500_debug_driver);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001682}
1683
1684static void __exit ab8500_debug_exit(void)
1685{
Mattias Wallind7b9f322010-11-26 13:06:39 +01001686 platform_driver_unregister(&ab8500_debug_driver);
Mattias Wallin5814fc32010-09-13 16:05:04 +02001687}
1688subsys_initcall(ab8500_debug_init);
1689module_exit(ab8500_debug_exit);
1690
1691MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
1692MODULE_DESCRIPTION("AB8500 DEBUG");
1693MODULE_LICENSE("GPL v2");