blob: 27df09333eaabab4b61338f05ab26db6ba670766 [file] [log] [blame]
Kenneth Heitke42120dc2013-04-29 16:00:59 -06001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Kenneth Heitke98661912012-09-19 18:51:40 -06002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13/**
14 * SPMI Debug-fs support.
15 *
16 * Hierarchy schema:
17 * /sys/kernel/debug/spmi
18 * /help -- static help text
19 * /spmi-0
20 * /spmi-0/address -- Starting register address for reads or writes
21 * /spmi-0/count -- number of registers to read (only on read)
22 * /spmi-0/data -- Triggers the SPMI formatted read.
23 * /spmi-0/data_raw -- Triggers the SPMI raw read or write
24 * /spmi-#
25 */
26
Kenneth Heitke98661912012-09-19 18:51:40 -060027#define pr_fmt(fmt) "%s:%d: " fmt, __func__, __LINE__
28
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/slab.h>
32#include <linux/uaccess.h>
33#include <linux/spinlock.h>
34#include <linux/string.h>
35#include <linux/debugfs.h>
36#include <linux/spmi.h>
37#include <linux/ctype.h>
Kenneth Heitke5998fab2013-01-22 16:09:19 -070038#include "spmi-dbgfs.h"
Kenneth Heitke98661912012-09-19 18:51:40 -060039
40#define ADDR_LEN 6 /* 5 byte address + 1 space character */
41#define CHARS_PER_ITEM 3 /* Format is 'XX ' */
42#define ITEMS_PER_LINE 16 /* 16 data items per line */
43#define MAX_LINE_LENGTH (ADDR_LEN + (ITEMS_PER_LINE * CHARS_PER_ITEM) + 1)
44#define MAX_REG_PER_TRANSACTION (8)
45
46static const char *DFS_ROOT_NAME = "spmi";
47static const mode_t DFS_MODE = S_IRUSR | S_IWUSR;
48
49/* Log buffer */
50struct spmi_log_buffer {
51 u32 rpos; /* Current 'read' position in buffer */
52 u32 wpos; /* Current 'write' position in buffer */
53 u32 len; /* Length of the buffer */
54 char data[0]; /* Log buffer */
55};
56
57/* SPMI controller specific data */
58struct spmi_ctrl_data {
59 u32 cnt;
60 u32 addr;
Kenneth Heitke5998fab2013-01-22 16:09:19 -070061 struct dentry *dir;
Kenneth Heitke98661912012-09-19 18:51:40 -060062 struct list_head node;
63 struct spmi_controller *ctrl;
64};
65
66/* SPMI transaction parameters */
67struct spmi_trans {
68 u32 cnt; /* Number of bytes to read */
69 u32 addr; /* 20-bit address: SID + PID + Register offset */
70 u32 offset; /* Offset of last read data */
71 bool raw_data; /* Set to true for raw data dump */
72 struct spmi_controller *ctrl;
73 struct spmi_log_buffer *log; /* log buffer */
74};
75
76struct spmi_dbgfs {
77 struct dentry *root;
78 struct mutex lock;
79 struct list_head ctrl; /* List of spmi_ctrl_data nodes */
80 struct debugfs_blob_wrapper help_msg;
81};
82
83static struct spmi_dbgfs dbgfs_data = {
84 .lock = __MUTEX_INITIALIZER(dbgfs_data.lock),
85 .ctrl = LIST_HEAD_INIT(dbgfs_data.ctrl),
86 .help_msg = {
87 .data =
88"SPMI Debug-FS support\n"
89"\n"
90"Hierarchy schema:\n"
91"/sys/kernel/debug/spmi\n"
92" /help -- Static help text\n"
93" /spmi-0 -- Directory for SPMI bus 0\n"
94" /spmi-0/address -- Starting register address for reads or writes\n"
95" /spmi-0/count -- Number of registers to read (only used for reads)\n"
96" /spmi-0/data -- Initiates the SPMI read (formatted output)\n"
97" /spmi-0/data_raw -- Initiates the SPMI raw read or write\n"
98" /spmi-n -- Directory for SPMI bus n\n"
99"\n"
100"To perform SPMI read or write transactions, you need to first write the\n"
101"address of the slave device register to the 'address' file. For read\n"
102"transactions, the number of bytes to be read needs to be written to the\n"
103"'count' file.\n"
104"\n"
105"The 'address' file specifies the 20-bit address of a slave device register.\n"
106"The upper 4 bits 'address[19..16]' specify the slave identifier (SID) for\n"
107"the slave device. The lower 16 bits specify the slave register address.\n"
108"\n"
109"Reading from the 'data' file will initiate a SPMI read transaction starting\n"
110"from slave register 'address' for 'count' number of bytes.\n"
111"\n"
112"Writing to the 'data' file will initiate a SPMI write transaction starting\n"
113"from slave register 'address'. The number of registers written to will\n"
114"match the number of bytes written to the 'data' file.\n"
115"\n"
116"Example: Read 4 bytes starting at register address 0x1234 for SID 2\n"
117"\n"
118"echo 0x21234 > address\n"
119"echo 4 > count\n"
120"cat data\n"
121"\n"
122"Example: Write 3 bytes starting at register address 0x1008 for SID 1\n"
123"\n"
124"echo 0x11008 > address\n"
125"echo 0x01 0x02 0x03 > data\n"
126"\n"
127"Note that the count file is not used for writes. Since 3 bytes are\n"
128"written to the 'data' file, then 3 bytes will be written across the\n"
129"SPMI bus.\n\n",
130 },
131};
132
133static int spmi_dfs_open(struct spmi_ctrl_data *ctrl_data, struct file *file)
134{
135 struct spmi_log_buffer *log;
136 struct spmi_trans *trans;
137
138 size_t logbufsize = SZ_4K;
139
140 if (!ctrl_data) {
141 pr_err("No SPMI controller data\n");
142 return -EINVAL;
143 }
144
145 /* Per file "transaction" data */
146 trans = kzalloc(sizeof(*trans), GFP_KERNEL);
147
148 if (!trans) {
149 pr_err("Unable to allocate memory for transaction data\n");
150 return -ENOMEM;
151 }
152
153 /* Allocate log buffer */
154 log = kzalloc(logbufsize, GFP_KERNEL);
155
156 if (!log) {
157 kfree(trans);
158 pr_err("Unable to allocate memory for log buffer\n");
159 return -ENOMEM;
160 }
161
162 log->rpos = 0;
163 log->wpos = 0;
164 log->len = logbufsize - sizeof(*log);
165
166 trans->log = log;
167 trans->cnt = ctrl_data->cnt;
168 trans->addr = ctrl_data->addr;
169 trans->ctrl = ctrl_data->ctrl;
170 trans->offset = trans->addr;
171
172 file->private_data = trans;
173 return 0;
174}
175
176static int spmi_dfs_data_open(struct inode *inode, struct file *file)
177{
178 struct spmi_ctrl_data *ctrl_data = inode->i_private;
179 return spmi_dfs_open(ctrl_data, file);
180}
181
182static int spmi_dfs_raw_data_open(struct inode *inode, struct file *file)
183{
184 int rc;
185 struct spmi_trans *trans;
186 struct spmi_ctrl_data *ctrl_data = inode->i_private;
187
188 rc = spmi_dfs_open(ctrl_data, file);
189 trans = file->private_data;
190 trans->raw_data = true;
191 return rc;
192}
193
194static int spmi_dfs_close(struct inode *inode, struct file *file)
195{
196 struct spmi_trans *trans = file->private_data;
197
198 if (trans && trans->log) {
199 file->private_data = NULL;
200 kfree(trans->log);
201 kfree(trans);
202 }
203
204 return 0;
205}
206
207/**
208 * spmi_read_data: reads data across the SPMI bus
209 * @ctrl: The SPMI controller
210 * @buf: buffer to store the data read.
211 * @offset: SPMI address offset to start reading from.
212 * @cnt: The number of bytes to read.
213 *
214 * Returns 0 on success, otherwise returns error code from SPMI driver.
215 */
216static int
217spmi_read_data(struct spmi_controller *ctrl, uint8_t *buf, int offset, int cnt)
218{
219 int ret = 0;
220 int len;
221 uint8_t sid;
222 uint16_t addr;
223
224 while (cnt > 0) {
225 sid = (offset >> 16) & 0xF;
226 addr = offset & 0xFFFF;
227 len = min(cnt, MAX_REG_PER_TRANSACTION);
228
229 ret = spmi_ext_register_readl(ctrl, sid, addr, buf, len);
230 if (ret < 0) {
231 pr_err("SPMI read failed, err = %d\n", ret);
232 goto done;
233 }
234
235 cnt -= len;
236 buf += len;
237 offset += len;
238 }
239
240done:
241 return ret;
242}
243
244/**
245 * spmi_write_data: writes data across the SPMI bus
246 * @ctrl: The SPMI controller
247 * @buf: data to be written.
248 * @offset: SPMI address offset to start writing to.
249 * @cnt: The number of bytes to write.
250 *
251 * Returns 0 on success, otherwise returns error code from SPMI driver.
252 */
253static int
254spmi_write_data(struct spmi_controller *ctrl, uint8_t *buf, int offset, int cnt)
255{
256 int ret = 0;
257 int len;
258 uint8_t sid;
259 uint16_t addr;
260
261 while (cnt > 0) {
262 sid = (offset >> 16) & 0xF;
263 addr = offset & 0xFFFF;
264 len = min(cnt, MAX_REG_PER_TRANSACTION);
265
266 ret = spmi_ext_register_writel(ctrl, sid, addr, buf, len);
267 if (ret < 0) {
268 pr_err("SPMI write failed, err = %d\n", ret);
269 goto done;
270 }
271
272 cnt -= len;
273 buf += len;
274 offset += len;
275 }
276
277done:
278 return ret;
279}
280
281/**
282 * print_to_log: format a string and place into the log buffer
283 * @log: The log buffer to place the result into.
284 * @fmt: The format string to use.
285 * @...: The arguments for the format string.
286 *
287 * The return value is the number of characters written to @log buffer
288 * not including the trailing '\0'.
289 */
290static int print_to_log(struct spmi_log_buffer *log, const char *fmt, ...)
291{
292 va_list args;
293 int cnt;
294 char *buf = &log->data[log->wpos];
295 size_t size = log->len - log->wpos;
296
297 va_start(args, fmt);
298 cnt = vscnprintf(buf, size, fmt, args);
299 va_end(args);
300
301 log->wpos += cnt;
302 return cnt;
303}
304
305/**
306 * write_next_line_to_log: Writes a single "line" of data into the log buffer
307 * @trans: Pointer to SPMI transaction data.
308 * @offset: SPMI address offset to start reading from.
309 * @pcnt: Pointer to 'cnt' variable. Indicates the number of bytes to read.
310 *
311 * The 'offset' is a 20-bits SPMI address which includes a 4-bit slave id (SID),
312 * an 8-bit peripheral id (PID), and an 8-bit peripheral register address.
313 *
314 * On a successful read, the pcnt is decremented by the number of data
315 * bytes read across the SPMI bus. When the cnt reaches 0, all requested
316 * bytes have been read.
317 */
318static int
319write_next_line_to_log(struct spmi_trans *trans, int offset, size_t *pcnt)
320{
321 int i, j;
322 u8 data[ITEMS_PER_LINE];
323 struct spmi_log_buffer *log = trans->log;
324
325 int cnt = 0;
326 int padding = offset % ITEMS_PER_LINE;
327 int items_to_read = min(ARRAY_SIZE(data) - padding, *pcnt);
328 int items_to_log = min(ITEMS_PER_LINE, padding + items_to_read);
329
330 /* Buffer needs enough space for an entire line */
331 if ((log->len - log->wpos) < MAX_LINE_LENGTH)
332 goto done;
333
334 /* Read the desired number of "items" */
335 if (spmi_read_data(trans->ctrl, data, offset, items_to_read))
336 goto done;
337
338 *pcnt -= items_to_read;
339
340 /* Each line starts with the aligned offset (20-bit address) */
341 cnt = print_to_log(log, "%5.5X ", offset & 0xffff0);
342 if (cnt == 0)
343 goto done;
344
345 /* If the offset is unaligned, add padding to right justify items */
346 for (i = 0; i < padding; ++i) {
347 cnt = print_to_log(log, "-- ");
348 if (cnt == 0)
349 goto done;
350 }
351
352 /* Log the data items */
353 for (j = 0; i < items_to_log; ++i, ++j) {
354 cnt = print_to_log(log, "%2.2X ", data[j]);
355 if (cnt == 0)
356 goto done;
357 }
358
359 /* If the last character was a space, then replace it with a newline */
360 if (log->wpos > 0 && log->data[log->wpos - 1] == ' ')
361 log->data[log->wpos - 1] = '\n';
362
363done:
364 return cnt;
365}
366
367/**
368 * write_raw_data_to_log: Writes a single "line" of data into the log buffer
369 * @trans: Pointer to SPMI transaction data.
370 * @offset: SPMI address offset to start reading from.
371 * @pcnt: Pointer to 'cnt' variable. Indicates the number of bytes to read.
372 *
373 * The 'offset' is a 20-bits SPMI address which includes a 4-bit slave id (SID),
374 * an 8-bit peripheral id (PID), and an 8-bit peripheral register address.
375 *
376 * On a successful read, the pcnt is decremented by the number of data
377 * bytes read across the SPMI bus. When the cnt reaches 0, all requested
378 * bytes have been read.
379 */
380static int
381write_raw_data_to_log(struct spmi_trans *trans, int offset, size_t *pcnt)
382{
383 u8 data[16];
384 struct spmi_log_buffer *log = trans->log;
385
386 int i;
387 int cnt = 0;
388 int items_to_read = min(ARRAY_SIZE(data), *pcnt);
389
390 /* Buffer needs enough space for an entire line */
391 if ((log->len - log->wpos) < 80)
392 goto done;
393
394 /* Read the desired number of "items" */
395 if (spmi_read_data(trans->ctrl, data, offset, items_to_read))
396 goto done;
397
398 *pcnt -= items_to_read;
399
400 /* Log the data items */
401 for (i = 0; i < items_to_read; ++i) {
402 cnt = print_to_log(log, "0x%2.2X ", data[i]);
403 if (cnt == 0)
404 goto done;
405 }
406
407 /* If the last character was a space, then replace it with a newline */
408 if (log->wpos > 0 && log->data[log->wpos - 1] == ' ')
409 log->data[log->wpos - 1] = '\n';
410
411done:
412 return cnt;
413}
414
415/**
416 * get_log_data - reads data across the SPMI bus and saves to the log buffer
417 * @trans: Pointer to SPMI transaction data.
418 *
419 * Returns the number of "items" read or SPMI error code for read failures.
420 */
421static int get_log_data(struct spmi_trans *trans)
422{
423 int cnt;
424 int last_cnt;
425 int items_read;
426 int total_items_read = 0;
427 u32 offset = trans->offset;
428 size_t item_cnt = trans->cnt;
429 struct spmi_log_buffer *log = trans->log;
430 int (*write_to_log)(struct spmi_trans *, int, size_t *);
431
432 if (item_cnt == 0)
433 return 0;
434
435 if (trans->raw_data)
436 write_to_log = write_raw_data_to_log;
437 else
438 write_to_log = write_next_line_to_log;
439
440 /* Reset the log buffer 'pointers' */
441 log->wpos = log->rpos = 0;
442
443 /* Keep reading data until the log is full */
444 do {
445 last_cnt = item_cnt;
446 cnt = write_to_log(trans, offset, &item_cnt);
447 items_read = last_cnt - item_cnt;
448 offset += items_read;
449 total_items_read += items_read;
450 } while (cnt && item_cnt > 0);
451
452 /* Adjust the transaction offset and count */
453 trans->cnt = item_cnt;
454 trans->offset += total_items_read;
455
456 return total_items_read;
457}
458
459/**
460 * spmi_dfs_reg_write: write user's byte array (coded as string) over SPMI.
461 * @file: file pointer
462 * @buf: user data to be written.
463 * @count: maximum space available in @buf
464 * @ppos: starting position
465 * @return number of user byte written, or negative error value
466 */
467static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf,
468 size_t count, loff_t *ppos)
469{
470 int bytes_read;
471 int data;
472 int pos = 0;
473 int cnt = 0;
474 u8 *values;
475 size_t ret = 0;
476
477 struct spmi_trans *trans = file->private_data;
478 u32 offset = trans->offset;
479
480 /* Make a copy of the user data */
481 char *kbuf = kmalloc(count + 1, GFP_KERNEL);
482 if (!kbuf)
483 return -ENOMEM;
484
485 ret = copy_from_user(kbuf, buf, count);
486 if (ret == count) {
487 pr_err("failed to copy data from user\n");
488 ret = -EFAULT;
489 goto free_buf;
490 }
491
492 count -= ret;
493 *ppos += count;
494 kbuf[count] = '\0';
495
496 /* Override the text buffer with the raw data */
497 values = kbuf;
498
499 /* Parse the data in the buffer. It should be a string of numbers */
500 while (sscanf(kbuf + pos, "%i%n", &data, &bytes_read) == 1) {
501 pos += bytes_read;
502 values[cnt++] = data & 0xff;
503 }
504
505 if (!cnt)
506 goto free_buf;
507
508 /* Perform the SPMI write(s) */
509 ret = spmi_write_data(trans->ctrl, values, offset, cnt);
510
511 if (ret) {
512 pr_err("SPMI write failed, err = %zu\n", ret);
513 } else {
514 ret = count;
515 trans->offset += cnt;
516 }
517
518free_buf:
519 kfree(kbuf);
520 return ret;
521}
522
523/**
524 * spmi_dfs_reg_read: reads value(s) over SPMI and fill user's buffer a
525 * byte array (coded as string)
526 * @file: file pointer
527 * @buf: where to put the result
528 * @count: maximum space available in @buf
529 * @ppos: starting position
530 * @return number of user bytes read, or negative error value
531 */
532static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf,
533 size_t count, loff_t *ppos)
534{
535 struct spmi_trans *trans = file->private_data;
536 struct spmi_log_buffer *log = trans->log;
537 size_t ret;
538 size_t len;
539
540 /* Is the the log buffer empty */
541 if (log->rpos >= log->wpos) {
542 if (get_log_data(trans) <= 0)
543 return 0;
544 }
545
546 len = min(count, log->wpos - log->rpos);
547
548 ret = copy_to_user(buf, &log->data[log->rpos], len);
549 if (ret == len) {
550 pr_err("error copy SPMI register values to user\n");
551 return -EFAULT;
552 }
553
554 /* 'ret' is the number of bytes not copied */
555 len -= ret;
556
557 *ppos += len;
558 log->rpos += len;
559 return len;
560}
561
562static const struct file_operations spmi_dfs_reg_fops = {
563 .open = spmi_dfs_data_open,
564 .release = spmi_dfs_close,
565 .read = spmi_dfs_reg_read,
566 .write = spmi_dfs_reg_write,
567};
568
569static const struct file_operations spmi_dfs_raw_data_fops = {
570 .open = spmi_dfs_raw_data_open,
571 .release = spmi_dfs_close,
572 .read = spmi_dfs_reg_read,
573 .write = spmi_dfs_reg_write,
574};
575
576/**
577 * spmi_dfs_create_fs: create debugfs file system.
578 * @return pointer to root directory or NULL if failed to create fs
579 */
580static struct dentry *spmi_dfs_create_fs(void)
581{
582 struct dentry *root, *file;
583
Kenneth Heitke42120dc2013-04-29 16:00:59 -0600584 pr_debug("Creating SPMI debugfs file-system\n");
Kenneth Heitke98661912012-09-19 18:51:40 -0600585 root = debugfs_create_dir(DFS_ROOT_NAME, NULL);
586 if (IS_ERR(root)) {
587 pr_err("Error creating top level directory err:%ld",
588 (long)root);
589 if ((int)root == -ENODEV)
590 pr_err("debugfs is not enabled in the kernel");
591 return NULL;
592 }
593
594 dbgfs_data.help_msg.size = strlen(dbgfs_data.help_msg.data);
595
596 file = debugfs_create_blob("help", S_IRUGO, root, &dbgfs_data.help_msg);
597 if (!file) {
598 pr_err("error creating help entry\n");
599 goto err_remove_fs;
600 }
601 return root;
602
603err_remove_fs:
604 debugfs_remove_recursive(root);
605 return NULL;
606}
607
608/**
609 * spmi_dfs_get_root: return a pointer to SPMI debugfs root directory.
610 * @brief return a pointer to the existing directory, or if no root
611 * directory exists then create one. Directory is created with file that
612 * configures SPMI transaction, namely: sid, address, and count.
613 * @returns valid pointer on success or NULL
614 */
615struct dentry *spmi_dfs_get_root(void)
616{
617 if (dbgfs_data.root)
618 return dbgfs_data.root;
619
620 if (mutex_lock_interruptible(&dbgfs_data.lock) < 0)
621 return NULL;
622 /* critical section */
623 if (!dbgfs_data.root) { /* double checking idiom */
624 dbgfs_data.root = spmi_dfs_create_fs();
625 }
626 mutex_unlock(&dbgfs_data.lock);
627 return dbgfs_data.root;
628}
629
630/*
631 * spmi_dfs_add_controller: adds new spmi controller entry
632 * @return zero on success
633 */
634int spmi_dfs_add_controller(struct spmi_controller *ctrl)
635{
636 struct dentry *dir;
637 struct dentry *root;
638 struct dentry *file;
639 struct spmi_ctrl_data *ctrl_data;
640
641 pr_debug("Adding controller %s\n", ctrl->dev.kobj.name);
642 root = spmi_dfs_get_root();
643 if (!root)
644 return -ENOENT;
645
646 /* Allocate transaction data for the controller */
647 ctrl_data = kzalloc(sizeof(*ctrl_data), GFP_KERNEL);
648 if (!ctrl_data)
649 return -ENOMEM;
650
651 dir = debugfs_create_dir(ctrl->dev.kobj.name, root);
652 if (!dir) {
653 pr_err("Error creating entry for spmi controller %s\n",
654 ctrl->dev.kobj.name);
655 goto err_create_dir_failed;
656 }
657
658 ctrl_data->cnt = 1;
Kenneth Heitke5998fab2013-01-22 16:09:19 -0700659 ctrl_data->dir = dir;
Kenneth Heitke98661912012-09-19 18:51:40 -0600660 ctrl_data->ctrl = ctrl;
661
662 file = debugfs_create_u32("count", DFS_MODE, dir, &ctrl_data->cnt);
663 if (!file) {
664 pr_err("error creating 'count' entry\n");
665 goto err_remove_fs;
666 }
667
668 file = debugfs_create_x32("address", DFS_MODE, dir, &ctrl_data->addr);
669 if (!file) {
670 pr_err("error creating 'address' entry\n");
671 goto err_remove_fs;
672 }
673
674 file = debugfs_create_file("data", DFS_MODE, dir, ctrl_data,
675 &spmi_dfs_reg_fops);
676 if (!file) {
677 pr_err("error creating 'data' entry\n");
678 goto err_remove_fs;
679 }
680
681 file = debugfs_create_file("data_raw", DFS_MODE, dir, ctrl_data,
682 &spmi_dfs_raw_data_fops);
683 if (!file) {
684 pr_err("error creating 'data' entry\n");
685 goto err_remove_fs;
686 }
687
688 list_add(&ctrl_data->node, &dbgfs_data.ctrl);
689 return 0;
690
691err_remove_fs:
692 debugfs_remove_recursive(dir);
693err_create_dir_failed:
694 kfree(ctrl_data);
695 return -ENOMEM;
696}
697
Kenneth Heitke5998fab2013-01-22 16:09:19 -0700698/*
Kenneth Heitke42120dc2013-04-29 16:00:59 -0600699 * spmi_dfs_del_controller: deletes spmi controller entry
700 * @return zero on success
701 */
702int spmi_dfs_del_controller(struct spmi_controller *ctrl)
703{
704 int rc;
705 struct list_head *pos, *tmp;
706 struct spmi_ctrl_data *ctrl_data;
707
708 pr_debug("Deleting controller %s\n", ctrl->dev.kobj.name);
709
710 rc = mutex_lock_interruptible(&dbgfs_data.lock);
711 if (rc)
712 return rc;
713
714 list_for_each_safe(pos, tmp, &dbgfs_data.ctrl) {
715 ctrl_data = list_entry(pos, struct spmi_ctrl_data, node);
716
717 if (ctrl_data->ctrl == ctrl) {
718 debugfs_remove_recursive(ctrl_data->dir);
719 list_del(pos);
720 kfree(ctrl_data);
721 rc = 0;
722 goto done;
723 }
724 }
725 rc = -EINVAL;
726 pr_debug("Unknown controller %s\n", ctrl->dev.kobj.name);
727
728done:
729 mutex_unlock(&dbgfs_data.lock);
730 return rc;
731}
732
733/*
Kenneth Heitke5998fab2013-01-22 16:09:19 -0700734 * spmi_dfs_create_file: creates a new file in the SPMI debugfs
735 * @returns valid dentry pointer on success or NULL
736 */
737struct dentry *spmi_dfs_create_file(struct spmi_controller *ctrl,
738 const char *name, void *data,
739 const struct file_operations *fops)
740{
741 struct spmi_ctrl_data *ctrl_data;
742
743 list_for_each_entry(ctrl_data, &dbgfs_data.ctrl, node) {
744 if (ctrl_data->ctrl == ctrl)
745 return debugfs_create_file(name,
746 DFS_MODE, ctrl_data->dir, data, fops);
747 }
748
749 return NULL;
750}
751
Kenneth Heitke98661912012-09-19 18:51:40 -0600752static void __exit spmi_dfs_delete_all_ctrl(struct list_head *head)
753{
754 struct list_head *pos, *tmp;
755
756 list_for_each_safe(pos, tmp, head) {
757 struct spmi_ctrl_data *ctrl_data;
758
759 ctrl_data = list_entry(pos, struct spmi_ctrl_data, node);
760 list_del(pos);
761 kfree(ctrl_data);
762 }
763}
764
765static void __exit spmi_dfs_destroy(void)
766{
767 pr_debug("de-initializing spmi debugfs ...");
768 if (mutex_lock_interruptible(&dbgfs_data.lock) < 0)
769 return;
770 if (dbgfs_data.root) {
771 debugfs_remove_recursive(dbgfs_data.root);
772 dbgfs_data.root = NULL;
773 spmi_dfs_delete_all_ctrl(&dbgfs_data.ctrl);
774 }
775 mutex_unlock(&dbgfs_data.lock);
776}
777
778module_exit(spmi_dfs_destroy);
779
780MODULE_LICENSE("GPL v2");
781MODULE_ALIAS("platform:spmi_debug_fs");