blob: 1e76a2f35066a2d1a91d94b40abd1d73e54440d0 [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>
Linus Walleij0cd5b6d02013-02-06 23:23:01 +010085#include <linux/mfd/abx500/ab8500.h>
John Beckett1478a312011-05-31 13:54:27 +010086#include <linux/mfd/abx500/ab8500-gpadc.h>
Mattias Wallin5814fc32010-09-13 16:05:04 +020087
carriere etienne0fbce762011-04-08 16:26:36 +020088#ifdef CONFIG_DEBUG_FS
89#include <linux/string.h>
90#include <linux/ctype.h>
91#endif
92
Mattias Wallin5814fc32010-09-13 16:05:04 +020093static u32 debug_bank;
94static u32 debug_address;
95
Lee Jones4b8ac082013-01-14 16:10:36 +000096static int irq_first;
97static int irq_last;
Linus Walleijddba25f2012-02-03 11:19:05 +010098static u32 *irq_count;
99static int num_irqs;
Mattias Wallin0b337e72010-11-19 17:55:11 +0100100
Linus Walleijddba25f2012-02-03 11:19:05 +0100101static struct device_attribute **dev_attr;
102static char **event_name;
Lee Jones4b8ac082013-01-14 16:10:36 +0000103
Lee Jones73482342013-02-26 10:06:55 +0000104static u8 avg_sample = SAMPLE_16;
105static u8 trig_edge = RISING_EDGE;
106static u8 conv_type = ADC_SW;
107static u8 trig_timer;
108
Mattias Wallin5814fc32010-09-13 16:05:04 +0200109/**
110 * struct ab8500_reg_range
111 * @first: the first address of the range
112 * @last: the last address of the range
113 * @perm: access permissions for the range
114 */
115struct ab8500_reg_range {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100116 u8 first;
117 u8 last;
118 u8 perm;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200119};
120
121/**
Lee Jones822672a2012-06-20 13:56:38 +0100122 * struct ab8500_prcmu_ranges
Mattias Wallin5814fc32010-09-13 16:05:04 +0200123 * @num_ranges: the number of ranges in the list
124 * @bankid: bank identifier
125 * @range: the list of register ranges
126 */
Lee Jones822672a2012-06-20 13:56:38 +0100127struct ab8500_prcmu_ranges {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100128 u8 num_ranges;
129 u8 bankid;
130 const struct ab8500_reg_range *range;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200131};
132
carriere etienne0fbce762011-04-08 16:26:36 +0200133/* hwreg- "mask" and "shift" entries ressources */
134struct hwreg_cfg {
135 u32 bank; /* target bank */
136 u32 addr; /* target address */
137 uint fmt; /* format */
138 uint mask; /* read/write mask, applied before any bit shift */
139 int shift; /* bit shift (read:right shift, write:left shift */
140};
141/* fmt bit #0: 0=hexa, 1=dec */
142#define REG_FMT_DEC(c) ((c)->fmt & 0x1)
143#define REG_FMT_HEX(c) (!REG_FMT_DEC(c))
144
145static struct hwreg_cfg hwreg_cfg = {
146 .addr = 0, /* default: invalid phys addr */
147 .fmt = 0, /* default: 32bit access, hex output */
148 .mask = 0xFFFFFFFF, /* default: no mask */
149 .shift = 0, /* default: no bit shift */
150};
151
Mattias Wallin5814fc32010-09-13 16:05:04 +0200152#define AB8500_NAME_STRING "ab8500"
John Beckett1478a312011-05-31 13:54:27 +0100153#define AB8500_ADC_NAME_STRING "gpadc"
Philippe Langlais40c064e2011-10-17 09:48:55 +0200154#define AB8500_NUM_BANKS 24
Mattias Wallin5814fc32010-09-13 16:05:04 +0200155
156#define AB8500_REV_REG 0x80
157
Lee Jones822672a2012-06-20 13:56:38 +0100158static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100159 [0x0] = {
160 .num_ranges = 0,
Lee Jonesfad55a82013-01-14 17:17:34 +0000161 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100162 },
163 [AB8500_SYS_CTRL1_BLOCK] = {
164 .num_ranges = 3,
165 .range = (struct ab8500_reg_range[]) {
166 {
167 .first = 0x00,
168 .last = 0x02,
169 },
170 {
171 .first = 0x42,
172 .last = 0x42,
173 },
174 {
175 .first = 0x80,
176 .last = 0x81,
177 },
178 },
179 },
180 [AB8500_SYS_CTRL2_BLOCK] = {
181 .num_ranges = 4,
182 .range = (struct ab8500_reg_range[]) {
183 {
184 .first = 0x00,
185 .last = 0x0D,
186 },
187 {
188 .first = 0x0F,
189 .last = 0x17,
190 },
191 {
192 .first = 0x30,
193 .last = 0x30,
194 },
195 {
196 .first = 0x32,
197 .last = 0x33,
198 },
199 },
200 },
201 [AB8500_REGU_CTRL1] = {
202 .num_ranges = 3,
203 .range = (struct ab8500_reg_range[]) {
204 {
205 .first = 0x00,
206 .last = 0x00,
207 },
208 {
209 .first = 0x03,
210 .last = 0x10,
211 },
212 {
213 .first = 0x80,
214 .last = 0x84,
215 },
216 },
217 },
218 [AB8500_REGU_CTRL2] = {
219 .num_ranges = 5,
220 .range = (struct ab8500_reg_range[]) {
221 {
222 .first = 0x00,
223 .last = 0x15,
224 },
225 {
226 .first = 0x17,
227 .last = 0x19,
228 },
229 {
230 .first = 0x1B,
231 .last = 0x1D,
232 },
233 {
234 .first = 0x1F,
235 .last = 0x22,
236 },
237 {
238 .first = 0x40,
239 .last = 0x44,
240 },
241 /* 0x80-0x8B is SIM registers and should
242 * not be accessed from here */
243 },
244 },
245 [AB8500_USB] = {
246 .num_ranges = 2,
247 .range = (struct ab8500_reg_range[]) {
248 {
249 .first = 0x80,
250 .last = 0x83,
251 },
252 {
253 .first = 0x87,
254 .last = 0x8A,
255 },
256 },
257 },
258 [AB8500_TVOUT] = {
259 .num_ranges = 9,
260 .range = (struct ab8500_reg_range[]) {
261 {
262 .first = 0x00,
263 .last = 0x12,
264 },
265 {
266 .first = 0x15,
267 .last = 0x17,
268 },
269 {
270 .first = 0x19,
271 .last = 0x21,
272 },
273 {
274 .first = 0x27,
275 .last = 0x2C,
276 },
277 {
278 .first = 0x41,
279 .last = 0x41,
280 },
281 {
282 .first = 0x45,
283 .last = 0x5B,
284 },
285 {
286 .first = 0x5D,
287 .last = 0x5D,
288 },
289 {
290 .first = 0x69,
291 .last = 0x69,
292 },
293 {
294 .first = 0x80,
295 .last = 0x81,
296 },
297 },
298 },
299 [AB8500_DBI] = {
300 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000301 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100302 },
303 [AB8500_ECI_AV_ACC] = {
304 .num_ranges = 1,
305 .range = (struct ab8500_reg_range[]) {
306 {
307 .first = 0x80,
308 .last = 0x82,
309 },
310 },
311 },
312 [0x9] = {
313 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000314 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100315 },
316 [AB8500_GPADC] = {
317 .num_ranges = 1,
318 .range = (struct ab8500_reg_range[]) {
319 {
320 .first = 0x00,
321 .last = 0x08,
322 },
323 },
324 },
325 [AB8500_CHARGER] = {
Philippe Langlais40c064e2011-10-17 09:48:55 +0200326 .num_ranges = 9,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100327 .range = (struct ab8500_reg_range[]) {
328 {
329 .first = 0x00,
330 .last = 0x03,
331 },
332 {
333 .first = 0x05,
334 .last = 0x05,
335 },
336 {
337 .first = 0x40,
338 .last = 0x40,
339 },
340 {
341 .first = 0x42,
342 .last = 0x42,
343 },
344 {
345 .first = 0x44,
346 .last = 0x44,
347 },
348 {
349 .first = 0x50,
350 .last = 0x55,
351 },
352 {
353 .first = 0x80,
354 .last = 0x82,
355 },
356 {
357 .first = 0xC0,
358 .last = 0xC2,
359 },
Philippe Langlais40c064e2011-10-17 09:48:55 +0200360 {
361 .first = 0xf5,
362 .last = 0xf6,
363 },
Mattias Wallind7b9f322010-11-26 13:06:39 +0100364 },
365 },
366 [AB8500_GAS_GAUGE] = {
367 .num_ranges = 3,
368 .range = (struct ab8500_reg_range[]) {
369 {
370 .first = 0x00,
371 .last = 0x00,
372 },
373 {
374 .first = 0x07,
375 .last = 0x0A,
376 },
377 {
378 .first = 0x10,
379 .last = 0x14,
380 },
381 },
382 },
Philippe Langlais40c064e2011-10-17 09:48:55 +0200383 [AB8500_DEVELOPMENT] = {
384 .num_ranges = 1,
385 .range = (struct ab8500_reg_range[]) {
386 {
387 .first = 0x00,
388 .last = 0x00,
389 },
390 },
391 },
392 [AB8500_DEBUG] = {
393 .num_ranges = 1,
394 .range = (struct ab8500_reg_range[]) {
395 {
396 .first = 0x05,
397 .last = 0x07,
398 },
399 },
400 },
Mattias Wallind7b9f322010-11-26 13:06:39 +0100401 [AB8500_AUDIO] = {
402 .num_ranges = 1,
403 .range = (struct ab8500_reg_range[]) {
404 {
405 .first = 0x00,
406 .last = 0x6F,
407 },
408 },
409 },
410 [AB8500_INTERRUPT] = {
411 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000412 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100413 },
414 [AB8500_RTC] = {
415 .num_ranges = 1,
416 .range = (struct ab8500_reg_range[]) {
417 {
418 .first = 0x00,
419 .last = 0x0F,
420 },
421 },
422 },
423 [AB8500_MISC] = {
424 .num_ranges = 8,
425 .range = (struct ab8500_reg_range[]) {
426 {
427 .first = 0x00,
428 .last = 0x05,
429 },
430 {
431 .first = 0x10,
432 .last = 0x15,
433 },
434 {
435 .first = 0x20,
436 .last = 0x25,
437 },
438 {
439 .first = 0x30,
440 .last = 0x35,
441 },
442 {
443 .first = 0x40,
444 .last = 0x45,
445 },
446 {
447 .first = 0x50,
448 .last = 0x50,
449 },
450 {
451 .first = 0x60,
452 .last = 0x67,
453 },
454 {
455 .first = 0x80,
456 .last = 0x80,
457 },
458 },
459 },
460 [0x11] = {
461 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000462 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100463 },
464 [0x12] = {
465 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000466 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100467 },
468 [0x13] = {
469 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000470 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100471 },
472 [0x14] = {
473 .num_ranges = 0,
Mark Brown87fff232010-12-13 14:06:47 +0000474 .range = NULL,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100475 },
476 [AB8500_OTP_EMUL] = {
477 .num_ranges = 1,
478 .range = (struct ab8500_reg_range[]) {
479 {
480 .first = 0x01,
481 .last = 0x0F,
482 },
483 },
484 },
Mattias Wallin5814fc32010-09-13 16:05:04 +0200485};
486
Lee Jones4b8ac082013-01-14 16:10:36 +0000487static irqreturn_t ab8500_debug_handler(int irq, void *data)
488{
489 char buf[16];
490 struct kobject *kobj = (struct kobject *)data;
Mattias Wallin0b337e72010-11-19 17:55:11 +0100491 unsigned int irq_abb = irq - irq_first;
Lee Jones4b8ac082013-01-14 16:10:36 +0000492
Linus Walleijddba25f2012-02-03 11:19:05 +0100493 if (irq_abb < num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +0100494 irq_count[irq_abb]++;
Lee Jones4b8ac082013-01-14 16:10:36 +0000495 /*
496 * This makes it possible to use poll for events (POLLPRI | POLLERR)
Mattias Wallin0b337e72010-11-19 17:55:11 +0100497 * from userspace on sysfs file named <irq-nr>
Lee Jones4b8ac082013-01-14 16:10:36 +0000498 */
Mattias Wallin0b337e72010-11-19 17:55:11 +0100499 sprintf(buf, "%d", irq);
Lee Jones4b8ac082013-01-14 16:10:36 +0000500 sysfs_notify(kobj, NULL, buf);
501
502 return IRQ_HANDLED;
503}
504
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100505/* Prints to seq_file or log_buf */
506static int ab8500_registers_print(struct device *dev, u32 bank,
507 struct seq_file *s)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200508{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100509 unsigned int i;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200510
Mattias Wallind7b9f322010-11-26 13:06:39 +0100511 for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
512 u32 reg;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200513
Mattias Wallind7b9f322010-11-26 13:06:39 +0100514 for (reg = debug_ranges[bank].range[i].first;
515 reg <= debug_ranges[bank].range[i].last;
516 reg++) {
517 u8 value;
518 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200519
Mattias Wallind7b9f322010-11-26 13:06:39 +0100520 err = abx500_get_register_interruptible(dev,
521 (u8)bank, (u8)reg, &value);
522 if (err < 0) {
523 dev_err(dev, "ab->read fail %d\n", err);
524 return err;
525 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200526
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100527 if (s) {
Mattias Wallincfc08492012-05-28 15:53:58 +0200528 err = seq_printf(s, " [0x%02X/0x%02X]: 0x%02X\n",
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100529 bank, reg, value);
530 if (err < 0) {
531 dev_err(dev,
Mattias Wallincfc08492012-05-28 15:53:58 +0200532 "seq_printf overflow bank=0x%02X reg=0x%02X\n",
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100533 bank, reg);
534 /* Error is not returned here since
535 * the output is wanted in any case */
536 return 0;
537 }
538 } else {
Mattias Wallincfc08492012-05-28 15:53:58 +0200539 printk(KERN_INFO" [0x%02X/0x%02X]: 0x%02X\n",
540 bank, reg, value);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100541 }
542 }
543 }
544 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200545}
546
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100547static int ab8500_print_bank_registers(struct seq_file *s, void *p)
548{
549 struct device *dev = s->private;
550 u32 bank = debug_bank;
551
552 seq_printf(s, AB8500_NAME_STRING " register values:\n");
553
Mattias Wallincfc08492012-05-28 15:53:58 +0200554 seq_printf(s, " bank 0x%02X:\n", bank);
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100555
556 ab8500_registers_print(dev, bank, s);
557 return 0;
558}
559
Mattias Wallin5814fc32010-09-13 16:05:04 +0200560static int ab8500_registers_open(struct inode *inode, struct file *file)
561{
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100562 return single_open(file, ab8500_print_bank_registers, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200563}
564
565static const struct file_operations ab8500_registers_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +0100566 .open = ab8500_registers_open,
567 .read = seq_read,
568 .llseek = seq_lseek,
569 .release = single_release,
570 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +0200571};
572
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100573static int ab8500_print_all_banks(struct seq_file *s, void *p)
574{
575 struct device *dev = s->private;
576 unsigned int i;
577 int err;
578
579 seq_printf(s, AB8500_NAME_STRING " register values:\n");
580
581 for (i = 1; i < AB8500_NUM_BANKS; i++) {
Mattias Wallincfc08492012-05-28 15:53:58 +0200582 err = seq_printf(s, " bank 0x%02X:\n", i);
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100583 if (err < 0)
Mattias Wallincfc08492012-05-28 15:53:58 +0200584 dev_err(dev, "seq_printf overflow, bank=0x%02X\n", i);
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100585
586 ab8500_registers_print(dev, i, s);
587 }
588 return 0;
589}
590
Mian Yousaf Kaukab1d843a62012-01-27 11:35:41 +0100591/* Dump registers to kernel log */
592void ab8500_dump_all_banks(struct device *dev)
593{
594 unsigned int i;
595
596 printk(KERN_INFO"ab8500 register values:\n");
597
598 for (i = 1; i < AB8500_NUM_BANKS; i++) {
Mattias Wallincfc08492012-05-28 15:53:58 +0200599 printk(KERN_INFO" bank 0x%02X:\n", i);
Mian Yousaf Kaukab1d843a62012-01-27 11:35:41 +0100600 ab8500_registers_print(dev, i, NULL);
601 }
602}
603
Lee Jones5ff90902013-02-12 14:35:28 +0000604/* Space for 500 registers. */
605#define DUMP_MAX_REGS 700
606struct ab8500_register_dump
607{
608 u8 bank;
609 u8 reg;
610 u8 value;
Lee Jones5ff90902013-02-12 14:35:28 +0000611} ab8500_complete_register_dump[DUMP_MAX_REGS];
612
613extern int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
614
615/* This shall only be called upon kernel panic! */
616void ab8500_dump_all_banks_to_mem(void)
617{
618 int i, r = 0;
619 u8 bank;
Jonas Aaberg222460c2012-06-18 10:35:28 +0200620 int err = 0;
Lee Jones5ff90902013-02-12 14:35:28 +0000621
622 pr_info("Saving all ABB registers at \"ab8500_complete_register_dump\" "
623 "for crash analyze.\n");
624
625 for (bank = 1; bank < AB8500_NUM_BANKS; bank++) {
626 for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
627 u8 reg;
628
629 for (reg = debug_ranges[bank].range[i].first;
630 reg <= debug_ranges[bank].range[i].last;
631 reg++) {
632 u8 value;
Lee Jones5ff90902013-02-12 14:35:28 +0000633
634 err = prcmu_abb_read(bank, reg, &value, 1);
635
Jonas Aaberg222460c2012-06-18 10:35:28 +0200636 if (err < 0)
637 goto out;
638
Lee Jones5ff90902013-02-12 14:35:28 +0000639 ab8500_complete_register_dump[r].bank = bank;
640 ab8500_complete_register_dump[r].reg = reg;
641 ab8500_complete_register_dump[r].value = value;
642
643 r++;
644
645 if (r >= DUMP_MAX_REGS) {
646 pr_err("%s: too many register to dump!\n",
647 __func__);
Jonas Aaberg222460c2012-06-18 10:35:28 +0200648 err = -EINVAL;
649 goto out;
Lee Jones5ff90902013-02-12 14:35:28 +0000650 }
651 }
652 }
653 }
Jonas Aaberg222460c2012-06-18 10:35:28 +0200654out:
655 if (err >= 0)
656 pr_info("Saved all ABB registers.\n");
657 else
658 pr_info("Failed to save all ABB registers.\n");
Lee Jones5ff90902013-02-12 14:35:28 +0000659}
660
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +0100661static int ab8500_all_banks_open(struct inode *inode, struct file *file)
662{
663 struct seq_file *s;
664 int err;
665
666 err = single_open(file, ab8500_print_all_banks, inode->i_private);
667 if (!err) {
668 /* Default buf size in seq_read is not enough */
669 s = (struct seq_file *)file->private_data;
670 s->size = (PAGE_SIZE * 2);
671 s->buf = kmalloc(s->size, GFP_KERNEL);
672 if (!s->buf) {
673 single_release(inode, file);
674 err = -ENOMEM;
675 }
676 }
677 return err;
678}
679
680static const struct file_operations ab8500_all_banks_fops = {
681 .open = ab8500_all_banks_open,
682 .read = seq_read,
683 .llseek = seq_lseek,
684 .release = single_release,
685 .owner = THIS_MODULE,
686};
687
Mattias Wallin5814fc32010-09-13 16:05:04 +0200688static int ab8500_bank_print(struct seq_file *s, void *p)
689{
Mattias Wallincfc08492012-05-28 15:53:58 +0200690 return seq_printf(s, "0x%02X\n", debug_bank);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200691}
692
693static int ab8500_bank_open(struct inode *inode, struct file *file)
694{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100695 return single_open(file, ab8500_bank_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200696}
697
698static ssize_t ab8500_bank_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100699 const char __user *user_buf,
700 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200701{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100702 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +0100703 unsigned long user_bank;
704 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200705
Mattias Wallind7b9f322010-11-26 13:06:39 +0100706 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +0200707 err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100708 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +0200709 return err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200710
Mattias Wallind7b9f322010-11-26 13:06:39 +0100711 if (user_bank >= AB8500_NUM_BANKS) {
712 dev_err(dev, "debugfs error input > number of banks\n");
713 return -EINVAL;
714 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200715
Mattias Wallind7b9f322010-11-26 13:06:39 +0100716 debug_bank = user_bank;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200717
Peter Huewe8504d632011-06-06 22:43:32 +0200718 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200719}
720
721static int ab8500_address_print(struct seq_file *s, void *p)
722{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100723 return seq_printf(s, "0x%02X\n", debug_address);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200724}
725
726static int ab8500_address_open(struct inode *inode, struct file *file)
727{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100728 return single_open(file, ab8500_address_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200729}
730
731static ssize_t ab8500_address_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100732 const char __user *user_buf,
733 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200734{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100735 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +0100736 unsigned long user_address;
737 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200738
Mattias Wallind7b9f322010-11-26 13:06:39 +0100739 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +0200740 err = kstrtoul_from_user(user_buf, count, 0, &user_address);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100741 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +0200742 return err;
743
Mattias Wallind7b9f322010-11-26 13:06:39 +0100744 if (user_address > 0xff) {
745 dev_err(dev, "debugfs error input > 0xff\n");
746 return -EINVAL;
747 }
748 debug_address = user_address;
Peter Huewe8504d632011-06-06 22:43:32 +0200749 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200750}
751
752static int ab8500_val_print(struct seq_file *s, void *p)
753{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100754 struct device *dev = s->private;
755 int ret;
756 u8 regvalue;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200757
Mattias Wallind7b9f322010-11-26 13:06:39 +0100758 ret = abx500_get_register_interruptible(dev,
759 (u8)debug_bank, (u8)debug_address, &regvalue);
760 if (ret < 0) {
761 dev_err(dev, "abx500_get_reg fail %d, %d\n",
762 ret, __LINE__);
763 return -EINVAL;
764 }
765 seq_printf(s, "0x%02X\n", regvalue);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200766
Mattias Wallind7b9f322010-11-26 13:06:39 +0100767 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200768}
769
770static int ab8500_val_open(struct inode *inode, struct file *file)
771{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100772 return single_open(file, ab8500_val_print, inode->i_private);
Mattias Wallin5814fc32010-09-13 16:05:04 +0200773}
774
775static ssize_t ab8500_val_write(struct file *file,
Mattias Wallind7b9f322010-11-26 13:06:39 +0100776 const char __user *user_buf,
777 size_t count, loff_t *ppos)
Mattias Wallin5814fc32010-09-13 16:05:04 +0200778{
Mattias Wallind7b9f322010-11-26 13:06:39 +0100779 struct device *dev = ((struct seq_file *)(file->private_data))->private;
Mattias Wallind7b9f322010-11-26 13:06:39 +0100780 unsigned long user_val;
781 int err;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200782
Mattias Wallind7b9f322010-11-26 13:06:39 +0100783 /* Get userspace string and assure termination */
Peter Huewe8504d632011-06-06 22:43:32 +0200784 err = kstrtoul_from_user(user_buf, count, 0, &user_val);
Mattias Wallind7b9f322010-11-26 13:06:39 +0100785 if (err)
Peter Huewe8504d632011-06-06 22:43:32 +0200786 return err;
787
Mattias Wallind7b9f322010-11-26 13:06:39 +0100788 if (user_val > 0xff) {
789 dev_err(dev, "debugfs error input > 0xff\n");
790 return -EINVAL;
791 }
792 err = abx500_set_register_interruptible(dev,
793 (u8)debug_bank, debug_address, (u8)user_val);
794 if (err < 0) {
795 printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
796 return -EINVAL;
797 }
Mattias Wallin5814fc32010-09-13 16:05:04 +0200798
Peter Huewe8504d632011-06-06 22:43:32 +0200799 return count;
Mattias Wallin5814fc32010-09-13 16:05:04 +0200800}
801
carriere etienne0fbce762011-04-08 16:26:36 +0200802/*
Bengt Jonsson8f0eb432012-02-14 13:01:00 +0100803 * Interrupt status
804 */
805static u32 num_interrupts[AB8500_MAX_NR_IRQS];
806static int num_interrupt_lines;
807
808void ab8500_debug_register_interrupt(int line)
809{
810 if (line < num_interrupt_lines)
811 num_interrupts[line]++;
812}
813
814static int ab8500_interrupts_print(struct seq_file *s, void *p)
815{
816 int line;
817
818 seq_printf(s, "irq: number of\n");
819
820 for (line = 0; line < num_interrupt_lines; line++)
821 seq_printf(s, "%3i: %6i\n", line, num_interrupts[line]);
822
823 return 0;
824}
825
826static int ab8500_interrupts_open(struct inode *inode, struct file *file)
827{
828 return single_open(file, ab8500_interrupts_print, inode->i_private);
829}
830
831/*
carriere etienne0fbce762011-04-08 16:26:36 +0200832 * - HWREG DB8500 formated routines
833 */
834static int ab8500_hwreg_print(struct seq_file *s, void *d)
835{
836 struct device *dev = s->private;
837 int ret;
838 u8 regvalue;
839
840 ret = abx500_get_register_interruptible(dev,
841 (u8)hwreg_cfg.bank, (u8)hwreg_cfg.addr, &regvalue);
842 if (ret < 0) {
843 dev_err(dev, "abx500_get_reg fail %d, %d\n",
844 ret, __LINE__);
845 return -EINVAL;
846 }
847
848 if (hwreg_cfg.shift >= 0)
849 regvalue >>= hwreg_cfg.shift;
850 else
851 regvalue <<= -hwreg_cfg.shift;
852 regvalue &= hwreg_cfg.mask;
853
854 if (REG_FMT_DEC(&hwreg_cfg))
855 seq_printf(s, "%d\n", regvalue);
856 else
857 seq_printf(s, "0x%02X\n", regvalue);
858 return 0;
859}
860
861static int ab8500_hwreg_open(struct inode *inode, struct file *file)
862{
863 return single_open(file, ab8500_hwreg_print, inode->i_private);
864}
865
John Beckett1478a312011-05-31 13:54:27 +0100866static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
867{
868 int bat_ctrl_raw;
869 int bat_ctrl_convert;
870 struct ab8500_gpadc *gpadc;
871
Philippe Langlais8908c042012-04-18 15:52:59 +0200872 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +0000873 bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL,
874 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +0100875 bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +0000876 BAT_CTRL, bat_ctrl_raw);
John Beckett1478a312011-05-31 13:54:27 +0100877
878 return seq_printf(s, "%d,0x%X\n",
879 bat_ctrl_convert, bat_ctrl_raw);
880}
881
882static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
883{
884 return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private);
885}
886
887static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
888 .open = ab8500_gpadc_bat_ctrl_open,
889 .read = seq_read,
890 .llseek = seq_lseek,
891 .release = single_release,
892 .owner = THIS_MODULE,
893};
894
895static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
896{
897 int btemp_ball_raw;
898 int btemp_ball_convert;
899 struct ab8500_gpadc *gpadc;
900
Philippe Langlais8908c042012-04-18 15:52:59 +0200901 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +0000902 btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL,
903 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +0100904 btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL,
Lee Jones73482342013-02-26 10:06:55 +0000905 btemp_ball_raw);
John Beckett1478a312011-05-31 13:54:27 +0100906
907 return seq_printf(s,
908 "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw);
909}
910
911static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
912 struct file *file)
913{
914 return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private);
915}
916
917static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
918 .open = ab8500_gpadc_btemp_ball_open,
919 .read = seq_read,
920 .llseek = seq_lseek,
921 .release = single_release,
922 .owner = THIS_MODULE,
923};
924
925static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p)
926{
927 int main_charger_v_raw;
928 int main_charger_v_convert;
929 struct ab8500_gpadc *gpadc;
930
Philippe Langlais8908c042012-04-18 15:52:59 +0200931 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +0000932 main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V,
933 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +0100934 main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +0000935 MAIN_CHARGER_V, main_charger_v_raw);
John Beckett1478a312011-05-31 13:54:27 +0100936
937 return seq_printf(s, "%d,0x%X\n",
938 main_charger_v_convert, main_charger_v_raw);
939}
940
941static int ab8500_gpadc_main_charger_v_open(struct inode *inode,
942 struct file *file)
943{
944 return single_open(file, ab8500_gpadc_main_charger_v_print,
945 inode->i_private);
946}
947
948static const struct file_operations ab8500_gpadc_main_charger_v_fops = {
949 .open = ab8500_gpadc_main_charger_v_open,
950 .read = seq_read,
951 .llseek = seq_lseek,
952 .release = single_release,
953 .owner = THIS_MODULE,
954};
955
956static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p)
957{
958 int acc_detect1_raw;
959 int acc_detect1_convert;
960 struct ab8500_gpadc *gpadc;
961
Philippe Langlais8908c042012-04-18 15:52:59 +0200962 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +0000963 acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1,
964 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +0100965 acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1,
Lee Jones73482342013-02-26 10:06:55 +0000966 acc_detect1_raw);
John Beckett1478a312011-05-31 13:54:27 +0100967
968 return seq_printf(s, "%d,0x%X\n",
969 acc_detect1_convert, acc_detect1_raw);
970}
971
972static int ab8500_gpadc_acc_detect1_open(struct inode *inode,
973 struct file *file)
974{
975 return single_open(file, ab8500_gpadc_acc_detect1_print,
976 inode->i_private);
977}
978
979static const struct file_operations ab8500_gpadc_acc_detect1_fops = {
980 .open = ab8500_gpadc_acc_detect1_open,
981 .read = seq_read,
982 .llseek = seq_lseek,
983 .release = single_release,
984 .owner = THIS_MODULE,
985};
986
987static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p)
988{
989 int acc_detect2_raw;
990 int acc_detect2_convert;
991 struct ab8500_gpadc *gpadc;
992
Philippe Langlais8908c042012-04-18 15:52:59 +0200993 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +0000994 acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2,
995 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +0100996 acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +0000997 ACC_DETECT2, acc_detect2_raw);
John Beckett1478a312011-05-31 13:54:27 +0100998
999 return seq_printf(s, "%d,0x%X\n",
1000 acc_detect2_convert, acc_detect2_raw);
1001}
1002
1003static int ab8500_gpadc_acc_detect2_open(struct inode *inode,
1004 struct file *file)
1005{
1006 return single_open(file, ab8500_gpadc_acc_detect2_print,
1007 inode->i_private);
1008}
1009
1010static const struct file_operations ab8500_gpadc_acc_detect2_fops = {
1011 .open = ab8500_gpadc_acc_detect2_open,
1012 .read = seq_read,
1013 .llseek = seq_lseek,
1014 .release = single_release,
1015 .owner = THIS_MODULE,
1016};
1017
1018static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p)
1019{
1020 int aux1_raw;
1021 int aux1_convert;
1022 struct ab8500_gpadc *gpadc;
1023
Philippe Langlais8908c042012-04-18 15:52:59 +02001024 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001025 aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1,
1026 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001027 aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1,
Lee Jones73482342013-02-26 10:06:55 +00001028 aux1_raw);
John Beckett1478a312011-05-31 13:54:27 +01001029
1030 return seq_printf(s, "%d,0x%X\n",
1031 aux1_convert, aux1_raw);
1032}
1033
1034static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file)
1035{
1036 return single_open(file, ab8500_gpadc_aux1_print, inode->i_private);
1037}
1038
1039static const struct file_operations ab8500_gpadc_aux1_fops = {
1040 .open = ab8500_gpadc_aux1_open,
1041 .read = seq_read,
1042 .llseek = seq_lseek,
1043 .release = single_release,
1044 .owner = THIS_MODULE,
1045};
1046
1047static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p)
1048{
1049 int aux2_raw;
1050 int aux2_convert;
1051 struct ab8500_gpadc *gpadc;
1052
Philippe Langlais8908c042012-04-18 15:52:59 +02001053 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001054 aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2,
1055 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001056 aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2,
Lee Jones73482342013-02-26 10:06:55 +00001057 aux2_raw);
John Beckett1478a312011-05-31 13:54:27 +01001058
1059 return seq_printf(s, "%d,0x%X\n",
1060 aux2_convert, aux2_raw);
1061}
1062
1063static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file)
1064{
1065 return single_open(file, ab8500_gpadc_aux2_print, inode->i_private);
1066}
1067
1068static const struct file_operations ab8500_gpadc_aux2_fops = {
1069 .open = ab8500_gpadc_aux2_open,
1070 .read = seq_read,
1071 .llseek = seq_lseek,
1072 .release = single_release,
1073 .owner = THIS_MODULE,
1074};
1075
1076static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
1077{
1078 int main_bat_v_raw;
1079 int main_bat_v_convert;
1080 struct ab8500_gpadc *gpadc;
1081
Philippe Langlais8908c042012-04-18 15:52:59 +02001082 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001083 main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V,
1084 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001085 main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V,
Lee Jones73482342013-02-26 10:06:55 +00001086 main_bat_v_raw);
John Beckett1478a312011-05-31 13:54:27 +01001087
1088 return seq_printf(s, "%d,0x%X\n",
1089 main_bat_v_convert, main_bat_v_raw);
1090}
1091
1092static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
1093 struct file *file)
1094{
1095 return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private);
1096}
1097
1098static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
1099 .open = ab8500_gpadc_main_bat_v_open,
1100 .read = seq_read,
1101 .llseek = seq_lseek,
1102 .release = single_release,
1103 .owner = THIS_MODULE,
1104};
1105
1106static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p)
1107{
1108 int vbus_v_raw;
1109 int vbus_v_convert;
1110 struct ab8500_gpadc *gpadc;
1111
Philippe Langlais8908c042012-04-18 15:52:59 +02001112 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001113 vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V,
1114 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001115 vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V,
Lee Jones73482342013-02-26 10:06:55 +00001116 vbus_v_raw);
John Beckett1478a312011-05-31 13:54:27 +01001117
1118 return seq_printf(s, "%d,0x%X\n",
1119 vbus_v_convert, vbus_v_raw);
1120}
1121
1122static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file)
1123{
1124 return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private);
1125}
1126
1127static const struct file_operations ab8500_gpadc_vbus_v_fops = {
1128 .open = ab8500_gpadc_vbus_v_open,
1129 .read = seq_read,
1130 .llseek = seq_lseek,
1131 .release = single_release,
1132 .owner = THIS_MODULE,
1133};
1134
1135static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p)
1136{
1137 int main_charger_c_raw;
1138 int main_charger_c_convert;
1139 struct ab8500_gpadc *gpadc;
1140
Philippe Langlais8908c042012-04-18 15:52:59 +02001141 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001142 main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C,
1143 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001144 main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +00001145 MAIN_CHARGER_C, main_charger_c_raw);
John Beckett1478a312011-05-31 13:54:27 +01001146
1147 return seq_printf(s, "%d,0x%X\n",
1148 main_charger_c_convert, main_charger_c_raw);
1149}
1150
1151static int ab8500_gpadc_main_charger_c_open(struct inode *inode,
1152 struct file *file)
1153{
1154 return single_open(file, ab8500_gpadc_main_charger_c_print,
1155 inode->i_private);
1156}
1157
1158static const struct file_operations ab8500_gpadc_main_charger_c_fops = {
1159 .open = ab8500_gpadc_main_charger_c_open,
1160 .read = seq_read,
1161 .llseek = seq_lseek,
1162 .release = single_release,
1163 .owner = THIS_MODULE,
1164};
1165
1166static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p)
1167{
1168 int usb_charger_c_raw;
1169 int usb_charger_c_convert;
1170 struct ab8500_gpadc *gpadc;
1171
Philippe Langlais8908c042012-04-18 15:52:59 +02001172 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001173 usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C,
1174 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001175 usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +00001176 USB_CHARGER_C, usb_charger_c_raw);
John Beckett1478a312011-05-31 13:54:27 +01001177
1178 return seq_printf(s, "%d,0x%X\n",
1179 usb_charger_c_convert, usb_charger_c_raw);
1180}
1181
1182static int ab8500_gpadc_usb_charger_c_open(struct inode *inode,
1183 struct file *file)
1184{
1185 return single_open(file, ab8500_gpadc_usb_charger_c_print,
1186 inode->i_private);
1187}
1188
1189static const struct file_operations ab8500_gpadc_usb_charger_c_fops = {
1190 .open = ab8500_gpadc_usb_charger_c_open,
1191 .read = seq_read,
1192 .llseek = seq_lseek,
1193 .release = single_release,
1194 .owner = THIS_MODULE,
1195};
1196
1197static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
1198{
1199 int bk_bat_v_raw;
1200 int bk_bat_v_convert;
1201 struct ab8500_gpadc *gpadc;
1202
Philippe Langlais8908c042012-04-18 15:52:59 +02001203 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001204 bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V,
1205 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001206 bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc,
Lee Jones73482342013-02-26 10:06:55 +00001207 BK_BAT_V, bk_bat_v_raw);
John Beckett1478a312011-05-31 13:54:27 +01001208
1209 return seq_printf(s, "%d,0x%X\n",
1210 bk_bat_v_convert, bk_bat_v_raw);
1211}
1212
1213static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
1214{
1215 return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private);
1216}
1217
1218static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
1219 .open = ab8500_gpadc_bk_bat_v_open,
1220 .read = seq_read,
1221 .llseek = seq_lseek,
1222 .release = single_release,
1223 .owner = THIS_MODULE,
1224};
1225
1226static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
1227{
1228 int die_temp_raw;
1229 int die_temp_convert;
1230 struct ab8500_gpadc *gpadc;
1231
Philippe Langlais8908c042012-04-18 15:52:59 +02001232 gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
Lee Jones73482342013-02-26 10:06:55 +00001233 die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP,
1234 avg_sample, trig_edge, trig_timer, conv_type);
John Beckett1478a312011-05-31 13:54:27 +01001235 die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP,
Lee Jones73482342013-02-26 10:06:55 +00001236 die_temp_raw);
John Beckett1478a312011-05-31 13:54:27 +01001237
1238 return seq_printf(s, "%d,0x%X\n",
1239 die_temp_convert, die_temp_raw);
1240}
1241
1242static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
1243{
1244 return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private);
1245}
1246
1247static const struct file_operations ab8500_gpadc_die_temp_fops = {
1248 .open = ab8500_gpadc_die_temp_open,
1249 .read = seq_read,
1250 .llseek = seq_lseek,
1251 .release = single_release,
1252 .owner = THIS_MODULE,
1253};
1254
Lee Jones73482342013-02-26 10:06:55 +00001255static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p)
1256{
1257 return seq_printf(s, "%d\n", avg_sample);
1258}
1259
1260static int ab8500_gpadc_avg_sample_open(struct inode *inode, struct file *file)
1261{
1262 return single_open(file, ab8500_gpadc_avg_sample_print,
1263 inode->i_private);
1264}
1265
1266static ssize_t ab8500_gpadc_avg_sample_write(struct file *file,
1267 const char __user *user_buf,
1268 size_t count, loff_t *ppos)
1269{
1270 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1271 char buf[32];
1272 int buf_size;
1273 unsigned long user_avg_sample;
1274 int err;
1275
1276 /* Get userspace string and assure termination */
1277 buf_size = min(count, (sizeof(buf) - 1));
1278 if (copy_from_user(buf, user_buf, buf_size))
1279 return -EFAULT;
1280 buf[buf_size] = 0;
1281
1282 err = strict_strtoul(buf, 0, &user_avg_sample);
1283 if (err)
1284 return -EINVAL;
1285 if ((user_avg_sample == SAMPLE_1) || (user_avg_sample == SAMPLE_4)
1286 || (user_avg_sample == SAMPLE_8)
1287 || (user_avg_sample == SAMPLE_16)) {
1288 avg_sample = (u8) user_avg_sample;
1289 } else {
1290 dev_err(dev, "debugfs error input: "
1291 "should be egal to 1, 4, 8 or 16\n");
1292 return -EINVAL;
1293 }
1294 return buf_size;
1295}
1296
1297static const struct file_operations ab8500_gpadc_avg_sample_fops = {
1298 .open = ab8500_gpadc_avg_sample_open,
1299 .read = seq_read,
1300 .write = ab8500_gpadc_avg_sample_write,
1301 .llseek = seq_lseek,
1302 .release = single_release,
1303 .owner = THIS_MODULE,
1304};
1305
1306static int ab8500_gpadc_trig_edge_print(struct seq_file *s, void *p)
1307{
1308 return seq_printf(s, "%d\n", trig_edge);
1309}
1310
1311static int ab8500_gpadc_trig_edge_open(struct inode *inode, struct file *file)
1312{
1313 return single_open(file, ab8500_gpadc_trig_edge_print,
1314 inode->i_private);
1315}
1316
1317static ssize_t ab8500_gpadc_trig_edge_write(struct file *file,
1318 const char __user *user_buf,
1319 size_t count, loff_t *ppos)
1320{
1321 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1322 char buf[32];
1323 int buf_size;
1324 unsigned long user_trig_edge;
1325 int err;
1326
1327 /* Get userspace string and assure termination */
1328 buf_size = min(count, (sizeof(buf) - 1));
1329 if (copy_from_user(buf, user_buf, buf_size))
1330 return -EFAULT;
1331 buf[buf_size] = 0;
1332
1333 err = strict_strtoul(buf, 0, &user_trig_edge);
1334 if (err)
1335 return -EINVAL;
1336 if ((user_trig_edge == RISING_EDGE)
1337 || (user_trig_edge == FALLING_EDGE)) {
1338 trig_edge = (u8) user_trig_edge;
1339 } else {
1340 dev_err(dev, "Wrong input:\n"
1341 "Enter 0. Rising edge\n"
1342 "Enter 1. Falling edge\n");
1343 return -EINVAL;
1344 }
1345 return buf_size;
1346}
1347
1348static const struct file_operations ab8500_gpadc_trig_edge_fops = {
1349 .open = ab8500_gpadc_trig_edge_open,
1350 .read = seq_read,
1351 .write = ab8500_gpadc_trig_edge_write,
1352 .llseek = seq_lseek,
1353 .release = single_release,
1354 .owner = THIS_MODULE,
1355};
1356
1357static int ab8500_gpadc_trig_timer_print(struct seq_file *s, void *p)
1358{
1359 return seq_printf(s, "%d\n", trig_timer);
1360}
1361
1362static int ab8500_gpadc_trig_timer_open(struct inode *inode, struct file *file)
1363{
1364 return single_open(file, ab8500_gpadc_trig_timer_print,
1365 inode->i_private);
1366}
1367
1368static ssize_t ab8500_gpadc_trig_timer_write(struct file *file,
1369 const char __user *user_buf,
1370 size_t count, loff_t *ppos)
1371{
1372 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1373 char buf[32];
1374 int buf_size;
1375 unsigned long user_trig_timer;
1376 int err;
1377
1378 /* Get userspace string and assure termination */
1379 buf_size = min(count, (sizeof(buf) - 1));
1380 if (copy_from_user(buf, user_buf, buf_size))
1381 return -EFAULT;
1382 buf[buf_size] = 0;
1383
1384 err = strict_strtoul(buf, 0, &user_trig_timer);
1385 if (err)
1386 return -EINVAL;
1387 if ((user_trig_timer >= 0) && (user_trig_timer <= 255)) {
1388 trig_timer = (u8) user_trig_timer;
1389 } else {
1390 dev_err(dev, "debugfs error input: "
1391 "should be beetween 0 to 255\n");
1392 return -EINVAL;
1393 }
1394 return buf_size;
1395}
1396
1397static const struct file_operations ab8500_gpadc_trig_timer_fops = {
1398 .open = ab8500_gpadc_trig_timer_open,
1399 .read = seq_read,
1400 .write = ab8500_gpadc_trig_timer_write,
1401 .llseek = seq_lseek,
1402 .release = single_release,
1403 .owner = THIS_MODULE,
1404};
1405
1406static int ab8500_gpadc_conv_type_print(struct seq_file *s, void *p)
1407{
1408 return seq_printf(s, "%d\n", conv_type);
1409}
1410
1411static int ab8500_gpadc_conv_type_open(struct inode *inode, struct file *file)
1412{
1413 return single_open(file, ab8500_gpadc_conv_type_print,
1414 inode->i_private);
1415}
1416
1417static ssize_t ab8500_gpadc_conv_type_write(struct file *file,
1418 const char __user *user_buf,
1419 size_t count, loff_t *ppos)
1420{
1421 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1422 char buf[32];
1423 int buf_size;
1424 unsigned long user_conv_type;
1425 int err;
1426
1427 /* Get userspace string and assure termination */
1428 buf_size = min(count, (sizeof(buf) - 1));
1429 if (copy_from_user(buf, user_buf, buf_size))
1430 return -EFAULT;
1431 buf[buf_size] = 0;
1432
1433 err = strict_strtoul(buf, 0, &user_conv_type);
1434 if (err)
1435 return -EINVAL;
1436 if ((user_conv_type == ADC_SW)
1437 || (user_conv_type == ADC_HW)) {
1438 conv_type = (u8) user_conv_type;
1439 } else {
1440 dev_err(dev, "Wrong input:\n"
1441 "Enter 0. ADC SW conversion\n"
1442 "Enter 1. ADC HW conversion\n");
1443 return -EINVAL;
1444 }
1445 return buf_size;
1446}
1447
1448static const struct file_operations ab8500_gpadc_conv_type_fops = {
1449 .open = ab8500_gpadc_conv_type_open,
1450 .read = seq_read,
1451 .write = ab8500_gpadc_conv_type_write,
1452 .llseek = seq_lseek,
1453 .release = single_release,
1454 .owner = THIS_MODULE,
1455};
1456
carriere etienne0fbce762011-04-08 16:26:36 +02001457/*
1458 * return length of an ASCII numerical value, 0 is string is not a
1459 * numerical value.
1460 * string shall start at value 1st char.
1461 * string can be tailed with \0 or space or newline chars only.
1462 * value can be decimal or hexadecimal (prefixed 0x or 0X).
1463 */
1464static int strval_len(char *b)
1465{
1466 char *s = b;
1467 if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) {
1468 s += 2;
1469 for (; *s && (*s != ' ') && (*s != '\n'); s++) {
1470 if (!isxdigit(*s))
1471 return 0;
1472 }
1473 } else {
1474 if (*s == '-')
1475 s++;
1476 for (; *s && (*s != ' ') && (*s != '\n'); s++) {
1477 if (!isdigit(*s))
1478 return 0;
1479 }
1480 }
1481 return (int) (s-b);
1482}
1483
1484/*
1485 * parse hwreg input data.
1486 * update global hwreg_cfg only if input data syntax is ok.
1487 */
1488static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
1489 struct device *dev)
1490{
1491 uint write, val = 0;
1492 u8 regvalue;
1493 int ret;
1494 struct hwreg_cfg loc = {
1495 .bank = 0, /* default: invalid phys addr */
1496 .addr = 0, /* default: invalid phys addr */
1497 .fmt = 0, /* default: 32bit access, hex output */
1498 .mask = 0xFFFFFFFF, /* default: no mask */
1499 .shift = 0, /* default: no bit shift */
1500 };
1501
1502 /* read or write ? */
1503 if (!strncmp(b, "read ", 5)) {
1504 write = 0;
1505 b += 5;
1506 } else if (!strncmp(b, "write ", 6)) {
1507 write = 1;
1508 b += 6;
1509 } else
1510 return -EINVAL;
1511
1512 /* OPTIONS -l|-w|-b -s -m -o */
1513 while ((*b == ' ') || (*b == '-')) {
1514 if (*(b-1) != ' ') {
1515 b++;
1516 continue;
1517 }
1518 if ((!strncmp(b, "-d ", 3)) ||
1519 (!strncmp(b, "-dec ", 5))) {
1520 b += (*(b+2) == ' ') ? 3 : 5;
1521 loc.fmt |= (1<<0);
1522 } else if ((!strncmp(b, "-h ", 3)) ||
1523 (!strncmp(b, "-hex ", 5))) {
1524 b += (*(b+2) == ' ') ? 3 : 5;
1525 loc.fmt &= ~(1<<0);
1526 } else if ((!strncmp(b, "-m ", 3)) ||
1527 (!strncmp(b, "-mask ", 6))) {
1528 b += (*(b+2) == ' ') ? 3 : 6;
1529 if (strval_len(b) == 0)
1530 return -EINVAL;
1531 loc.mask = simple_strtoul(b, &b, 0);
1532 } else if ((!strncmp(b, "-s ", 3)) ||
1533 (!strncmp(b, "-shift ", 7))) {
1534 b += (*(b+2) == ' ') ? 3 : 7;
1535 if (strval_len(b) == 0)
1536 return -EINVAL;
1537 loc.shift = simple_strtol(b, &b, 0);
1538 } else {
1539 return -EINVAL;
1540 }
1541 }
1542 /* get arg BANK and ADDRESS */
1543 if (strval_len(b) == 0)
1544 return -EINVAL;
1545 loc.bank = simple_strtoul(b, &b, 0);
1546 while (*b == ' ')
1547 b++;
1548 if (strval_len(b) == 0)
1549 return -EINVAL;
1550 loc.addr = simple_strtoul(b, &b, 0);
1551
1552 if (write) {
1553 while (*b == ' ')
1554 b++;
1555 if (strval_len(b) == 0)
1556 return -EINVAL;
1557 val = simple_strtoul(b, &b, 0);
1558 }
1559
1560 /* args are ok, update target cfg (mainly for read) */
1561 *cfg = loc;
1562
1563#ifdef ABB_HWREG_DEBUG
1564 pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d"
1565 "value=0x%X\n", (write) ? "write" : "read",
1566 REG_FMT_DEC(cfg) ? "decimal" : "hexa",
1567 cfg->addr, cfg->mask, cfg->shift, val);
1568#endif
1569
1570 if (!write)
1571 return 0;
1572
1573 ret = abx500_get_register_interruptible(dev,
1574 (u8)cfg->bank, (u8)cfg->addr, &regvalue);
1575 if (ret < 0) {
1576 dev_err(dev, "abx500_get_reg fail %d, %d\n",
1577 ret, __LINE__);
1578 return -EINVAL;
1579 }
1580
1581 if (cfg->shift >= 0) {
1582 regvalue &= ~(cfg->mask << (cfg->shift));
1583 val = (val & cfg->mask) << (cfg->shift);
1584 } else {
1585 regvalue &= ~(cfg->mask >> (-cfg->shift));
1586 val = (val & cfg->mask) >> (-cfg->shift);
1587 }
1588 val = val | regvalue;
1589
1590 ret = abx500_set_register_interruptible(dev,
1591 (u8)cfg->bank, (u8)cfg->addr, (u8)val);
1592 if (ret < 0) {
1593 pr_err("abx500_set_reg failed %d, %d", ret, __LINE__);
1594 return -EINVAL;
1595 }
1596
1597 return 0;
1598}
1599
1600static ssize_t ab8500_hwreg_write(struct file *file,
1601 const char __user *user_buf, size_t count, loff_t *ppos)
1602{
1603 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1604 char buf[128];
1605 int buf_size, ret;
1606
1607 /* Get userspace string and assure termination */
1608 buf_size = min(count, (sizeof(buf)-1));
1609 if (copy_from_user(buf, user_buf, buf_size))
1610 return -EFAULT;
1611 buf[buf_size] = 0;
1612
1613 /* get args and process */
1614 ret = hwreg_common_write(buf, &hwreg_cfg, dev);
1615 return (ret) ? ret : buf_size;
1616}
1617
1618/*
1619 * - irq subscribe/unsubscribe stuff
1620 */
Lee Jones4b8ac082013-01-14 16:10:36 +00001621static int ab8500_subscribe_unsubscribe_print(struct seq_file *s, void *p)
1622{
1623 seq_printf(s, "%d\n", irq_first);
1624
1625 return 0;
1626}
1627
1628static int ab8500_subscribe_unsubscribe_open(struct inode *inode,
1629 struct file *file)
1630{
1631 return single_open(file, ab8500_subscribe_unsubscribe_print,
1632 inode->i_private);
1633}
1634
1635/*
Mattias Wallin0b337e72010-11-19 17:55:11 +01001636 * Userspace should use poll() on this file. When an event occur
Lee Jones4b8ac082013-01-14 16:10:36 +00001637 * the blocking poll will be released.
1638 */
1639static ssize_t show_irq(struct device *dev,
1640 struct device_attribute *attr, char *buf)
1641{
Mattias Wallin0b337e72010-11-19 17:55:11 +01001642 unsigned long name;
1643 unsigned int irq_index;
1644 int err;
Lee Jones4b8ac082013-01-14 16:10:36 +00001645
Mattias Wallin0b337e72010-11-19 17:55:11 +01001646 err = strict_strtoul(attr->attr.name, 0, &name);
1647 if (err)
1648 return err;
1649
1650 irq_index = name - irq_first;
Linus Walleijddba25f2012-02-03 11:19:05 +01001651 if (irq_index >= num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +01001652 return -EINVAL;
1653 else
1654 return sprintf(buf, "%u\n", irq_count[irq_index]);
1655}
Lee Jones4b8ac082013-01-14 16:10:36 +00001656
1657static ssize_t ab8500_subscribe_write(struct file *file,
1658 const char __user *user_buf,
1659 size_t count, loff_t *ppos)
1660{
1661 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1662 char buf[32];
1663 int buf_size;
1664 unsigned long user_val;
1665 int err;
Mattias Wallin0b337e72010-11-19 17:55:11 +01001666 unsigned int irq_index;
Lee Jones4b8ac082013-01-14 16:10:36 +00001667
1668 /* Get userspace string and assure termination */
1669 buf_size = min(count, (sizeof(buf)-1));
1670 if (copy_from_user(buf, user_buf, buf_size))
1671 return -EFAULT;
1672 buf[buf_size] = 0;
1673
1674 err = strict_strtoul(buf, 0, &user_val);
1675 if (err)
1676 return -EINVAL;
1677 if (user_val < irq_first) {
1678 dev_err(dev, "debugfs error input < %d\n", irq_first);
1679 return -EINVAL;
1680 }
1681 if (user_val > irq_last) {
1682 dev_err(dev, "debugfs error input > %d\n", irq_last);
1683 return -EINVAL;
1684 }
1685
Mattias Wallin0b337e72010-11-19 17:55:11 +01001686 irq_index = user_val - irq_first;
Linus Walleijddba25f2012-02-03 11:19:05 +01001687 if (irq_index >= num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +01001688 return -EINVAL;
1689
Lee Jones4b8ac082013-01-14 16:10:36 +00001690 /*
Mattias Wallin0b337e72010-11-19 17:55:11 +01001691 * This will create a sysfs file named <irq-nr> which userspace can
Lee Jones4b8ac082013-01-14 16:10:36 +00001692 * use to select or poll and get the AB8500 events
1693 */
Mattias Wallin0b337e72010-11-19 17:55:11 +01001694 dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute),
1695 GFP_KERNEL);
1696 event_name[irq_index] = kmalloc(buf_size, GFP_KERNEL);
1697 sprintf(event_name[irq_index], "%lu", user_val);
1698 dev_attr[irq_index]->show = show_irq;
1699 dev_attr[irq_index]->store = NULL;
1700 dev_attr[irq_index]->attr.name = event_name[irq_index];
1701 dev_attr[irq_index]->attr.mode = S_IRUGO;
1702 err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr);
Lee Jones4b8ac082013-01-14 16:10:36 +00001703 if (err < 0) {
1704 printk(KERN_ERR "sysfs_create_file failed %d\n", err);
1705 return err;
1706 }
1707
1708 err = request_threaded_irq(user_val, NULL, ab8500_debug_handler,
1709 IRQF_SHARED | IRQF_NO_SUSPEND,
1710 "ab8500-debug", &dev->kobj);
1711 if (err < 0) {
1712 printk(KERN_ERR "request_threaded_irq failed %d, %lu\n",
1713 err, user_val);
Mattias Wallin0b337e72010-11-19 17:55:11 +01001714 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
Lee Jones4b8ac082013-01-14 16:10:36 +00001715 return err;
1716 }
1717
1718 return buf_size;
1719}
1720
1721static ssize_t ab8500_unsubscribe_write(struct file *file,
1722 const char __user *user_buf,
1723 size_t count, loff_t *ppos)
1724{
1725 struct device *dev = ((struct seq_file *)(file->private_data))->private;
1726 char buf[32];
1727 int buf_size;
1728 unsigned long user_val;
1729 int err;
Mattias Wallin0b337e72010-11-19 17:55:11 +01001730 unsigned int irq_index;
Lee Jones4b8ac082013-01-14 16:10:36 +00001731
1732 /* Get userspace string and assure termination */
1733 buf_size = min(count, (sizeof(buf)-1));
1734 if (copy_from_user(buf, user_buf, buf_size))
1735 return -EFAULT;
1736 buf[buf_size] = 0;
1737
1738 err = strict_strtoul(buf, 0, &user_val);
1739 if (err)
1740 return -EINVAL;
1741 if (user_val < irq_first) {
1742 dev_err(dev, "debugfs error input < %d\n", irq_first);
1743 return -EINVAL;
1744 }
1745 if (user_val > irq_last) {
1746 dev_err(dev, "debugfs error input > %d\n", irq_last);
1747 return -EINVAL;
1748 }
1749
Mattias Wallin0b337e72010-11-19 17:55:11 +01001750 irq_index = user_val - irq_first;
Linus Walleijddba25f2012-02-03 11:19:05 +01001751 if (irq_index >= num_irqs)
Mattias Wallin0b337e72010-11-19 17:55:11 +01001752 return -EINVAL;
Lee Jones4b8ac082013-01-14 16:10:36 +00001753
Mattias Wallin0b337e72010-11-19 17:55:11 +01001754 /* Set irq count to 0 when unsubscribe */
1755 irq_count[irq_index] = 0;
1756
1757 if (dev_attr[irq_index])
1758 sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
1759
1760
1761 free_irq(user_val, &dev->kobj);
1762 kfree(event_name[irq_index]);
1763 kfree(dev_attr[irq_index]);
Lee Jones4b8ac082013-01-14 16:10:36 +00001764
1765 return buf_size;
1766}
1767
carriere etienne0fbce762011-04-08 16:26:36 +02001768/*
1769 * - several deubgfs nodes fops
1770 */
1771
Mattias Wallin5814fc32010-09-13 16:05:04 +02001772static const struct file_operations ab8500_bank_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001773 .open = ab8500_bank_open,
1774 .write = ab8500_bank_write,
1775 .read = seq_read,
1776 .llseek = seq_lseek,
1777 .release = single_release,
1778 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001779};
1780
1781static const struct file_operations ab8500_address_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001782 .open = ab8500_address_open,
1783 .write = ab8500_address_write,
1784 .read = seq_read,
1785 .llseek = seq_lseek,
1786 .release = single_release,
1787 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001788};
1789
1790static const struct file_operations ab8500_val_fops = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01001791 .open = ab8500_val_open,
1792 .write = ab8500_val_write,
1793 .read = seq_read,
1794 .llseek = seq_lseek,
1795 .release = single_release,
1796 .owner = THIS_MODULE,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001797};
1798
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001799static const struct file_operations ab8500_interrupts_fops = {
1800 .open = ab8500_interrupts_open,
1801 .read = seq_read,
1802 .llseek = seq_lseek,
1803 .release = single_release,
1804 .owner = THIS_MODULE,
1805};
1806
Lee Jones4b8ac082013-01-14 16:10:36 +00001807static const struct file_operations ab8500_subscribe_fops = {
1808 .open = ab8500_subscribe_unsubscribe_open,
1809 .write = ab8500_subscribe_write,
1810 .read = seq_read,
1811 .llseek = seq_lseek,
1812 .release = single_release,
1813 .owner = THIS_MODULE,
1814};
1815
1816static const struct file_operations ab8500_unsubscribe_fops = {
1817 .open = ab8500_subscribe_unsubscribe_open,
1818 .write = ab8500_unsubscribe_write,
1819 .read = seq_read,
1820 .llseek = seq_lseek,
1821 .release = single_release,
1822 .owner = THIS_MODULE,
1823};
1824
carriere etienne0fbce762011-04-08 16:26:36 +02001825static const struct file_operations ab8500_hwreg_fops = {
1826 .open = ab8500_hwreg_open,
1827 .write = ab8500_hwreg_write,
1828 .read = seq_read,
1829 .llseek = seq_lseek,
1830 .release = single_release,
1831 .owner = THIS_MODULE,
1832};
1833
Mattias Wallin5814fc32010-09-13 16:05:04 +02001834static struct dentry *ab8500_dir;
John Beckett1478a312011-05-31 13:54:27 +01001835static struct dentry *ab8500_gpadc_dir;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001836
Bill Pembertonf791be42012-11-19 13:23:04 -05001837static int ab8500_debug_probe(struct platform_device *plf)
Mattias Wallin5814fc32010-09-13 16:05:04 +02001838{
carriere etienne0fbce762011-04-08 16:26:36 +02001839 struct dentry *file;
Linus Walleijddba25f2012-02-03 11:19:05 +01001840 int ret = -ENOMEM;
1841 struct ab8500 *ab8500;
Mattias Wallind7b9f322010-11-26 13:06:39 +01001842 debug_bank = AB8500_MISC;
1843 debug_address = AB8500_REV_REG & 0x00FF;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001844
Linus Walleijddba25f2012-02-03 11:19:05 +01001845 ab8500 = dev_get_drvdata(plf->dev.parent);
1846 num_irqs = ab8500->mask_size;
1847
Ashok G70bad042012-02-28 10:21:00 +05301848 irq_count = kzalloc(sizeof(*irq_count)*num_irqs, GFP_KERNEL);
Linus Walleijddba25f2012-02-03 11:19:05 +01001849 if (!irq_count)
1850 return -ENOMEM;
1851
1852 dev_attr = kzalloc(sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
1853 if (!dev_attr)
1854 goto out_freeirq_count;
1855
1856 event_name = kzalloc(sizeof(*event_name)*num_irqs, GFP_KERNEL);
1857 if (!event_name)
1858 goto out_freedev_attr;
1859
Lee Jones4b8ac082013-01-14 16:10:36 +00001860 irq_first = platform_get_irq_byname(plf, "IRQ_FIRST");
1861 if (irq_first < 0) {
1862 dev_err(&plf->dev, "First irq not found, err %d\n",
John Beckett1478a312011-05-31 13:54:27 +01001863 irq_first);
Linus Walleijddba25f2012-02-03 11:19:05 +01001864 ret = irq_first;
1865 goto out_freeevent_name;
Lee Jones4b8ac082013-01-14 16:10:36 +00001866 }
1867
1868 irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
1869 if (irq_last < 0) {
1870 dev_err(&plf->dev, "Last irq not found, err %d\n",
John Beckett1478a312011-05-31 13:54:27 +01001871 irq_last);
Linus Walleijddba25f2012-02-03 11:19:05 +01001872 ret = irq_last;
1873 goto out_freeevent_name;
Lee Jones4b8ac082013-01-14 16:10:36 +00001874 }
1875
Mattias Wallind7b9f322010-11-26 13:06:39 +01001876 ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL);
1877 if (!ab8500_dir)
carriere etienne0fbce762011-04-08 16:26:36 +02001878 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001879
John Beckett1478a312011-05-31 13:54:27 +01001880 ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING,
1881 ab8500_dir);
1882 if (!ab8500_gpadc_dir)
1883 goto err;
1884
1885 file = debugfs_create_file("all-bank-registers", S_IRUGO,
1886 ab8500_dir, &plf->dev, &ab8500_registers_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001887 if (!file)
1888 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001889
Mian Yousaf Kaukab42002c62012-01-26 15:39:20 +01001890 file = debugfs_create_file("all-banks", S_IRUGO,
1891 ab8500_dir, &plf->dev, &ab8500_all_banks_fops);
1892 if (!file)
1893 goto err;
1894
John Beckett1478a312011-05-31 13:54:27 +01001895 file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR),
1896 ab8500_dir, &plf->dev, &ab8500_bank_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001897 if (!file)
1898 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001899
John Beckett1478a312011-05-31 13:54:27 +01001900 file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR),
1901 ab8500_dir, &plf->dev, &ab8500_address_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001902 if (!file)
1903 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001904
John Beckett1478a312011-05-31 13:54:27 +01001905 file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR),
1906 ab8500_dir, &plf->dev, &ab8500_val_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001907 if (!file)
1908 goto err;
Mattias Wallin5814fc32010-09-13 16:05:04 +02001909
John Beckett1478a312011-05-31 13:54:27 +01001910 file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR),
1911 ab8500_dir, &plf->dev, &ab8500_subscribe_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001912 if (!file)
1913 goto err;
Lee Jones4b8ac082013-01-14 16:10:36 +00001914
Bengt Jonsson8f0eb432012-02-14 13:01:00 +01001915 if (is_ab8500(ab8500))
1916 num_interrupt_lines = AB8500_NR_IRQS;
1917 else if (is_ab8505(ab8500))
1918 num_interrupt_lines = AB8505_NR_IRQS;
1919 else if (is_ab9540(ab8500))
1920 num_interrupt_lines = AB9540_NR_IRQS;
1921
1922 file = debugfs_create_file("interrupts", (S_IRUGO),
1923 ab8500_dir, &plf->dev, &ab8500_interrupts_fops);
1924 if (!file)
1925 goto err;
1926
John Beckett1478a312011-05-31 13:54:27 +01001927 file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR),
1928 ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001929 if (!file)
1930 goto err;
1931
John Beckett1478a312011-05-31 13:54:27 +01001932 file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR),
1933 ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
1934 if (!file)
1935 goto err;
1936
1937 file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR),
1938 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops);
1939 if (!file)
1940 goto err;
1941
1942 file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR),
1943 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops);
1944 if (!file)
1945 goto err;
1946
1947 file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR),
1948 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops);
1949 if (!file)
1950 goto err;
1951
1952 file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR),
1953 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops);
1954 if (!file)
1955 goto err;
1956
1957 file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR),
1958 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops);
1959 if (!file)
1960 goto err;
1961
1962 file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR),
1963 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops);
1964 if (!file)
1965 goto err;
1966
1967 file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR),
1968 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops);
1969 if (!file)
1970 goto err;
1971
1972 file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR),
1973 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops);
1974 if (!file)
1975 goto err;
1976
1977 file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR),
1978 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops);
1979 if (!file)
1980 goto err;
1981
1982 file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR),
1983 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops);
1984 if (!file)
1985 goto err;
1986
1987 file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR),
1988 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
1989 if (!file)
1990 goto err;
1991
1992 file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR),
1993 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops);
1994 if (!file)
1995 goto err;
1996
1997 file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR),
1998 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops);
carriere etienne0fbce762011-04-08 16:26:36 +02001999 if (!file)
2000 goto err;
Lee Jones4b8ac082013-01-14 16:10:36 +00002001
Lee Jones73482342013-02-26 10:06:55 +00002002 file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUGO),
2003 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_avg_sample_fops);
2004 if (!file)
2005 goto err;
2006
2007 file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUGO),
2008 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_edge_fops);
2009 if (!file)
2010 goto err;
2011
2012 file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUGO),
2013 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_timer_fops);
2014 if (!file)
2015 goto err;
2016
2017 file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUGO),
2018 ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_conv_type_fops);
2019 if (!file)
2020 goto err;
2021
Mattias Wallind7b9f322010-11-26 13:06:39 +01002022 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002023
carriere etienne0fbce762011-04-08 16:26:36 +02002024err:
2025 if (ab8500_dir)
2026 debugfs_remove_recursive(ab8500_dir);
Mattias Wallind7b9f322010-11-26 13:06:39 +01002027 dev_err(&plf->dev, "failed to create debugfs entries.\n");
Linus Walleijddba25f2012-02-03 11:19:05 +01002028out_freeevent_name:
2029 kfree(event_name);
2030out_freedev_attr:
2031 kfree(dev_attr);
2032out_freeirq_count:
2033 kfree(irq_count);
2034
2035 return ret;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002036}
2037
Bill Pemberton4740f732012-11-19 13:26:01 -05002038static int ab8500_debug_remove(struct platform_device *plf)
Mattias Wallin5814fc32010-09-13 16:05:04 +02002039{
carriere etienne0fbce762011-04-08 16:26:36 +02002040 debugfs_remove_recursive(ab8500_dir);
Linus Walleijddba25f2012-02-03 11:19:05 +01002041 kfree(event_name);
2042 kfree(dev_attr);
2043 kfree(irq_count);
2044
Mattias Wallind7b9f322010-11-26 13:06:39 +01002045 return 0;
Mattias Wallin5814fc32010-09-13 16:05:04 +02002046}
2047
2048static struct platform_driver ab8500_debug_driver = {
Mattias Wallind7b9f322010-11-26 13:06:39 +01002049 .driver = {
2050 .name = "ab8500-debug",
2051 .owner = THIS_MODULE,
2052 },
2053 .probe = ab8500_debug_probe,
Bill Pemberton84449212012-11-19 13:20:24 -05002054 .remove = ab8500_debug_remove
Mattias Wallin5814fc32010-09-13 16:05:04 +02002055};
2056
2057static int __init ab8500_debug_init(void)
2058{
Mattias Wallind7b9f322010-11-26 13:06:39 +01002059 return platform_driver_register(&ab8500_debug_driver);
Mattias Wallin5814fc32010-09-13 16:05:04 +02002060}
2061
2062static void __exit ab8500_debug_exit(void)
2063{
Mattias Wallind7b9f322010-11-26 13:06:39 +01002064 platform_driver_unregister(&ab8500_debug_driver);
Mattias Wallin5814fc32010-09-13 16:05:04 +02002065}
2066subsys_initcall(ab8500_debug_init);
2067module_exit(ab8500_debug_exit);
2068
2069MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
2070MODULE_DESCRIPTION("AB8500 DEBUG");
2071MODULE_LICENSE("GPL v2");