[RAMEN9610-13608][COMMON][RAMEN9610-13599] lib: dss: fix to set debug level
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / lib / debug-snapshot.c
1 /*
2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * Debug-SnapShot: Debug Framework for Ramdump based debugging method
6 * The original code is Exynos-Snapshot for Exynos SoC
7 *
8 * Author: Hosung Kim <hosung0.kim@samsung.com>
9 * Author: Changki Kim <changki.kim@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16 #include <linux/kernel.h>
17 #include <linux/version.h>
18 #include <linux/io.h>
19 #include <linux/device.h>
20 #include <linux/bootmem.h>
21 #include <linux/slab.h>
22 #include <linux/vmalloc.h>
23 #include <linux/module.h>
24 #include <linux/memblock.h>
25 #include <linux/of_address.h>
26 #include <linux/of_reserved_mem.h>
27 #include <linux/sched/clock.h>
28
29 #include "debug-snapshot-local.h"
30
31 /* To Support Samsung SoC */
32 #include <dt-bindings/soc/samsung/debug-snapshot-table.h>
33 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
34 #include <soc/samsung/cal-if.h>
35 #endif
36
37 extern void register_hook_logbuf(void (*)(const char *, size_t));
38 extern void register_hook_logger(void (*)(const char *, const char *, size_t));
39
40 struct dbg_snapshot_interface {
41 struct dbg_snapshot_log *info_event;
42 struct dbg_snapshot_item info_log[DSS_ITEM_MAX_NUM];
43 };
44
45 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
46 struct dbg_snapshot_ops {
47 int (*pd_status)(unsigned int id);
48 };
49
50 struct dbg_snapshot_ops dss_ops = {
51 .pd_status = cal_pd_status,
52 };
53 #endif
54
55 const char *debug_level_val[] = {
56 "low",
57 "mid",
58 };
59
60 struct dbg_snapshot_item dss_items[] = {
61 {"header", {0, 0, 0, false, false}, NULL ,NULL, 0, },
62 {"log_kernel", {0, 0, 0, false, false}, NULL ,NULL, 0, },
63 {"log_platform", {0, 0, 0, false, false}, NULL ,NULL, 0, },
64 {"log_sfr", {0, 0, 0, false, false}, NULL ,NULL, 0, },
65 {"log_s2d", {0, 0, 0, true, false}, NULL, NULL, 0, },
66 {"log_cachedump", {0, 0, 0, true, false}, NULL, NULL, 0, },
67 {"log_etm", {0, 0, 0, true, false}, NULL ,NULL, 0, },
68 {"log_bcm", {0, 0, 0, false, false}, NULL ,NULL, 0, },
69 {"log_pstore", {0, 0, 0, true, false}, NULL ,NULL, 0, },
70 {"log_kevents", {0, 0, 0, false, false}, NULL ,NULL, 0, },
71 };
72
73 /* External interface variable for trace debugging */
74 static struct dbg_snapshot_interface dss_info __attribute__ ((used));
75 static struct dbg_snapshot_interface *ess_info __attribute__ ((used));
76
77 struct dbg_snapshot_base dss_base;
78 struct dbg_snapshot_base ess_base;
79 struct dbg_snapshot_log *dss_log = NULL;
80 struct dbg_snapshot_desc dss_desc;
81
82 /* Variable for assigning virtual address base */
83 static size_t g_dbg_snapshot_vaddr_base = DSS_FIXED_VIRT_BASE;
84
85 int dbg_snapshot_set_debug_level(int level)
86 {
87 if (level > -1 && level < ARRAY_SIZE(debug_level_val)) {
88 dss_desc.debug_level = level;
89 } else {
90 #if !IS_ENABLED(CONFIG_DEBUG_SNAPSHOT_USER_MODE)
91 dss_desc.debug_level = DSS_DEBUG_LEVEL_MID;
92 #else
93 dss_desc.debug_level = DSS_DEBUG_LEVEL_LOW;
94 #endif
95 }
96 dbg_snapshot_set_debug_level_reg();
97 return 0;
98 }
99
100 int dbg_snapshot_get_debug_level(void)
101 {
102 return dss_desc.debug_level;
103 }
104
105 int dbg_snapshot_set_enable(const char *name, int en)
106 {
107 struct dbg_snapshot_item *item = NULL;
108 unsigned long i;
109
110 if (!strncmp(name, "base", strlen(name))) {
111 dss_base.enabled = en;
112 pr_info("debug-snapshot: %sabled\n", en ? "en" : "dis");
113 } else {
114 for (i = 0; i < ARRAY_SIZE(dss_items); i++) {
115 if (!strncmp(dss_items[i].name, name, strlen(name))) {
116 item = &dss_items[i];
117 item->entry.enabled = en;
118 item->time = local_clock();
119 pr_info("debug-snapshot: item - %s is %sabled\n",
120 name, en ? "en" : "dis");
121 break;
122 }
123 }
124 }
125 return 0;
126 }
127 EXPORT_SYMBOL(dbg_snapshot_set_enable);
128
129 int dbg_snapshot_try_enable(const char *name, unsigned long long duration)
130 {
131 struct dbg_snapshot_item *item = NULL;
132 unsigned long long time;
133 unsigned long i;
134 int ret = -1;
135
136 /* If DSS was disabled, just return */
137 if (unlikely(!dss_base.enabled) || !dbg_snapshot_get_enable("header"))
138 return ret;
139
140 for (i = 0; i < ARRAY_SIZE(dss_items); i++) {
141 if (!strncmp(dss_items[i].name, name, strlen(name))) {
142 item = &dss_items[i];
143
144 /* We only interest in disabled */
145 if (!item->entry.enabled) {
146 time = local_clock() - item->time;
147 if (time > duration) {
148 item->entry.enabled = true;
149 ret = 1;
150 } else
151 ret = 0;
152 }
153 break;
154 }
155 }
156 return ret;
157 }
158 EXPORT_SYMBOL(dbg_snapshot_try_enable);
159
160 int dbg_snapshot_get_enable(const char *name)
161 {
162 struct dbg_snapshot_item *item = NULL;
163 unsigned long i;
164 int ret = 0;
165
166 if (!strncmp(name, "base", strlen(name)))
167 return dss_base.enabled;
168
169 for (i = 0; i < ARRAY_SIZE(dss_items); i++) {
170 if (!strncmp(dss_items[i].name, name, strlen(name))) {
171 item = &dss_items[i];
172 ret = item->entry.enabled;
173 break;
174 }
175 }
176 return ret;
177 }
178 EXPORT_SYMBOL(dbg_snapshot_get_enable);
179
180 static inline int dbg_snapshot_check_eob(struct dbg_snapshot_item *item,
181 size_t size)
182 {
183 size_t max, cur;
184
185 max = (size_t)(item->head_ptr + item->entry.size);
186 cur = (size_t)(item->curr_ptr + size);
187
188 if (unlikely(cur > max))
189 return -1;
190 else
191 return 0;
192 }
193
194 static inline void dbg_snapshot_hook_logger(const char *name,
195 const char *buf, size_t size)
196 {
197 struct dbg_snapshot_item *item = &dss_items[dss_desc.log_platform_num];
198
199 if (likely(dss_base.enabled && item->entry.enabled)) {
200 if (unlikely((dbg_snapshot_check_eob(item, size))))
201 item->curr_ptr = item->head_ptr;
202 memcpy(item->curr_ptr, buf, size);
203 item->curr_ptr += size;
204 }
205 }
206
207 static inline void dbg_snapshot_hook_logbuf(const char *buf, size_t size)
208 {
209 struct dbg_snapshot_item *item = &dss_items[dss_desc.log_kernel_num];
210
211 if (likely(dss_base.enabled && item->entry.enabled)) {
212 size_t last_buf;
213
214 if (dbg_snapshot_check_eob(item, size))
215 item->curr_ptr = item->head_ptr;
216
217 memcpy(item->curr_ptr, buf, size);
218 item->curr_ptr += size;
219 /* save the address of last_buf to physical address */
220 last_buf = (size_t)item->curr_ptr;
221
222 __raw_writel(item->entry.paddr + (last_buf - item->entry.vaddr),
223 dbg_snapshot_get_base_vaddr() + DSS_OFFSET_LAST_LOGBUF);
224 }
225 }
226
227 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
228 static bool dbg_snapshot_check_pmu(struct dbg_snapshot_sfrdump *sfrdump,
229 const struct device_node *np)
230 {
231 int ret = 0, count, i;
232 unsigned int val;
233
234 if (!sfrdump->pwr_mode)
235 return true;
236
237 count = of_property_count_u32_elems(np, "cal-pd-id");
238 for (i = 0; i < count; i++) {
239 ret = of_property_read_u32_index(np, "cal-pd-id", i, &val);
240 if (ret < 0) {
241 pr_err("failed to get pd-id - %s\n", sfrdump->name);
242 return false;
243 }
244 ret = dss_ops.pd_status(val);
245 if (ret < 0) {
246 pr_err("not powered - %s (pd-id: %d)\n", sfrdump->name, i);
247 return false;
248 }
249 }
250 return true;
251 }
252
253 void dbg_snapshot_dump_sfr(void)
254 {
255 struct dbg_snapshot_sfrdump *sfrdump;
256 struct dbg_snapshot_item *item = &dss_items[dss_desc.log_sfr_num];
257 struct list_head *entry;
258 struct device_node *np;
259 unsigned int reg, offset, val, size;
260 int i, ret;
261 static char buf[SZ_64];
262
263 if (unlikely(!dss_base.enabled || !item->entry.enabled))
264 return;
265
266 if (list_empty(&dss_desc.sfrdump_list)) {
267 pr_emerg("debug-snapshot: %s: No information\n", __func__);
268 return;
269 }
270
271 list_for_each(entry, &dss_desc.sfrdump_list) {
272 sfrdump = list_entry(entry, struct dbg_snapshot_sfrdump, list);
273 np = of_node_get(sfrdump->node);
274 ret = dbg_snapshot_check_pmu(sfrdump, np);
275 if (!ret)
276 /* may off */
277 continue;
278
279 for (i = 0; i < sfrdump->num; i++) {
280 ret = of_property_read_u32_index(np, "addr", i, &reg);
281 if (ret < 0) {
282 pr_err("debug-snapshot: failed to get address information - %s\n",
283 sfrdump->name);
284 break;
285 }
286 if (reg == 0xFFFFFFFF || reg == 0)
287 break;
288 offset = reg - sfrdump->phy_reg;
289 if (reg < offset) {
290 pr_err("debug-snapshot: invalid address information - %s: 0x%08x\n",
291 sfrdump->name, reg);
292 break;
293 }
294 val = __raw_readl(sfrdump->reg + offset);
295 snprintf(buf, SZ_64, "0x%X = 0x%0X\n",reg, val);
296 size = (unsigned int)strlen(buf);
297 if (unlikely((dbg_snapshot_check_eob(item, size))))
298 item->curr_ptr = item->head_ptr;
299 memcpy(item->curr_ptr, buf, strlen(buf));
300 item->curr_ptr += strlen(buf);
301 }
302 of_node_put(np);
303 pr_info("debug-snapshot: complete to dump %s\n", sfrdump->name);
304 }
305
306 }
307
308 static int dbg_snapshot_sfr_dump_init(struct device_node *np)
309 {
310 struct device_node *dump_np;
311 struct dbg_snapshot_sfrdump *sfrdump;
312 char *dump_str;
313 int count, ret, i;
314 u32 phy_regs[2];
315
316 ret = of_property_count_strings(np, "sfr-dump-list");
317 if (ret < 0) {
318 pr_err("failed to get sfr-dump-list\n");
319 return ret;
320 }
321 count = ret;
322
323 INIT_LIST_HEAD(&dss_desc.sfrdump_list);
324 for (i = 0; i < count; i++) {
325 ret = of_property_read_string_index(np, "sfr-dump-list", i,
326 (const char **)&dump_str);
327 if (ret < 0) {
328 pr_err("failed to get sfr-dump-list\n");
329 continue;
330 }
331
332 dump_np = of_get_child_by_name(np, dump_str);
333 if (!dump_np) {
334 pr_err("failed to get %s node, count:%d\n", dump_str, count);
335 continue;
336 }
337
338 sfrdump = kzalloc(sizeof(struct dbg_snapshot_sfrdump), GFP_KERNEL);
339 if (!sfrdump) {
340 pr_err("failed to get memory region of dbg_snapshot_sfrdump\n");
341 of_node_put(dump_np);
342 continue;
343 }
344
345 ret = of_property_read_u32_array(dump_np, "reg", phy_regs, 2);
346 if (ret < 0) {
347 pr_err("failed to get register information\n");
348 of_node_put(dump_np);
349 kfree(sfrdump);
350 continue;
351 }
352
353 sfrdump->reg = ioremap(phy_regs[0], phy_regs[1]);
354 if (!sfrdump->reg) {
355 pr_err("failed to get i/o address %s node\n", dump_str);
356 of_node_put(dump_np);
357 kfree(sfrdump);
358 continue;
359 }
360 sfrdump->name = dump_str;
361
362 ret = of_property_count_u32_elems(dump_np, "addr");
363 if (ret < 0) {
364 pr_err("failed to get addr count\n");
365 of_node_put(dump_np);
366 kfree(sfrdump);
367 continue;
368 }
369 sfrdump->phy_reg = phy_regs[0];
370 sfrdump->num = ret;
371
372 ret = of_property_count_u32_elems(dump_np, "cal-pd-id");
373 if (ret < 0)
374 sfrdump->pwr_mode = false;
375 else
376 sfrdump->pwr_mode = true;
377
378 sfrdump->node = dump_np;
379 list_add(&sfrdump->list, &dss_desc.sfrdump_list);
380
381 pr_info("success to regsiter %s\n", sfrdump->name);
382 of_node_put(dump_np);
383 ret = 0;
384 }
385 return ret;
386 }
387 #endif
388
389 static int __init dbg_snapshot_remap(void)
390 {
391 unsigned long i, j;
392 unsigned int enabled_count = 0;
393 pgprot_t prot = __pgprot(PROT_NORMAL_NC);
394 int page_size, ret;
395 struct page *page;
396 struct page **pages;
397
398 for (i = 0; i < ARRAY_SIZE(dss_items); i++) {
399 if (dss_items[i].entry.enabled) {
400 enabled_count++;
401 page_size = dss_items[i].entry.size / PAGE_SIZE;
402 pages = kzalloc(sizeof(struct page *) * page_size, GFP_KERNEL);
403 page = phys_to_page(dss_items[i].entry.paddr);
404
405 for (j = 0; j < page_size; j++)
406 pages[j] = page++;
407
408 ret = map_vm_area(&dss_items[i].vm, prot, pages);
409 kfree(pages);
410 if (ret) {
411 pr_err("debug-snapshot: failed to mapping between virt and phys");
412 return -ENOMEM;
413 }
414
415 dss_items[i].entry.vaddr = (size_t)dss_items[i].vm.addr;
416 dss_items[i].head_ptr = (unsigned char *)dss_items[i].entry.vaddr;
417 dss_items[i].curr_ptr = (unsigned char *)dss_items[i].entry.vaddr;
418 }
419 }
420 dss_desc.log_cnt = ARRAY_SIZE(dss_items);
421 return enabled_count;
422 }
423
424 static int __init dbg_snapshot_init_desc(void)
425 {
426 unsigned int i, len;
427
428 /* initialize dss_desc */
429 memset((struct dbg_snapshot_desc *)&dss_desc, 0, sizeof(struct dbg_snapshot_desc));
430 dss_desc.callstack = CONFIG_DEBUG_SNAPSHOT_CALLSTACK;
431 raw_spin_lock_init(&dss_desc.ctrl_lock);
432 raw_spin_lock_init(&dss_desc.nmi_lock);
433
434 for (i = 0; i < (unsigned int)ARRAY_SIZE(dss_items); i++) {
435 len = strlen(dss_items[i].name);
436 if (!strncmp(dss_items[i].name, "header", len))
437 dss_desc.header_num = i;
438 else if (!strncmp(dss_items[i].name, "log_kevents", len))
439 dss_desc.kevents_num = i;
440 else if (!strncmp(dss_items[i].name, "log_kernel", len))
441 dss_desc.log_kernel_num = i;
442 else if (!strncmp(dss_items[i].name, "log_platform", len))
443 dss_desc.log_platform_num = i;
444 else if (!strncmp(dss_items[i].name, "log_sfr", len))
445 dss_desc.log_sfr_num = i;
446 else if (!strncmp(dss_items[i].name, "log_pstore", len))
447 dss_desc.log_pstore_num = i;
448 }
449
450 #ifdef CONFIG_S3C2410_WATCHDOG
451 dss_desc.no_wdt_dev = false;
452 #else
453 dss_desc.no_wdt_dev = true;
454 #endif
455 return 0;
456 }
457
458 #ifdef CONFIG_OF_RESERVED_MEM
459 static int __init dbg_snapshot_item_reserved_mem_setup(struct reserved_mem *remem)
460 {
461 unsigned int i;
462
463 for (i = 0; i < (unsigned int)ARRAY_SIZE(dss_items); i++) {
464 if (strnstr(remem->name, dss_items[i].name, strlen(remem->name)))
465 break;
466 }
467
468 if (i == ARRAY_SIZE(dss_items))
469 return -ENODEV;
470
471 dss_items[i].entry.paddr = remem->base;
472 dss_items[i].entry.size = remem->size;
473 dss_items[i].entry.enabled = true;
474
475 dss_items[i].vm.phys_addr = remem->base;
476 dss_items[i].vm.addr = (void *)g_dbg_snapshot_vaddr_base;
477 dss_items[i].vm.size = remem->size;
478 dss_items[i].vm.flags = VM_NO_GUARD;
479 g_dbg_snapshot_vaddr_base += remem->size;
480
481 vm_area_add_early(&dss_items[i].vm);
482
483 if (strnstr(remem->name, "header", strlen(remem->name))) {
484 dss_base.paddr = remem->base;
485 dss_base.vaddr = (size_t)dss_items[i].vm.addr;
486 ess_base = dss_base;
487 dss_base.enabled = false;
488 }
489 dss_base.size += remem->size;
490 return 0;
491 }
492
493 #define DECLARE_DBG_SNAPSHOT_RESERVED_REGION(compat, name) \
494 RESERVEDMEM_OF_DECLARE(name, compat#name, dbg_snapshot_item_reserved_mem_setup)
495
496 #if !defined(CONFIG_DEBUG_SNAPSHOT_USER_MODE)
497 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", header);
498 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_kernel);
499 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_platform);
500 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_sfr);
501 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_s2d);
502 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_cachedump);
503 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_etm);
504 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_bcm);
505 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_pstore);
506 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_kevents);
507 #else
508 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", header);
509 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_kernel_user);
510 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_platform_user);
511 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_sfr_user);
512 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_s2d_user);
513 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_cachedump_user);
514 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_etm_user);
515 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_bcm_user);
516 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_pstore_user);
517 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_kevents_user);
518 #endif
519 #endif
520
521 /*
522 * ---------------------------------------------------------------------
523 * - dummy data:phy_addr, virtual_addr, buffer_size, magic_key(4K) -
524 * ---------------------------------------------------------------------
525 * - Cores MMU register(4K) -
526 * ---------------------------------------------------------------------
527 * - Cores CPU register(4K) -
528 * ---------------------------------------------------------------------
529 */
530 static int __init dbg_snapshot_output(void)
531 {
532 unsigned long i, size = 0;
533
534 pr_info("debug-snapshot physical / virtual memory layout:\n");
535 for (i = 0; i < ARRAY_SIZE(dss_items); i++) {
536 if (dss_items[i].entry.enabled)
537 pr_info("%-12s: phys:0x%zx / virt:0x%zx / size:0x%zx\n",
538 dss_items[i].name,
539 dss_items[i].entry.paddr,
540 dss_items[i].entry.vaddr,
541 dss_items[i].entry.size);
542 size += dss_items[i].entry.size;
543 }
544
545 pr_info("total_item_size: %ldKB, dbg_snapshot_log struct size: %dKB\n",
546 size / SZ_1K, dbg_snapshot_log_size / SZ_1K);
547
548 return 0;
549 }
550
551 /* Header dummy data(4K)
552 * -------------------------------------------------------------------------
553 * 0 4 8 C
554 * -------------------------------------------------------------------------
555 * 0 vaddr phy_addr size magic_code
556 * 4 Scratch_val logbuf_addr 0 0
557 * -------------------------------------------------------------------------
558 */
559
560 static void __init dbg_snapshot_fixmap_header(void)
561 {
562 /* fill 0 to next to header */
563 size_t vaddr, paddr, size;
564 size_t *addr;
565
566 vaddr = dss_items[dss_desc.header_num].entry.vaddr;
567 paddr = dss_items[dss_desc.header_num].entry.paddr;
568 size = dss_items[dss_desc.header_num].entry.size;
569
570 /* set to confirm debug-snapshot */
571 addr = (size_t *)vaddr;
572 memcpy(addr, &dss_base, sizeof(struct dbg_snapshot_base));
573
574 if (!dbg_snapshot_get_enable("header"))
575 return;
576
577 /* initialize kernel event to 0 except only header */
578 memset((size_t *)(vaddr + DSS_KEEP_HEADER_SZ), 0, size - DSS_KEEP_HEADER_SZ);
579 }
580
581 static void __init dbg_snapshot_fixmap(void)
582 {
583 size_t last_buf;
584 size_t vaddr, paddr, size;
585 unsigned long i;
586
587 /* fixmap to header first */
588 dbg_snapshot_fixmap_header();
589
590 for (i = 1; i < ARRAY_SIZE(dss_items); i++) {
591 if (!dss_items[i].entry.enabled)
592 continue;
593
594 /* assign dss_item information */
595 paddr = dss_items[i].entry.paddr;
596 vaddr = dss_items[i].entry.vaddr;
597 size = dss_items[i].entry.size;
598
599 if (i == dss_desc.log_kernel_num) {
600 /* load last_buf address value(phy) by virt address */
601 last_buf = (size_t)__raw_readl(dbg_snapshot_get_base_vaddr() +
602 DSS_OFFSET_LAST_LOGBUF);
603 /* check physical address offset of kernel logbuf */
604 if (last_buf >= dss_items[i].entry.paddr &&
605 (last_buf) <= (dss_items[i].entry.paddr + dss_items[i].entry.size)) {
606 /* assumed valid address, conversion to virt */
607 dss_items[i].curr_ptr = (unsigned char *)(dss_items[i].entry.vaddr +
608 (last_buf - dss_items[i].entry.paddr));
609 } else {
610 /* invalid address, set to first line */
611 dss_items[i].curr_ptr = (unsigned char *)vaddr;
612 /* initialize logbuf to 0 */
613 memset((size_t *)vaddr, 0, size);
614 }
615 } else {
616 /* initialized log to 0 if persist == false */
617 if (!dss_items[i].entry.persist)
618 memset((size_t *)vaddr, 0, size);
619 }
620 dss_info.info_log[i - 1].name = kstrdup(dss_items[i].name, GFP_KERNEL);
621 dss_info.info_log[i - 1].head_ptr = (unsigned char *)dss_items[i].entry.vaddr;
622 dss_info.info_log[i - 1].curr_ptr = NULL;
623 dss_info.info_log[i - 1].entry.size = size;
624 }
625
626 dss_log = (struct dbg_snapshot_log *)(dss_items[dss_desc.kevents_num].entry.vaddr);
627
628 /* set fake translation to virtual address to debug trace */
629 dss_info.info_event = dss_log;
630 ess_info = &dss_info;
631
632 /* output the information of debug-snapshot */
633 dbg_snapshot_output();
634 }
635
636 static int dbg_snapshot_init_dt_parse(struct device_node *np)
637 {
638 int ret = 0;
639 struct device_node *sfr_dump_np;
640
641 if (of_property_read_u32(np, "use_multistage_wdt_irq",
642 &dss_desc.multistage_wdt_irq)) {
643 dss_desc.multistage_wdt_irq = 0;
644 pr_err("debug-snapshot: no support multistage_wdt\n");
645 }
646
647 sfr_dump_np = of_get_child_by_name(np, "dump-info");
648 if (!sfr_dump_np) {
649 pr_err("debug-snapshot: failed to get dump-info node\n");
650 ret = -ENODEV;
651 } else {
652 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
653 ret = dbg_snapshot_sfr_dump_init(sfr_dump_np);
654 if (ret < 0) {
655 pr_err("debug-snapshot: failed to register sfr dump node\n");
656 ret = -ENODEV;
657 of_node_put(sfr_dump_np);
658 }
659 #endif
660 }
661 if (ret < 0)
662 dbg_snapshot_set_enable("log_sfr", false);
663
664 of_node_put(np);
665 return ret;
666 }
667
668 static const struct of_device_id dss_of_match[] __initconst = {
669 { .compatible = "debug-snapshot-soc",
670 .data = dbg_snapshot_init_dt_parse},
671 {},
672 };
673
674 static int __init dbg_snapshot_init_dt(void)
675 {
676 struct device_node *np;
677 const struct of_device_id *matched_np;
678 dss_initcall_t init_fn;
679
680 np = of_find_matching_node_and_match(NULL, dss_of_match, &matched_np);
681
682 if (!np) {
683 pr_info("debug-snapshot: couldn't find device tree file of debug-snapshot\n");
684 dbg_snapshot_set_enable("log_sfr", false);
685 return -ENODEV;
686 }
687
688 init_fn = (dss_initcall_t)matched_np->data;
689 return init_fn(np);
690 }
691
692 static int __init dbg_snapshot_init_value(void)
693 {
694 int val = dbg_snapshot_get_debug_level_reg();
695
696 dbg_snapshot_set_debug_level(val);
697
698 pr_info("debug-snapshot: debug_level [%s]\n",
699 debug_level_val[dss_desc.debug_level]);
700
701 dbg_snapshot_scratch_reg(DSS_SIGN_SCRATCH);
702
703 return 0;
704 }
705
706 static int __init dbg_snapshot_init(void)
707 {
708 dbg_snapshot_init_desc();
709 if (dbg_snapshot_remap() > 0) {
710 /*
711 * for debugging when we don't know the virtual address of pointer,
712 * In just privous the debug buffer, It is added 16byte dummy data.
713 * start address(dummy 16bytes)
714 * --> @virtual_addr | @phy_addr | @buffer_size | @magic_key(0xDBDBDBDB)
715 * And then, the debug buffer is shown.
716 */
717 dbg_snapshot_init_log_idx();
718 dbg_snapshot_fixmap();
719 dbg_snapshot_init_dt();
720 dbg_snapshot_init_helper();
721 dbg_snapshot_init_utils();
722 dbg_snapshot_init_value();
723
724 dbg_snapshot_set_enable("base", true);
725
726 register_hook_logbuf(dbg_snapshot_hook_logbuf);
727 register_hook_logger(dbg_snapshot_hook_logger);
728 } else
729 pr_err("debug-snapshot: %s failed\n", __func__);
730
731 return 0;
732 }
733 early_initcall(dbg_snapshot_init);