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>
26 #include <linux/of_fdt.h>
27 #include <linux/of_address.h>
28 #include <linux/of_reserved_mem.h>
29 #include <linux/sched/clock.h>
31 #include "debug-snapshot-local.h"
33 /* To Support Samsung SoC */
34 #include <dt-bindings/soc/samsung/debug-snapshot-table.h>
35 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
36 #include <soc/samsung/cal-if.h>
39 extern void register_hook_logbuf(void (*)(const char *, size_t));
40 extern void register_hook_logger(void (*)(const char *, const char *, size_t));
42 struct dbg_snapshot_interface
{
43 struct dbg_snapshot_log
*info_event
;
44 struct dbg_snapshot_item info_log
[DSS_ITEM_MAX_NUM
];
47 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
48 struct dbg_snapshot_ops
{
49 int (*pd_status
)(unsigned int id
);
52 struct dbg_snapshot_ops dss_ops
= {
53 .pd_status
= cal_pd_status
,
57 const char *debug_level_val
[] = {
62 struct dbg_snapshot_bl
*dss_bl
;
63 struct dbg_snapshot_item dss_items
[] = {
64 {"header", {0, 0, 0, false, false}, NULL
,NULL
, 0, },
65 {"log_kernel", {0, 0, 0, false, false}, NULL
,NULL
, 0, },
66 {"log_platform", {0, 0, 0, false, false}, NULL
,NULL
, 0, },
67 {"log_sfr", {0, 0, 0, false, false}, NULL
,NULL
, 0, },
68 {"log_s2d", {0, 0, 0, true, false}, NULL
, NULL
, 0, },
69 {"log_cachedump", {0, 0, 0, true, false}, NULL
, NULL
, 0, },
70 {"log_etm", {0, 0, 0, true, false}, NULL
,NULL
, 0, },
71 {"log_bcm", {0, 0, 0, false, false}, NULL
,NULL
, 0, },
72 {"log_pstore", {0, 0, 0, true, false}, NULL
,NULL
, 0, },
73 {"log_kevents", {0, 0, 0, false, false}, NULL
,NULL
, 0, },
76 /* External interface variable for trace debugging */
77 static struct dbg_snapshot_interface dss_info
__attribute__ ((used
));
78 static struct dbg_snapshot_interface
*ess_info
__attribute__ ((used
));
80 struct dbg_snapshot_base dss_base
;
81 struct dbg_snapshot_base ess_base
;
82 struct dbg_snapshot_log
*dss_log
= NULL
;
83 struct dbg_snapshot_desc dss_desc
;
85 /* Variable for assigning virtual address base */
86 static size_t g_dbg_snapshot_vaddr_base
= DSS_FIXED_VIRT_BASE
;
88 int dbg_snapshot_get_debug_level(void)
90 return dss_desc
.debug_level
;
93 int dbg_snapshot_add_bl_item_info(const char *name
, unsigned int paddr
, unsigned int size
)
95 if (dss_bl
->item_count
>= SZ_16
)
98 memcpy(dss_bl
->item
[dss_bl
->item_count
].name
, name
, strlen(name
) + 1);
99 dss_bl
->item
[dss_bl
->item_count
].paddr
= paddr
;
100 dss_bl
->item
[dss_bl
->item_count
].size
= size
;
101 dss_bl
->item
[dss_bl
->item_count
].enabled
= 1;
102 dss_bl
->item_count
++;
107 int dbg_snapshot_set_enable(const char *name
, int en
)
109 struct dbg_snapshot_item
*item
= NULL
;
112 if (!strncmp(name
, "base", strlen(name
))) {
113 dss_base
.enabled
= en
;
114 pr_info("debug-snapshot: %sabled\n", en
? "en" : "dis");
116 for (i
= 0; i
< ARRAY_SIZE(dss_items
); i
++) {
117 if (!strncmp(dss_items
[i
].name
, name
, strlen(name
))) {
118 item
= &dss_items
[i
];
119 item
->entry
.enabled
= en
;
120 item
->time
= local_clock();
121 pr_info("debug-snapshot: item - %s is %sabled\n",
122 name
, en
? "en" : "dis");
129 EXPORT_SYMBOL(dbg_snapshot_set_enable
);
131 int dbg_snapshot_try_enable(const char *name
, unsigned long long duration
)
133 struct dbg_snapshot_item
*item
= NULL
;
134 unsigned long long time
;
138 /* If DSS was disabled, just return */
139 if (unlikely(!dss_base
.enabled
) || !dbg_snapshot_get_enable("header"))
142 for (i
= 0; i
< ARRAY_SIZE(dss_items
); i
++) {
143 if (!strncmp(dss_items
[i
].name
, name
, strlen(name
))) {
144 item
= &dss_items
[i
];
146 /* We only interest in disabled */
147 if (!item
->entry
.enabled
) {
148 time
= local_clock() - item
->time
;
149 if (time
> duration
) {
150 item
->entry
.enabled
= true;
160 EXPORT_SYMBOL(dbg_snapshot_try_enable
);
162 int dbg_snapshot_get_enable(const char *name
)
164 struct dbg_snapshot_item
*item
= NULL
;
168 if (!strncmp(name
, "base", strlen(name
)))
169 return dss_base
.enabled
;
171 for (i
= 0; i
< ARRAY_SIZE(dss_items
); i
++) {
172 if (!strncmp(dss_items
[i
].name
, name
, strlen(name
))) {
173 item
= &dss_items
[i
];
174 ret
= item
->entry
.enabled
;
180 EXPORT_SYMBOL(dbg_snapshot_get_enable
);
182 static inline int dbg_snapshot_check_eob(struct dbg_snapshot_item
*item
,
187 max
= (size_t)(item
->head_ptr
+ item
->entry
.size
);
188 cur
= (size_t)(item
->curr_ptr
+ size
);
190 if (unlikely(cur
> max
))
196 static inline void dbg_snapshot_hook_logger(const char *name
,
197 const char *buf
, size_t size
)
199 struct dbg_snapshot_item
*item
= &dss_items
[dss_desc
.log_platform_num
];
201 if (likely(dss_base
.enabled
&& item
->entry
.enabled
)) {
204 if (unlikely((dbg_snapshot_check_eob(item
, size
))))
205 item
->curr_ptr
= item
->head_ptr
;
207 memcpy(item
->curr_ptr
, buf
, size
);
208 item
->curr_ptr
+= size
;
209 /* save the address of last_buf to physical address */
210 last_buf
= (size_t)item
->curr_ptr
;
212 __raw_writel(item
->entry
.paddr
+ (last_buf
- item
->entry
.vaddr
),
213 dbg_snapshot_get_base_vaddr() + DSS_OFFSET_LAST_PLATFORM_LOGBUF
);
217 static inline void dbg_snapshot_hook_logbuf(const char *buf
, size_t size
)
219 struct dbg_snapshot_item
*item
= &dss_items
[dss_desc
.log_kernel_num
];
221 if (likely(dss_base
.enabled
&& item
->entry
.enabled
)) {
224 if (dbg_snapshot_check_eob(item
, size
))
225 item
->curr_ptr
= item
->head_ptr
;
227 memcpy(item
->curr_ptr
, buf
, size
);
228 item
->curr_ptr
+= size
;
229 /* save the address of last_buf to physical address */
230 last_buf
= (size_t)item
->curr_ptr
;
232 __raw_writel(item
->entry
.paddr
+ (last_buf
- item
->entry
.vaddr
),
233 dbg_snapshot_get_base_vaddr() + DSS_OFFSET_LAST_LOGBUF
);
237 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
238 static bool dbg_snapshot_check_pmu(struct dbg_snapshot_sfrdump
*sfrdump
,
239 const struct device_node
*np
)
241 int ret
= 0, count
, i
;
244 if (!sfrdump
->pwr_mode
)
247 count
= of_property_count_u32_elems(np
, "cal-pd-id");
248 for (i
= 0; i
< count
; i
++) {
249 ret
= of_property_read_u32_index(np
, "cal-pd-id", i
, &val
);
251 pr_err("failed to get pd-id - %s\n", sfrdump
->name
);
254 ret
= dss_ops
.pd_status(val
);
256 pr_err("not powered - %s (pd-id: %d)\n", sfrdump
->name
, i
);
263 void dbg_snapshot_dump_sfr(void)
265 struct dbg_snapshot_sfrdump
*sfrdump
;
266 struct dbg_snapshot_item
*item
= &dss_items
[dss_desc
.log_sfr_num
];
267 struct list_head
*entry
;
268 struct device_node
*np
;
269 unsigned int reg
, offset
, val
, size
;
271 static char buf
[SZ_64
];
273 if (unlikely(!dss_base
.enabled
|| !item
->entry
.enabled
))
276 if (list_empty(&dss_desc
.sfrdump_list
)) {
277 pr_emerg("debug-snapshot: %s: No information\n", __func__
);
281 list_for_each(entry
, &dss_desc
.sfrdump_list
) {
282 sfrdump
= list_entry(entry
, struct dbg_snapshot_sfrdump
, list
);
283 np
= of_node_get(sfrdump
->node
);
284 ret
= dbg_snapshot_check_pmu(sfrdump
, np
);
289 for (i
= 0; i
< sfrdump
->num
; i
++) {
290 ret
= of_property_read_u32_index(np
, "addr", i
, ®
);
292 pr_err("debug-snapshot: failed to get address information - %s\n",
296 if (reg
== 0xFFFFFFFF || reg
== 0)
298 offset
= reg
- sfrdump
->phy_reg
;
300 pr_err("debug-snapshot: invalid address information - %s: 0x%08x\n",
304 val
= __raw_readl(sfrdump
->reg
+ offset
);
305 snprintf(buf
, SZ_64
, "0x%X = 0x%0X\n",reg
, val
);
306 size
= (unsigned int)strlen(buf
);
307 if (unlikely((dbg_snapshot_check_eob(item
, size
))))
308 item
->curr_ptr
= item
->head_ptr
;
309 memcpy(item
->curr_ptr
, buf
, strlen(buf
));
310 item
->curr_ptr
+= strlen(buf
);
313 pr_info("debug-snapshot: complete to dump %s\n", sfrdump
->name
);
318 static int dbg_snapshot_sfr_dump_init(struct device_node
*np
)
320 struct device_node
*dump_np
;
321 struct dbg_snapshot_sfrdump
*sfrdump
;
326 ret
= of_property_count_strings(np
, "sfr-dump-list");
328 pr_err("failed to get sfr-dump-list\n");
333 INIT_LIST_HEAD(&dss_desc
.sfrdump_list
);
334 for (i
= 0; i
< count
; i
++) {
335 ret
= of_property_read_string_index(np
, "sfr-dump-list", i
,
336 (const char **)&dump_str
);
338 pr_err("failed to get sfr-dump-list\n");
342 dump_np
= of_get_child_by_name(np
, dump_str
);
344 pr_err("failed to get %s node, count:%d\n", dump_str
, count
);
348 sfrdump
= kzalloc(sizeof(struct dbg_snapshot_sfrdump
), GFP_KERNEL
);
350 pr_err("failed to get memory region of dbg_snapshot_sfrdump\n");
351 of_node_put(dump_np
);
355 ret
= of_property_read_u32_array(dump_np
, "reg", phy_regs
, 2);
357 pr_err("failed to get register information\n");
358 of_node_put(dump_np
);
363 sfrdump
->reg
= ioremap(phy_regs
[0], phy_regs
[1]);
365 pr_err("failed to get i/o address %s node\n", dump_str
);
366 of_node_put(dump_np
);
370 sfrdump
->name
= dump_str
;
372 ret
= of_property_count_u32_elems(dump_np
, "addr");
374 pr_err("failed to get addr count\n");
375 of_node_put(dump_np
);
379 sfrdump
->phy_reg
= phy_regs
[0];
382 ret
= of_property_count_u32_elems(dump_np
, "cal-pd-id");
384 sfrdump
->pwr_mode
= false;
386 sfrdump
->pwr_mode
= true;
388 sfrdump
->node
= dump_np
;
389 list_add(&sfrdump
->list
, &dss_desc
.sfrdump_list
);
391 pr_info("success to regsiter %s\n", sfrdump
->name
);
392 of_node_put(dump_np
);
399 static int __init
dbg_snapshot_remap(void)
402 unsigned int enabled_count
= 0;
403 pgprot_t prot
= __pgprot(PROT_NORMAL_NC
);
408 for (i
= 0; i
< ARRAY_SIZE(dss_items
); i
++) {
409 if (dss_items
[i
].entry
.enabled
) {
411 page_size
= dss_items
[i
].entry
.size
/ PAGE_SIZE
;
412 pages
= kzalloc(sizeof(struct page
*) * page_size
, GFP_KERNEL
);
413 page
= phys_to_page(dss_items
[i
].entry
.paddr
);
415 for (j
= 0; j
< page_size
; j
++)
418 ret
= map_vm_area(&dss_items
[i
].vm
, prot
, pages
);
421 pr_err("debug-snapshot: failed to mapping between virt and phys");
425 dss_items
[i
].entry
.vaddr
= (size_t)dss_items
[i
].vm
.addr
;
426 dss_items
[i
].head_ptr
= (unsigned char *)dss_items
[i
].entry
.vaddr
;
427 dss_items
[i
].curr_ptr
= (unsigned char *)dss_items
[i
].entry
.vaddr
;
430 dss_desc
.log_cnt
= ARRAY_SIZE(dss_items
);
431 return enabled_count
;
434 static int __init
dbg_snapshot_init_desc(void)
438 /* initialize dss_desc */
439 memset((struct dbg_snapshot_desc
*)&dss_desc
, 0, sizeof(struct dbg_snapshot_desc
));
440 dss_desc
.callstack
= CONFIG_DEBUG_SNAPSHOT_CALLSTACK
;
441 raw_spin_lock_init(&dss_desc
.ctrl_lock
);
442 raw_spin_lock_init(&dss_desc
.nmi_lock
);
444 for (i
= 0; i
< (unsigned int)ARRAY_SIZE(dss_items
); i
++) {
445 len
= strlen(dss_items
[i
].name
);
446 if (!strncmp(dss_items
[i
].name
, "header", len
))
447 dss_desc
.header_num
= i
;
448 else if (!strncmp(dss_items
[i
].name
, "log_kevents", len
))
449 dss_desc
.kevents_num
= i
;
450 else if (!strncmp(dss_items
[i
].name
, "log_kernel", len
))
451 dss_desc
.log_kernel_num
= i
;
452 else if (!strncmp(dss_items
[i
].name
, "log_platform", len
))
453 dss_desc
.log_platform_num
= i
;
454 else if (!strncmp(dss_items
[i
].name
, "log_sfr", len
))
455 dss_desc
.log_sfr_num
= i
;
456 else if (!strncmp(dss_items
[i
].name
, "log_pstore", len
))
457 dss_desc
.log_pstore_num
= i
;
460 #ifdef CONFIG_S3C2410_WATCHDOG
461 dss_desc
.no_wdt_dev
= false;
463 dss_desc
.no_wdt_dev
= true;
468 #ifdef CONFIG_OF_RESERVED_MEM
469 int __init
dbg_snapshot_reserved_mem_check(unsigned long node
, unsigned long size
)
474 name
= of_get_flat_dt_prop(node
, "compatible", NULL
);
478 if (!strstr(name
, "debug-snapshot"))
481 if (!strstr(name
, "log"))
489 #if !defined(CONFIG_DEBUG_SNAPSHOT_USER_MODE)
490 if (strstr(name
, "user"))
493 if (!strstr(name
, "user"))
500 static int __init
dbg_snapshot_item_reserved_mem_setup(struct reserved_mem
*remem
)
504 for (i
= 0; i
< (unsigned int)ARRAY_SIZE(dss_items
); i
++) {
505 if (strnstr(remem
->name
, dss_items
[i
].name
, strlen(remem
->name
)))
509 if (i
== ARRAY_SIZE(dss_items
))
512 dss_items
[i
].entry
.paddr
= remem
->base
;
513 dss_items
[i
].entry
.size
= remem
->size
;
514 dss_items
[i
].entry
.enabled
= true;
516 dss_items
[i
].vm
.phys_addr
= remem
->base
;
517 dss_items
[i
].vm
.addr
= (void *)g_dbg_snapshot_vaddr_base
;
518 dss_items
[i
].vm
.size
= remem
->size
;
519 dss_items
[i
].vm
.flags
= VM_NO_GUARD
;
520 g_dbg_snapshot_vaddr_base
+= remem
->size
;
522 vm_area_add_early(&dss_items
[i
].vm
);
524 if (strnstr(remem
->name
, "header", strlen(remem
->name
))) {
525 dss_base
.paddr
= remem
->base
;
526 dss_base
.vaddr
= (size_t)dss_items
[i
].vm
.addr
;
528 dss_base
.enabled
= false;
530 dss_base
.size
+= remem
->size
;
534 #define DECLARE_DBG_SNAPSHOT_RESERVED_REGION(compat, name) \
535 RESERVEDMEM_OF_DECLARE(name, compat#name, dbg_snapshot_item_reserved_mem_setup)
537 #if !defined(CONFIG_DEBUG_SNAPSHOT_USER_MODE)
538 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", header
);
539 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_kernel
);
540 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_platform
);
541 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_sfr
);
542 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_s2d
);
543 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_cachedump
);
544 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_etm
);
545 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_bcm
);
546 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_pstore
);
547 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_kevents
);
549 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", header
);
550 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_kernel_user
);
551 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_platform_user
);
552 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_sfr_user
);
553 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_s2d_user
);
554 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_cachedump_user
);
555 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_etm_user
);
556 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_bcm_user
);
557 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_pstore_user
);
558 DECLARE_DBG_SNAPSHOT_RESERVED_REGION("debug-snapshot,", log_kevents_user
);
563 * ---------------------------------------------------------------------
564 * - dummy data:phy_addr, virtual_addr, buffer_size, magic_key(4K) -
565 * ---------------------------------------------------------------------
566 * - Cores MMU register(4K) -
567 * ---------------------------------------------------------------------
568 * - Cores CPU register(4K) -
569 * ---------------------------------------------------------------------
571 static int __init
dbg_snapshot_output(void)
573 unsigned long i
, size
= 0;
575 pr_info("debug-snapshot physical / virtual memory layout:\n");
576 for (i
= 0; i
< ARRAY_SIZE(dss_items
); i
++) {
577 if (dss_items
[i
].entry
.enabled
)
578 pr_info("%-12s: phys:0x%zx / virt:0x%zx / size:0x%zx\n",
580 dss_items
[i
].entry
.paddr
,
581 dss_items
[i
].entry
.vaddr
,
582 dss_items
[i
].entry
.size
);
583 size
+= dss_items
[i
].entry
.size
;
586 pr_info("total_item_size: %ldKB, dbg_snapshot_log struct size: %dKB\n",
587 size
/ SZ_1K
, dbg_snapshot_log_size
/ SZ_1K
);
592 /* Header dummy data(4K)
593 * -------------------------------------------------------------------------
595 * -------------------------------------------------------------------------
596 * 0 vaddr phy_addr size magic_code
597 * 4 Scratch_val logbuf_addr 0 0
598 * -------------------------------------------------------------------------
601 static void __init
dbg_snapshot_fixmap_header(void)
603 /* fill 0 to next to header */
604 size_t vaddr
, paddr
, size
;
607 vaddr
= dss_items
[dss_desc
.header_num
].entry
.vaddr
;
608 paddr
= dss_items
[dss_desc
.header_num
].entry
.paddr
;
609 size
= dss_items
[dss_desc
.header_num
].entry
.size
;
611 /* set to confirm debug-snapshot */
612 addr
= (size_t *)vaddr
;
613 memcpy(addr
, &dss_base
, sizeof(struct dbg_snapshot_base
));
615 if (!dbg_snapshot_get_enable("header"))
618 /* initialize kernel event to 0 except only header */
619 memset((size_t *)(vaddr
+ DSS_KEEP_HEADER_SZ
), 0, size
- DSS_KEEP_HEADER_SZ
);
621 dss_bl
= dbg_snapshot_get_base_vaddr() + DSS_OFFSET_ITEM_INFO
;
622 memset(dss_bl
, 0, sizeof(struct dbg_snapshot_bl
));
623 dss_bl
->magic1
= 0x01234567;
624 dss_bl
->magic2
= 0x89ABCDEF;
625 dss_bl
->item_count
= ARRAY_SIZE(dss_items
);
626 memcpy(dss_bl
->item
[dss_desc
.header_num
].name
,
627 dss_items
[dss_desc
.header_num
].name
,
628 strlen(dss_items
[dss_desc
.header_num
].name
) + 1);
629 dss_bl
->item
[dss_desc
.header_num
].paddr
= paddr
;
630 dss_bl
->item
[dss_desc
.header_num
].size
= size
;
631 dss_bl
->item
[dss_desc
.header_num
].enabled
=
632 dss_items
[dss_desc
.header_num
].entry
.enabled
;
635 static void __init
dbg_snapshot_fixmap(void)
638 size_t vaddr
, paddr
, size
;
641 /* fixmap to header first */
642 dbg_snapshot_fixmap_header();
644 for (i
= 1; i
< ARRAY_SIZE(dss_items
); i
++) {
645 memcpy(dss_bl
->item
[i
].name
,
647 strlen(dss_items
[i
].name
) + 1);
648 dss_bl
->item
[i
].enabled
= dss_items
[i
].entry
.enabled
;
650 if (!dss_items
[i
].entry
.enabled
)
653 /* assign dss_item information */
654 paddr
= dss_items
[i
].entry
.paddr
;
655 vaddr
= dss_items
[i
].entry
.vaddr
;
656 size
= dss_items
[i
].entry
.size
;
658 if (i
== dss_desc
.log_kernel_num
) {
659 /* load last_buf address value(phy) by virt address */
660 last_buf
= (size_t)__raw_readl(dbg_snapshot_get_base_vaddr() +
661 DSS_OFFSET_LAST_LOGBUF
);
662 /* check physical address offset of kernel logbuf */
663 if (last_buf
>= dss_items
[i
].entry
.paddr
&&
664 (last_buf
) <= (dss_items
[i
].entry
.paddr
+ dss_items
[i
].entry
.size
)) {
665 /* assumed valid address, conversion to virt */
666 dss_items
[i
].curr_ptr
= (unsigned char *)(dss_items
[i
].entry
.vaddr
+
667 (last_buf
- dss_items
[i
].entry
.paddr
));
669 /* invalid address, set to first line */
670 dss_items
[i
].curr_ptr
= (unsigned char *)vaddr
;
671 /* initialize logbuf to 0 */
672 memset((size_t *)vaddr
, 0, size
);
674 } else if (i
== dss_desc
.log_platform_num
) {
675 last_buf
= (size_t)__raw_readl(dbg_snapshot_get_base_vaddr() +
676 DSS_OFFSET_LAST_PLATFORM_LOGBUF
);
677 if (last_buf
>= dss_items
[i
].entry
.vaddr
&&
678 (last_buf
) <= (dss_items
[i
].entry
.vaddr
+ dss_items
[i
].entry
.size
)) {
679 dss_items
[i
].curr_ptr
= (unsigned char *)(last_buf
);
681 dss_items
[i
].curr_ptr
= (unsigned char *)vaddr
;
682 memset((size_t *)vaddr
, 0, size
);
685 /* initialized log to 0 if persist == false */
686 if (!dss_items
[i
].entry
.persist
)
687 memset((size_t *)vaddr
, 0, size
);
689 dss_info
.info_log
[i
- 1].name
= kstrdup(dss_items
[i
].name
, GFP_KERNEL
);
690 dss_info
.info_log
[i
- 1].head_ptr
= (unsigned char *)dss_items
[i
].entry
.vaddr
;
691 dss_info
.info_log
[i
- 1].curr_ptr
= NULL
;
692 dss_info
.info_log
[i
- 1].entry
.size
= size
;
694 memcpy(dss_bl
->item
[i
].name
,
696 strlen(dss_items
[i
].name
) + 1);
697 dss_bl
->item
[i
].paddr
= paddr
;
698 dss_bl
->item
[i
].size
= size
;
701 dss_log
= (struct dbg_snapshot_log
*)(dss_items
[dss_desc
.kevents_num
].entry
.vaddr
);
703 /* set fake translation to virtual address to debug trace */
704 dss_info
.info_event
= dss_log
;
705 ess_info
= &dss_info
;
707 /* output the information of debug-snapshot */
708 dbg_snapshot_output();
711 static int dbg_snapshot_init_dt_parse(struct device_node
*np
)
714 struct device_node
*sfr_dump_np
;
716 if (of_property_read_u32(np
, "use_multistage_wdt_irq",
717 &dss_desc
.multistage_wdt_irq
)) {
718 dss_desc
.multistage_wdt_irq
= 0;
719 pr_err("debug-snapshot: no support multistage_wdt\n");
722 sfr_dump_np
= of_get_child_by_name(np
, "dump-info");
724 pr_err("debug-snapshot: failed to get dump-info node\n");
727 #ifdef CONFIG_DEBUG_SNAPSHOT_PMU
728 ret
= dbg_snapshot_sfr_dump_init(sfr_dump_np
);
730 pr_err("debug-snapshot: failed to register sfr dump node\n");
732 of_node_put(sfr_dump_np
);
737 dbg_snapshot_set_enable("log_sfr", false);
743 static const struct of_device_id dss_of_match
[] __initconst
= {
744 { .compatible
= "debug-snapshot-soc",
745 .data
= dbg_snapshot_init_dt_parse
},
749 static int __init
dbg_snapshot_init_dt(void)
751 struct device_node
*np
;
752 const struct of_device_id
*matched_np
;
753 dss_initcall_t init_fn
;
755 np
= of_find_matching_node_and_match(NULL
, dss_of_match
, &matched_np
);
758 pr_info("debug-snapshot: couldn't find device tree file of debug-snapshot\n");
759 dbg_snapshot_set_enable("log_sfr", false);
763 init_fn
= (dss_initcall_t
)matched_np
->data
;
767 static int __init
dbg_snapshot_init_value(void)
769 dss_desc
.debug_level
= dbg_snapshot_get_debug_level_reg();
771 pr_info("debug-snapshot: debug_level [%s]\n",
772 debug_level_val
[dss_desc
.debug_level
]);
774 if (dss_desc
.debug_level
!= DSS_DEBUG_LEVEL_LOW
)
775 dbg_snapshot_scratch_reg(DSS_SIGN_SCRATCH
);
777 /* copy linux_banner, physical address of
778 * kernel log / platform log / kevents to DSS header */
779 strncpy(dbg_snapshot_get_base_vaddr() + DSS_OFFSET_LINUX_BANNER
,
780 linux_banner
, strlen(linux_banner
));
785 static int __init
dbg_snapshot_init(void)
787 dbg_snapshot_init_desc();
788 if (dbg_snapshot_remap() > 0) {
790 * for debugging when we don't know the virtual address of pointer,
791 * In just privous the debug buffer, It is added 16byte dummy data.
792 * start address(dummy 16bytes)
793 * --> @virtual_addr | @phy_addr | @buffer_size | @magic_key(0xDBDBDBDB)
794 * And then, the debug buffer is shown.
796 dbg_snapshot_init_log_idx();
797 dbg_snapshot_fixmap();
798 dbg_snapshot_init_dt();
799 dbg_snapshot_init_helper();
800 dbg_snapshot_init_utils();
801 dbg_snapshot_init_value();
803 dbg_snapshot_set_enable("base", true);
805 register_hook_logbuf(dbg_snapshot_hook_logbuf
);
806 register_hook_logger(dbg_snapshot_hook_logger
);
808 pr_err("debug-snapshot: %s failed\n", __func__
);
812 early_initcall(dbg_snapshot_init
);