arm64: dts: Keep VCCQ power when S2R mode for Sandisk UFS
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / lib / debug-snapshot-sysfs.c
CommitLineData
dd101ca5
DC
1/*
2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * Exynos-SnapShot debugging framework for Exynos SoC
6 *
7 * Author: Hosung Kim <Hosung0.kim@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/module.h>
17#include <linux/ktime.h>
18#include <linux/kallsyms.h>
19#include <linux/platform_device.h>
20#include <linux/clk-provider.h>
21#include <linux/pstore_ram.h>
22#include <linux/sched/clock.h>
23#include <linux/ftrace.h>
24
25#include "debug-snapshot-local.h"
26#include <asm/irq.h>
27#include <asm/traps.h>
28#include <asm/hardirq.h>
29#include <asm/stacktrace.h>
30#include <linux/debug-snapshot.h>
31#include <linux/kernel_stat.h>
32#include <linux/irqnr.h>
33#include <linux/irq.h>
34#include <linux/irqdesc.h>
35
36/*
37 * sysfs implementation for debug-snapshot
38 * you can access the sysfs of debug-snapshot to /sys/devices/system/debug_snapshot
39 * path.
40 */
41static struct bus_type dss_subsys = {
42 .name = "debug-snapshot",
43 .dev_name = "debug-snapshot",
44};
45
46extern int dss_irqlog_exlist[DSS_EX_MAX_NUM];
47extern int dss_irqexit_exlist[DSS_EX_MAX_NUM];
48extern unsigned int dss_irqexit_threshold;
49
16912855
YN
50static ssize_t dss_enable_show(struct device *dev,
51 struct device_attribute *attr, char *buf)
dd101ca5
DC
52{
53 struct dbg_snapshot_item *item;
54 unsigned long i;
55 ssize_t n = 0;
56
57 /* item */
758cb36c 58 for (i = 0; i < dss_desc.log_cnt; i++) {
dd101ca5
DC
59 item = &dss_items[i];
60 n += scnprintf(buf + n, 24, "%-12s : %sable\n",
61 item->name, item->entry.enabled ? "en" : "dis");
62 }
63
64 /* base */
65 n += scnprintf(buf + n, 24, "%-12s : %sable\n",
66 "base", dss_base.enabled ? "en" : "dis");
67
68 return n;
69}
70
16912855
YN
71static ssize_t dss_enable_store(struct device *dev,
72 struct device_attribute *attr,
dd101ca5
DC
73 const char *buf, size_t count)
74{
75 int en;
76 char *name;
77
78 name = (char *)kstrndup(buf, count, GFP_KERNEL);
79 if (!name)
80 return count;
81
82 name[count - 1] = '\0';
83
84 en = dbg_snapshot_get_enable(name);
85
86 if (en == -1)
87 pr_info("echo name > enabled\n");
88 else {
89 if (en)
90 dbg_snapshot_set_enable(name, false);
91 else
92 dbg_snapshot_set_enable(name, true);
93 }
94
95 kfree(name);
96 return count;
97}
98
16912855
YN
99static ssize_t dss_callstack_show(struct device *dev,
100 struct device_attribute *attr, char *buf)
dd101ca5
DC
101{
102 ssize_t n = 0;
103
104 n = scnprintf(buf, 24, "callstack depth : %d\n", dss_desc.callstack);
105
106 return n;
107}
108
16912855 109static ssize_t dss_callstack_store(struct device *dev, struct device_attribute *attr,
dd101ca5
DC
110 const char *buf, size_t count)
111{
112 unsigned long callstack;
113
114 callstack = simple_strtoul(buf, NULL, 0);
115 pr_info("callstack depth(min 1, max 4) : %lu\n", callstack);
116
117 if (callstack < 5 && callstack > 0) {
118 dss_desc.callstack = (unsigned int)callstack;
119 pr_info("success inserting %lu to callstack value\n", callstack);
120 }
121 return count;
122}
123
16912855
YN
124static ssize_t dss_irqlog_exlist_show(struct device *dev,
125 struct device_attribute *attr, char *buf)
dd101ca5
DC
126{
127 unsigned long i;
128 ssize_t n = 0;
129
130 n = scnprintf(buf, 24, "excluded irq number\n");
131
132 for (i = 0; i < ARRAY_SIZE(dss_irqlog_exlist); i++) {
133 if (dss_irqlog_exlist[i] == 0)
134 break;
135 n += scnprintf(buf + n, 24, "irq num: %-4d\n", dss_irqlog_exlist[i]);
136 }
137 return n;
138}
139
16912855
YN
140static ssize_t dss_irqlog_exlist_store(struct device *dev,
141 struct device_attribute *attr,
dd101ca5
DC
142 const char *buf, size_t count)
143{
144 unsigned long i;
145 unsigned long irq;
146
147 irq = simple_strtoul(buf, NULL, 0);
148 pr_info("irq number : %lu\n", irq);
149
150 for (i = 0; i < ARRAY_SIZE(dss_irqlog_exlist); i++) {
151 if (dss_irqlog_exlist[i] == 0)
152 break;
153 }
154
155 if (i == ARRAY_SIZE(dss_irqlog_exlist)) {
156 pr_err("list is full\n");
157 return count;
158 }
159
160 if (irq != 0) {
161 dss_irqlog_exlist[i] = irq;
162 pr_info("success inserting %lu to list\n", irq);
163 }
164 return count;
165}
166
167#ifdef CONFIG_DEBUG_SNAPSHOT_IRQ_EXIT
16912855
YN
168static ssize_t dss_irqexit_exlist_show(struct device *dev,
169 struct device_attribute *attr, char *buf)
dd101ca5
DC
170{
171 unsigned long i;
172 ssize_t n = 0;
173
174 n = scnprintf(buf, 36, "Excluded irq number\n");
175 for (i = 0; i < ARRAY_SIZE(dss_irqexit_exlist); i++) {
176 if (dss_irqexit_exlist[i] == 0)
177 break;
178 n += scnprintf(buf + n, 24, "IRQ num: %-4d\n", dss_irqexit_exlist[i]);
179 }
180 return n;
181}
182
16912855
YN
183static ssize_t dss_irqexit_exlist_store(struct device *dev,
184 struct device_attribute *attr,
dd101ca5
DC
185 const char *buf, size_t count)
186{
187 unsigned long i;
188 unsigned long irq;
189
190 irq = simple_strtoul(buf, NULL, 0);
191 pr_info("irq number : %lu\n", irq);
192
193 for (i = 0; i < ARRAY_SIZE(dss_irqexit_exlist); i++) {
194 if (dss_irqexit_exlist[i] == 0)
195 break;
196 }
197
198 if (i == ARRAY_SIZE(dss_irqexit_exlist)) {
199 pr_err("list is full\n");
200 return count;
201 }
202
203 if (irq != 0) {
204 dss_irqexit_exlist[i] = irq;
205 pr_info("success inserting %lu to list\n", irq);
206 }
207 return count;
208}
209
16912855
YN
210static ssize_t dss_irqexit_threshold_show(struct device *dev,
211 struct device_attribute *attr, char *buf)
dd101ca5
DC
212{
213 ssize_t n;
214
215 n = scnprintf(buf, 46, "threshold : %12u us\n", dss_irqexit_threshold);
216 return n;
217}
218
16912855
YN
219static ssize_t dss_irqexit_threshold_store(struct device *dev,
220 struct device_attribute *attr,
dd101ca5
DC
221 const char *buf, size_t count)
222{
223 unsigned long val;
224
225 val = simple_strtoul(buf, NULL, 0);
226 pr_info("threshold value : %lu\n", val);
227
228 if (val != 0) {
229 dss_irqexit_threshold = (unsigned int)val;
230 pr_info("success %lu to threshold\n", val);
231 }
232 return count;
233}
234#endif
235
236#ifdef CONFIG_DEBUG_SNAPSHOT_REG
16912855
YN
237static ssize_t dss_reg_exlist_show(struct device *dev,
238 struct device_attribute *attr, char *buf)
dd101ca5
DC
239{
240 unsigned long i;
241 ssize_t n = 0;
242
243 n = scnprintf(buf, 36, "excluded register address\n");
244 for (i = 0; i < ARRAY_SIZE(dss_reg_exlist); i++) {
245 if (dss_reg_exlist[i].addr == 0)
246 break;
247 n += scnprintf(buf + n, 40, "register addr: %08zx size: %08zx\n",
248 dss_reg_exlist[i].addr, dss_reg_exlist[i].size);
249 }
250 return n;
251}
252
16912855
YN
253static ssize_t dss_reg_exlist_store(struct device *dev,
254 struct device_attribute *attr,
dd101ca5
DC
255 const char *buf, size_t count)
256{
257 unsigned long i;
258 size_t addr;
259
260 addr = simple_strtoul(buf, NULL, 0);
261 pr_info("register addr: %zx\n", addr);
262
263 for (i = 0; i < ARRAY_SIZE(dss_reg_exlist); i++) {
264 if (dss_reg_exlist[i].addr == 0)
265 break;
266 }
267 if (addr != 0) {
268 dss_reg_exlist[i].size = SZ_4K;
269 dss_reg_exlist[i].addr = addr;
270 pr_info("success %zx to threshold\n", (addr));
271 }
272 return count;
273}
274#endif
275
276
16912855 277static struct device_attribute dss_enable_attr =
dd101ca5
DC
278__ATTR(enabled, 0644, dss_enable_show, dss_enable_store);
279
16912855 280static struct device_attribute dss_callstack_attr =
dd101ca5
DC
281__ATTR(callstack, 0644, dss_callstack_show, dss_callstack_store);
282
16912855 283static struct device_attribute dss_irqlog_attr =
dd101ca5
DC
284__ATTR(exlist_irqdisabled, 0644, dss_irqlog_exlist_show,
285 dss_irqlog_exlist_store);
286#ifdef CONFIG_DEBUG_SNAPSHOT_IRQ_EXIT
16912855 287static struct device_attribute dss_irqexit_attr =
dd101ca5
DC
288__ATTR(exlist_irqexit, 0644, dss_irqexit_exlist_show,
289 dss_irqexit_exlist_store);
290
16912855 291static struct device_attribute dss_irqexit_threshold_attr =
dd101ca5
DC
292__ATTR(threshold_irqexit, 0644, dss_irqexit_threshold_show,
293 dss_irqexit_threshold_store);
294#endif
295#ifdef CONFIG_DEBUG_SNAPSHOT_REG
296
16912855 297static struct device_attribute dss_reg_attr =
dd101ca5
DC
298__ATTR(exlist_reg, 0644, dss_reg_exlist_show, dss_reg_exlist_store);
299#endif
300
301static struct attribute *dss_sysfs_attrs[] = {
302 &dss_enable_attr.attr,
303 &dss_callstack_attr.attr,
304 &dss_irqlog_attr.attr,
305#ifdef CONFIG_DEBUG_SNAPSHOT_IRQ_EXIT
306 &dss_irqexit_attr.attr,
307 &dss_irqexit_threshold_attr.attr,
308#endif
309#ifdef CONFIG_DEBUG_SNAPSHOT_REG
310 &dss_reg_attr.attr,
311#endif
312 NULL,
313};
314
315static struct attribute_group dss_sysfs_group = {
316 .attrs = dss_sysfs_attrs,
317};
318
319static const struct attribute_group *dss_sysfs_groups[] = {
320 &dss_sysfs_group,
321 NULL,
322};
323
324static int __init dbg_snapshot_sysfs_init(void)
325{
326 int ret = 0;
327
328 ret = subsys_system_register(&dss_subsys, dss_sysfs_groups);
329 if (ret)
330 pr_err("fail to register debug-snapshop subsys\n");
331
332 return ret;
333}
334late_initcall(dbg_snapshot_sysfs_init);