[RAMEN9610-20413][9610] wlbt: SCSC Driver version 10.6.1.0
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / drivers / misc / samsung / gpio_debug / gpio_debug.c
1 /* Copyright (c) 2014 Samsung Electronics Co., Ltd */
2
3 #include <linux/gpio_debug.h>
4 #include <linux/version.h>
5 #include <linux/kernel.h>
6 #include <linux/module.h>
7 #include <linux/platform_device.h>
8 #include <linux/of.h>
9 #include <linux/of_gpio.h>
10 #include <linux/gpio.h>
11 #include <linux/io.h>
12 #include <linux/debugfs.h>
13 #include <linux/slab.h>
14 #include <linux/mutex.h>
15
16 struct gpio_debug_data;
17
18 struct gpio_debug_event {
19 int gpio;
20 int gpio_idx;
21 struct gpio_debug_event_def def;
22 struct gpio_debug_data *data;
23 struct dentry *file;
24 };
25
26 struct gpio_debug_data {
27 int gpio_count;
28 int *gpios;
29 struct dentry *gpio_debug_dir;
30 struct dentry *gpio_debug_events_dir;
31 struct platform_device *pdev;
32 struct gpio_debug_event *events;
33 int event_count;
34 int event_base;
35 };
36
37 static struct gpio_debug_data debug_data;
38
39 DEFINE_MUTEX(debug_lock);
40
41 enum {
42 GPIO_DEBUG_TOGGLE_100,
43 GPIO_DEBUG_TOGGLE_200,
44 };
45
46 static struct gpio_debug_event_def debug_events_table[] = {
47 [GPIO_DEBUG_TOGGLE_100] = {
48 .name = "toggle100",
49 .description = "Toggle the GPIO 100 times at initialisation",
50 },
51 [GPIO_DEBUG_TOGGLE_200] = {
52 .name = "toggle200",
53 .description = "Toggle the GPIO 200 times at initialisation",
54 },
55 };
56
57 static void gpio_debug_event(int gpio, int state)
58 {
59 if (gpio >= 0)
60 gpio_set_value(gpio, state);
61 }
62
63 static void gpio_debug_event_exec(int event_id, int state)
64 {
65 if ((event_id >= 0) && (event_id < debug_data.event_count) && debug_data.events)
66 gpio_debug_event(debug_data.events[event_id].gpio, state);
67 }
68
69 void gpio_debug_event_enter(int base, int id)
70 {
71 gpio_debug_event_exec(base + id, 0);
72 }
73
74 void gpio_debug_event_exit(int base, int id)
75 {
76 gpio_debug_event_exec(base + id, 1);
77 }
78
79 int gpio_debug_event_enabled(int base, int id)
80 {
81 int event_id = base + id;
82
83 if ((event_id >= 0) &&
84 (event_id < debug_data.event_count) &&
85 debug_data.events &&
86 debug_data.events[event_id].gpio >= 0)
87 return 1;
88 else
89 return 0;
90 }
91
92 static int gpio_debug_event_link(struct gpio_debug_event *event, int gpio_index)
93 {
94 struct gpio_debug_data *data = event->data;
95
96 if (gpio_index >= data->gpio_count)
97 return -ERANGE;
98
99 if (gpio_index >= 0)
100 event->gpio = data->gpios[gpio_index];
101 else
102 event->gpio = -1;
103
104 event->gpio_idx = gpio_index;
105
106 return 0;
107 }
108
109 static ssize_t event_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos)
110 {
111 ssize_t ret = 0;
112 struct gpio_debug_event *event = file->f_inode->i_private;
113 char buf[256];
114 int pos;
115
116 mutex_lock(&debug_lock);
117
118 pos = snprintf(buf, sizeof(buf), "Description:\n%s\n\nEvent is mapped to GPIO index %d with number %d\n", event->def.description, event->gpio_idx, event->gpio);
119 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
120
121 mutex_unlock(&debug_lock);
122
123 return ret;
124 }
125
126 static ssize_t event_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos)
127 {
128 char *user_string;
129 ssize_t ret;
130 struct gpio_debug_event *event = file->f_inode->i_private;
131 int new_index = -1;
132
133 mutex_lock(&debug_lock);
134
135 user_string = kmalloc(count + 1, GFP_KERNEL);
136 memory_read_from_buffer(user_string, count, ppos, user_buf, count);
137
138 user_string[count] = '\0';
139 ret = (ssize_t)strnlen(user_string, count + 1);
140
141 if (kstrtou32(user_string, 10, &new_index)) {
142 return -EINVAL;
143
144 gpio_debug_event_link(event, new_index);
145
146 kfree(user_string);
147 mutex_unlock(&debug_lock);
148
149 return ret;
150 }
151
152 static const struct file_operations event_ops = {
153 .read = event_read,
154 .write = event_write,
155 };
156
157 static void create_event_file(struct gpio_debug_event *event)
158 {
159 struct gpio_debug_data *data = event->data;
160
161 if (data && data->gpio_debug_events_dir) {
162 event->file = debugfs_create_file(event->def.name, 0660, data->gpio_debug_events_dir, event, &event_ops);
163 if (IS_ERR_OR_NULL(event->file)) {
164 event->file = NULL;
165 pr_warn("%s: Could not create debugfs file for %s\n", __func__, event->def.name);
166 }
167 }
168 }
169
170 static void remove_event_file(struct gpio_debug_event *event)
171 {
172 if (event && event->file) {
173 debugfs_remove(event->file);
174 event->file = NULL;
175 }
176 }
177
178 static void gpio_debug_init_event(struct gpio_debug_data *data, struct gpio_debug_event_def *event, struct gpio_debug_event *event_save)
179 {
180 event_save->def.description = event->description;
181 event_save->def.name = event->name;
182 event_save->gpio = -1;
183 event_save->gpio_idx = -1;
184 event_save->data = data;
185
186 create_event_file(event_save);
187 }
188
189 static void gpio_debug_destroy_event(struct gpio_debug_event *event)
190 {
191 remove_event_file(event);
192 event->def.description = NULL;
193 event->def.name = NULL;
194 event->gpio = -1;
195 event->gpio_idx = -1;
196 event->data = NULL;
197 }
198
199 int gpio_debug_event_list_register(struct gpio_debug_event_def *events, int event_count)
200 {
201 struct gpio_debug_data *data = &debug_data;
202 int start_index = data->event_count;
203 struct gpio_debug_event *new_events;
204 int new_event_count = data->event_count + event_count;
205 int i, j;
206
207 mutex_lock(&debug_lock);
208
209 if (data->events)
210 for (i = 0; i < data->event_count; i++)
211 remove_event_file(&data->events[i]);
212
213 new_events = krealloc(data->events, new_event_count * sizeof(struct gpio_debug_event), GFP_KERNEL);
214 if (!new_events) {
215 pr_warn("%s: Could not expand for extra events\n", __func__);
216 /* If krealloc fails, data->events is unchanged, so just exit */
217 return -ENOMEM;
218 }
219 data->events = new_events;
220 for (i = 0; i < data->event_count; i++)
221 create_event_file(&data->events[i]);
222
223 data->event_count = new_event_count;
224
225 for (i = 0, j = start_index; (i < event_count) && (j < data->event_count); i++, j++)
226 gpio_debug_init_event(data, &events[i], &data->events[j]);
227
228 mutex_unlock(&debug_lock);
229 return start_index;
230 }
231
232 void gpio_debug_event_list_unregister(int base, int event_count)
233 {
234 int i;
235 struct gpio_debug_data *data = &debug_data;
236
237 mutex_lock(&debug_lock);
238
239 for (i = base; (i < (event_count + base)) && (i < data->event_count); i++)
240 gpio_debug_destroy_event(&data->events[i]);
241
242 mutex_unlock(&debug_lock);
243 }
244
245 static ssize_t event_list_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos)
246 {
247 int i;
248 ssize_t ret = 0;
249 int length = 0;
250 char *buf;
251 struct gpio_debug_data *data = file->f_inode->i_private;
252 struct device *dev = &data->pdev->dev;
253 char headline[] = " gpio event\n";
254
255 mutex_lock(&debug_lock);
256
257 length += strlen(headline);
258
259 for (i = 0; i < data->event_count; i++)
260 if (data->events[i].def.name)
261 length += strlen(data->events[i].def.name) + 7;
262 length++; /* Reserve space for NULL termination */
263
264 buf = devm_kzalloc(dev, length, GFP_KERNEL);
265 buf[0] = '\0';
266 snprintf(buf, length, "%s", headline);
267 for (i = 0; i < data->event_count; i++)
268 if (data->events[i].data) {
269 if (data->events[i].gpio_idx >= 0)
270 snprintf(buf, length, "%s%5d %s\n", buf, data->events[i].gpio_idx, data->events[i].def.name);
271 else
272 snprintf(buf, length, "%s %s\n", buf, data->events[i].def.name);
273 }
274 ret = simple_read_from_buffer(user_buf, count, ppos, buf, length);
275 devm_kfree(dev, buf);
276
277 mutex_unlock(&debug_lock);
278
279 return ret;
280 }
281
282 static const struct file_operations event_list_ops = {
283 .read = event_list_read,
284 };
285
286 static ssize_t num_gpios_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos)
287 {
288 ssize_t ret = 0;
289 struct gpio_debug_data *data = file->f_inode->i_private;
290 char buf[256];
291 int pos;
292
293 pos = snprintf(buf, sizeof(buf), "%d\n", data->gpio_count);
294 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
295 return ret;
296 }
297
298 static const struct file_operations num_gpios_ops = {
299 .read = num_gpios_read,
300 };
301
302 static int gpio_debug_probe(struct platform_device *pdev)
303 {
304 struct device_node *np = pdev->dev.of_node;
305 struct device *dev = &pdev->dev;
306 int count;
307 struct gpio_debug_data *data = &debug_data;
308 int i, j;
309
310 mutex_lock(&debug_lock);
311
312 count = of_gpio_count(np);
313 if (count < 0)
314 count = 0; /* Errors register as no GPIOs available */
315
316 data->gpio_count = count;
317 data->gpios = NULL;
318 data->pdev = pdev;
319
320 if (count) {
321 data->gpios = devm_kzalloc(dev, count * sizeof(int), GFP_KERNEL);
322 for (i = 0; i < count; i++) {
323 data->gpios[i] = of_get_gpio(np, i);
324 dev_info(dev, "GPIO at index %d has number %d\n", i, data->gpios[i]);
325 if (gpio_is_valid(data->gpios[i])) {
326 char label[256];
327
328 sprintf(label, "debug-gpio-%d", i);
329 dev_info(dev, "Requesting GPIO %d index %d with label %s\n", data->gpios[i], i, label);
330 if (devm_gpio_request(dev, data->gpios[i], label))
331 dev_err(dev, "GPIO [%d] request failed\n", data->gpios[i]);
332 gpio_set_value(data->gpios[i], 1);
333 } else
334 dev_warn(dev, "GPIO at index %d is invalid\n", i);
335 }
336 }
337
338 data->gpio_debug_dir = debugfs_create_dir("gpio_debug", NULL);
339 if (!IS_ERR_OR_NULL(data->gpio_debug_dir)) {
340 data->gpio_debug_events_dir = debugfs_create_dir("events", data->gpio_debug_dir);
341 if (IS_ERR_OR_NULL(data->gpio_debug_events_dir)) {
342 data->gpio_debug_events_dir = NULL;
343 dev_err(dev, "Debugfs cannot create subdir\n");
344 }
345 debugfs_create_file("event_list", 0440, data->gpio_debug_dir, data, &event_list_ops);
346 debugfs_create_file("num_gpios", 0440, data->gpio_debug_dir, data, &num_gpios_ops);
347 } else {
348 data->gpio_debug_dir = NULL;
349 dev_warn(dev, "Debugfs is not available, configuration of GPIO debug is not possible\n");
350 }
351
352 for (i = 0; i < data->event_count; i++)
353 create_event_file(&data->events[i]);
354
355 mutex_unlock(&debug_lock);
356
357 data->event_base = gpio_debug_event_list_register(debug_events_table, ARRAY_SIZE(debug_events_table));
358
359 for (i = 0; i < count; i++) {
360 gpio_debug_event_link(&data->events[data->event_base + GPIO_DEBUG_TOGGLE_100], i);
361 for (j = 0; j < 100; j++) {
362 gpio_debug_event_enter(data->event_base, GPIO_DEBUG_TOGGLE_100);
363 gpio_debug_event_exit(data->event_base, GPIO_DEBUG_TOGGLE_100);
364 }
365 }
366 gpio_debug_event_link(&data->events[data->event_base + GPIO_DEBUG_TOGGLE_100], -1);
367
368 for (i = 0; i < count; i++) {
369 gpio_debug_event_link(&data->events[data->event_base + GPIO_DEBUG_TOGGLE_200], i);
370 for (j = 0; j < 200; j++) {
371 gpio_debug_event_enter(data->event_base, GPIO_DEBUG_TOGGLE_200);
372 gpio_debug_event_exit(data->event_base, GPIO_DEBUG_TOGGLE_200);
373 }
374 }
375 gpio_debug_event_link(&data->events[data->event_base + GPIO_DEBUG_TOGGLE_200], -1);
376
377 return 0;
378 }
379
380 static int gpio_debug_remove(struct platform_device *pdev)
381 {
382 struct device *dev = &pdev->dev;
383 struct gpio_debug_data *data = &debug_data;
384
385 mutex_lock(&debug_lock);
386 debugfs_remove_recursive(data->gpio_debug_dir);
387 data->gpio_debug_dir = NULL;
388 data->gpio_debug_events_dir = NULL;
389
390 if (data->gpios) {
391 int i;
392
393 for (i = 0; i < data->gpio_count; i++)
394 if (gpio_is_valid(data->gpios[i]))
395 devm_gpio_free(dev, data->gpios[i]);
396 devm_kfree(dev, data->gpios);
397 data->gpios = NULL;
398 data->gpio_count = 0;
399 }
400 data->pdev = NULL;
401 kfree(data->events);
402 data->events = NULL;
403 data->event_count = 0;
404 mutex_unlock(&debug_lock);
405
406 return 0;
407 }
408
409 static const struct of_device_id gpio_debug_match[] = {
410 { .compatible = "samsung,gpio-debug", },
411 {},
412 };
413 MODULE_DEVICE_TABLE(of, gpio_debug_match);
414
415 static struct platform_driver gpio_debug_driver = {
416 .probe = gpio_debug_probe,
417 .remove = gpio_debug_remove,
418 .driver = {
419 .name = "gpio_debug",
420 .of_match_table = gpio_debug_match,
421 }
422 };
423 module_platform_driver(gpio_debug_driver);
424
425 MODULE_DESCRIPTION("GPIO Debug framework");
426 MODULE_AUTHOR("Samsung Electronics Co., Ltd");
427 MODULE_LICENSE("GPL and additional rights");