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