2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
5 * Debug-SnapShot: Debug Framework for Ramdump based debugging method
6 * The original code is Exynos-Snapshot for Exynos SoC
8 * Author: Hosung Kim <hosung0.kim@samsung.com>
9 * Author: Changki Kim <changki.kim@samsung.com>
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.
16 #include <linux/kernel.h>
17 #include <linux/version.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>
29 #include "debug-snapshot-local.h"
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>
37 extern void register_hook_logbuf(void (*)(const char *, size_t));
38 extern void register_hook_logger(void (*)(const char *, const char *, size_t));
40 struct dbg_snapshot_interface
{
41 struct dbg_snapshot_log
*info_event
;
42 struct dbg_snapshot_item info_log
[DSS_ITEM_MAX_NUM
];
45 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
46 struct dbg_snapshot_ops
{
47 int (*pd_status
)(unsigned int id
);
50 struct dbg_snapshot_ops dss_ops
= {
51 .pd_status
= cal_pd_status
,
55 const char *debug_level_val
[] = {
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, },
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
));
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
;
82 /* Variable for assigning virtual address base */
83 static size_t g_dbg_snapshot_vaddr_base
= DSS_FIXED_VIRT_BASE
;
85 int dbg_snapshot_set_debug_level(int level
)
87 if (level
> -1 && level
< ARRAY_SIZE(debug_level_val
)) {
88 dss_desc
.debug_level
= level
;
90 #if !IS_ENABLED(CONFIG_DEBUG_SNAPSHOT_USER_MODE)
91 dss_desc
.debug_level
= DSS_DEBUG_LEVEL_MID
;
93 dss_desc
.debug_level
= DSS_DEBUG_LEVEL_LOW
;
96 dbg_snapshot_set_debug_level_reg();
100 int dbg_snapshot_get_debug_level(void)
102 return dss_desc
.debug_level
;
105 int dbg_snapshot_set_enable(const char *name
, int en
)
107 struct dbg_snapshot_item
*item
= NULL
;
110 if (!strncmp(name
, "base", strlen(name
))) {
111 dss_base
.enabled
= en
;
112 pr_info("debug-snapshot: %sabled\n", en
? "en" : "dis");
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");
127 EXPORT_SYMBOL(dbg_snapshot_set_enable
);
129 int dbg_snapshot_try_enable(const char *name
, unsigned long long duration
)
131 struct dbg_snapshot_item
*item
= NULL
;
132 unsigned long long time
;
136 /* If DSS was disabled, just return */
137 if (unlikely(!dss_base
.enabled
) || !dbg_snapshot_get_enable("header"))
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
];
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;
158 EXPORT_SYMBOL(dbg_snapshot_try_enable
);
160 int dbg_snapshot_get_enable(const char *name
)
162 struct dbg_snapshot_item
*item
= NULL
;
166 if (!strncmp(name
, "base", strlen(name
)))
167 return dss_base
.enabled
;
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
;
178 EXPORT_SYMBOL(dbg_snapshot_get_enable
);
180 static inline int dbg_snapshot_check_eob(struct dbg_snapshot_item
*item
,
185 max
= (size_t)(item
->head_ptr
+ item
->entry
.size
);
186 cur
= (size_t)(item
->curr_ptr
+ size
);
188 if (unlikely(cur
> max
))
194 static inline void dbg_snapshot_hook_logger(const char *name
,
195 const char *buf
, size_t size
)
197 struct dbg_snapshot_item
*item
= &dss_items
[dss_desc
.log_platform_num
];
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
;
207 static inline void dbg_snapshot_hook_logbuf(const char *buf
, size_t size
)
209 struct dbg_snapshot_item
*item
= &dss_items
[dss_desc
.log_kernel_num
];
211 if (likely(dss_base
.enabled
&& item
->entry
.enabled
)) {
214 if (dbg_snapshot_check_eob(item
, size
))
215 item
->curr_ptr
= item
->head_ptr
;
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
;
222 __raw_writel(item
->entry
.paddr
+ (last_buf
- item
->entry
.vaddr
),
223 dbg_snapshot_get_base_vaddr() + DSS_OFFSET_LAST_LOGBUF
);
227 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
228 static bool dbg_snapshot_check_pmu(struct dbg_snapshot_sfrdump
*sfrdump
,
229 const struct device_node
*np
)
231 int ret
= 0, count
, i
;
234 if (!sfrdump
->pwr_mode
)
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
);
241 pr_err("failed to get pd-id - %s\n", sfrdump
->name
);
244 ret
= dss_ops
.pd_status(val
);
246 pr_err("not powered - %s (pd-id: %d)\n", sfrdump
->name
, i
);
253 void dbg_snapshot_dump_sfr(void)
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
;
261 static char buf
[SZ_64
];
263 if (unlikely(!dss_base
.enabled
|| !item
->entry
.enabled
))
266 if (list_empty(&dss_desc
.sfrdump_list
)) {
267 pr_emerg("debug-snapshot: %s: No information\n", __func__
);
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
);
279 for (i
= 0; i
< sfrdump
->num
; i
++) {
280 ret
= of_property_read_u32_index(np
, "addr", i
, ®
);
282 pr_err("debug-snapshot: failed to get address information - %s\n",
286 if (reg
== 0xFFFFFFFF || reg
== 0)
288 offset
= reg
- sfrdump
->phy_reg
;
290 pr_err("debug-snapshot: invalid address information - %s: 0x%08x\n",
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
);
303 pr_info("debug-snapshot: complete to dump %s\n", sfrdump
->name
);
308 static int dbg_snapshot_sfr_dump_init(struct device_node
*np
)
310 struct device_node
*dump_np
;
311 struct dbg_snapshot_sfrdump
*sfrdump
;
316 ret
= of_property_count_strings(np
, "sfr-dump-list");
318 pr_err("failed to get sfr-dump-list\n");
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
);
328 pr_err("failed to get sfr-dump-list\n");
332 dump_np
= of_get_child_by_name(np
, dump_str
);
334 pr_err("failed to get %s node, count:%d\n", dump_str
, count
);
338 sfrdump
= kzalloc(sizeof(struct dbg_snapshot_sfrdump
), GFP_KERNEL
);
340 pr_err("failed to get memory region of dbg_snapshot_sfrdump\n");
341 of_node_put(dump_np
);
345 ret
= of_property_read_u32_array(dump_np
, "reg", phy_regs
, 2);
347 pr_err("failed to get register information\n");
348 of_node_put(dump_np
);
353 sfrdump
->reg
= ioremap(phy_regs
[0], phy_regs
[1]);
355 pr_err("failed to get i/o address %s node\n", dump_str
);
356 of_node_put(dump_np
);
360 sfrdump
->name
= dump_str
;
362 ret
= of_property_count_u32_elems(dump_np
, "addr");
364 pr_err("failed to get addr count\n");
365 of_node_put(dump_np
);
369 sfrdump
->phy_reg
= phy_regs
[0];
372 ret
= of_property_count_u32_elems(dump_np
, "cal-pd-id");
374 sfrdump
->pwr_mode
= false;
376 sfrdump
->pwr_mode
= true;
378 sfrdump
->node
= dump_np
;
379 list_add(&sfrdump
->list
, &dss_desc
.sfrdump_list
);
381 pr_info("success to regsiter %s\n", sfrdump
->name
);
382 of_node_put(dump_np
);
389 static int __init
dbg_snapshot_remap(void)
392 unsigned int enabled_count
= 0;
393 pgprot_t prot
= __pgprot(PROT_NORMAL_NC
);
398 for (i
= 0; i
< ARRAY_SIZE(dss_items
); i
++) {
399 if (dss_items
[i
].entry
.enabled
) {
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
);
405 for (j
= 0; j
< page_size
; j
++)
408 ret
= map_vm_area(&dss_items
[i
].vm
, prot
, pages
);
411 pr_err("debug-snapshot: failed to mapping between virt and phys");
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
;
420 dss_desc
.log_cnt
= ARRAY_SIZE(dss_items
);
421 return enabled_count
;
424 static int __init
dbg_snapshot_init_desc(void)
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
);
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
;
450 #ifdef CONFIG_S3C2410_WATCHDOG
451 dss_desc
.no_wdt_dev
= false;
453 dss_desc
.no_wdt_dev
= true;
458 #ifdef CONFIG_OF_RESERVED_MEM
459 static int __init
dbg_snapshot_item_reserved_mem_setup(struct reserved_mem
*remem
)
463 for (i
= 0; i
< (unsigned int)ARRAY_SIZE(dss_items
); i
++) {
464 if (strnstr(remem
->name
, dss_items
[i
].name
, strlen(remem
->name
)))
468 if (i
== ARRAY_SIZE(dss_items
))
471 dss_items
[i
].entry
.paddr
= remem
->base
;
472 dss_items
[i
].entry
.size
= remem
->size
;
473 dss_items
[i
].entry
.enabled
= true;
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
;
481 vm_area_add_early(&dss_items
[i
].vm
);
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
;
487 dss_base
.enabled
= false;
489 dss_base
.size
+= remem
->size
;
493 #define DECLARE_DBG_SNAPSHOT_RESERVED_REGION(compat, name) \
494 RESERVEDMEM_OF_DECLARE(name, compat#name, dbg_snapshot_item_reserved_mem_setup)
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
);
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
);
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 * ---------------------------------------------------------------------
530 static int __init
dbg_snapshot_output(void)
532 unsigned long i
, size
= 0;
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",
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
;
545 pr_info("total_item_size: %ldKB, dbg_snapshot_log struct size: %dKB\n",
546 size
/ SZ_1K
, dbg_snapshot_log_size
/ SZ_1K
);
551 /* Header dummy data(4K)
552 * -------------------------------------------------------------------------
554 * -------------------------------------------------------------------------
555 * 0 vaddr phy_addr size magic_code
556 * 4 Scratch_val logbuf_addr 0 0
557 * -------------------------------------------------------------------------
560 static void __init
dbg_snapshot_fixmap_header(void)
562 /* fill 0 to next to header */
563 size_t vaddr
, paddr
, size
;
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
;
570 /* set to confirm debug-snapshot */
571 addr
= (size_t *)vaddr
;
572 memcpy(addr
, &dss_base
, sizeof(struct dbg_snapshot_base
));
574 if (!dbg_snapshot_get_enable("header"))
577 /* initialize kernel event to 0 except only header */
578 memset((size_t *)(vaddr
+ DSS_KEEP_HEADER_SZ
), 0, size
- DSS_KEEP_HEADER_SZ
);
581 static void __init
dbg_snapshot_fixmap(void)
584 size_t vaddr
, paddr
, size
;
587 /* fixmap to header first */
588 dbg_snapshot_fixmap_header();
590 for (i
= 1; i
< ARRAY_SIZE(dss_items
); i
++) {
591 if (!dss_items
[i
].entry
.enabled
)
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
;
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
));
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
);
616 /* initialized log to 0 if persist == false */
617 if (!dss_items
[i
].entry
.persist
)
618 memset((size_t *)vaddr
, 0, size
);
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
;
626 dss_log
= (struct dbg_snapshot_log
*)(dss_items
[dss_desc
.kevents_num
].entry
.vaddr
);
628 /* set fake translation to virtual address to debug trace */
629 dss_info
.info_event
= dss_log
;
630 ess_info
= &dss_info
;
632 /* output the information of debug-snapshot */
633 dbg_snapshot_output();
636 static int dbg_snapshot_init_dt_parse(struct device_node
*np
)
639 struct device_node
*sfr_dump_np
;
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");
647 sfr_dump_np
= of_get_child_by_name(np
, "dump-info");
649 pr_err("debug-snapshot: failed to get dump-info node\n");
652 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
653 ret
= dbg_snapshot_sfr_dump_init(sfr_dump_np
);
655 pr_err("debug-snapshot: failed to register sfr dump node\n");
657 of_node_put(sfr_dump_np
);
662 dbg_snapshot_set_enable("log_sfr", false);
668 static const struct of_device_id dss_of_match
[] __initconst
= {
669 { .compatible
= "debug-snapshot-soc",
670 .data
= dbg_snapshot_init_dt_parse
},
674 static int __init
dbg_snapshot_init_dt(void)
676 struct device_node
*np
;
677 const struct of_device_id
*matched_np
;
678 dss_initcall_t init_fn
;
680 np
= of_find_matching_node_and_match(NULL
, dss_of_match
, &matched_np
);
683 pr_info("debug-snapshot: couldn't find device tree file of debug-snapshot\n");
684 dbg_snapshot_set_enable("log_sfr", false);
688 init_fn
= (dss_initcall_t
)matched_np
->data
;
692 static int __init
dbg_snapshot_init_value(void)
694 int val
= dbg_snapshot_get_debug_level_reg();
696 dbg_snapshot_set_debug_level(val
);
698 pr_info("debug-snapshot: debug_level [%s]\n",
699 debug_level_val
[dss_desc
.debug_level
]);
701 dbg_snapshot_scratch_reg(DSS_SIGN_SCRATCH
);
706 static int __init
dbg_snapshot_init(void)
708 dbg_snapshot_init_desc();
709 if (dbg_snapshot_remap() > 0) {
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.
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();
724 dbg_snapshot_set_enable("base", true);
726 register_hook_logbuf(dbg_snapshot_hook_logbuf
);
727 register_hook_logger(dbg_snapshot_hook_logger
);
729 pr_err("debug-snapshot: %s failed\n", __func__
);
733 early_initcall(dbg_snapshot_init
);