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