xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/pstore.c (revision ba5f195c2946036e4462feb5ccec99dfe7bc4f8f)
1ad771a9cSHuibin Hong /*
2ad771a9cSHuibin Hong  * (C) Copyright 2022 Rockchip Electronics Co., Ltd.
3ad771a9cSHuibin Hong  *
4ad771a9cSHuibin Hong  * SPDX-License-Identifier:     GPL-2.0+
5ad771a9cSHuibin Hong  */
6ad771a9cSHuibin Hong 
7ad771a9cSHuibin Hong /*
8ad771a9cSHuibin Hong  * Example:
9ad771a9cSHuibin Hong  *	ramoops: ramoops@110000 {
10ad771a9cSHuibin Hong  *		compatible = "ramoops";
11ad771a9cSHuibin Hong  *		reg = <0x0 0x110000 0x0 0xe0000>;
12ad771a9cSHuibin Hong  *		boot-log-size = <0x8000>;
13ad771a9cSHuibin Hong  *		boot-log-count = <0x1>
14ad771a9cSHuibin Hong  *		console-size = <0x80000>;
15ad771a9cSHuibin Hong  *		pmsg-size = <0x30000>;
16ad771a9cSHuibin Hong  *		ftrace-size = <0x00000>;
17ad771a9cSHuibin Hong  *		record-size = <0x14000>;
18ad771a9cSHuibin Hong  *	};
19ad771a9cSHuibin Hong  */
20ad771a9cSHuibin Hong 
21ad771a9cSHuibin Hong #include <common.h>
22ad771a9cSHuibin Hong #include <asm/arch/rk_atags.h>
23ad771a9cSHuibin Hong 
24ad771a9cSHuibin Hong DECLARE_GLOBAL_DATA_PTR;
25ad771a9cSHuibin Hong 
26ad771a9cSHuibin Hong #define PERSISTENT_RAM_SIG		(0x43474244)
27ad771a9cSHuibin Hong #define LOG_TYPE_MASK			(0x00000fff)
28ad771a9cSHuibin Hong 
29ad771a9cSHuibin Hong struct persistent_ram_buffer {
30ad771a9cSHuibin Hong 	u32    sig;
31ad771a9cSHuibin Hong 	u32    start;
32ad771a9cSHuibin Hong 	u32    size;
33ad771a9cSHuibin Hong 	u8     data[0];
34ad771a9cSHuibin Hong };
35ad771a9cSHuibin Hong 
36ad771a9cSHuibin Hong enum log_type {
37ad771a9cSHuibin Hong 	LOG_TPL = 0,
38ad771a9cSHuibin Hong 	LOG_SPL,
39ad771a9cSHuibin Hong 	LOG_OPTEE,
40ad771a9cSHuibin Hong 	LOG_ATF,
41ad771a9cSHuibin Hong 	LOG_UBOOT,
42ad771a9cSHuibin Hong 	LOG_MAX = 12,
43ad771a9cSHuibin Hong };
44ad771a9cSHuibin Hong 
45ad771a9cSHuibin Hong #if 0
46ad771a9cSHuibin Hong /*
47ad771a9cSHuibin Hong  * This function is to be called by tpl/ddr.
48ad771a9cSHuibin Hong  *
49ad771a9cSHuibin Hong  * u32 'conf' definition:
50ad771a9cSHuibin Hong  *   [31:16] is pstore buffer base address (0x_[31:16]_0000), 64KB align.
51ad771a9cSHuibin Hong  *   [15:12] is pstore buffer size [15:12]*4KB.
52ad771a9cSHuibin Hong  *   [11:0] see 'enum log_type' per bit is for one stage, 1: enable, 0: disable.
53ad771a9cSHuibin Hong  *      [0] tpl(ddr)
54ad771a9cSHuibin Hong  *      [1] spl(miniloader)
55ad771a9cSHuibin Hong  *      [2] optee(bl32)
56ad771a9cSHuibin Hong  *      [3] atf(bl31)
57ad771a9cSHuibin Hong  *      [4] U-Boot
58ad771a9cSHuibin Hong  *      ...
59ad771a9cSHuibin Hong  */
60ad771a9cSHuibin Hong void pstore_atags_set_tag(u32 conf)
61ad771a9cSHuibin Hong {
62ad771a9cSHuibin Hong 	struct tag_pstore t;
63ad771a9cSHuibin Hong 	u32 addr = conf & 0xffff0000;
64ad771a9cSHuibin Hong 	u32 size = conf & 0x0000f000;
65ad771a9cSHuibin Hong 	int i = 0;
66ad771a9cSHuibin Hong 
67ad771a9cSHuibin Hong 	/* handle special: 0 is 64KB but not 0KB */
68ad771a9cSHuibin Hong 	if (size == 0)
69ad771a9cSHuibin Hong 		size = 0x10000;
70ad771a9cSHuibin Hong 
71ad771a9cSHuibin Hong 	/* is enabled log type ? */
72ad771a9cSHuibin Hong 	conf &= LOG_TYPE_MASK;
73ad771a9cSHuibin Hong 	if (conf == 0)
74ad771a9cSHuibin Hong 		return;
75ad771a9cSHuibin Hong 
76ad771a9cSHuibin Hong 	t.version = 0;
77ad771a9cSHuibin Hong 	for (i = 0; i < LOG_MAX; i++) {
78ad771a9cSHuibin Hong 		if (conf & (1 << (i))) {
79ad771a9cSHuibin Hong 			t.buf[i].addr = addr;
80ad771a9cSHuibin Hong 			t.buf[i].size = size;
81ad771a9cSHuibin Hong 		} else {
82ad771a9cSHuibin Hong 			t.buf[i].addr = 0x0;
83ad771a9cSHuibin Hong 			t.buf[i].size = 0x0;
84ad771a9cSHuibin Hong 		}
85ad771a9cSHuibin Hong 	}
86ad771a9cSHuibin Hong 
87ad771a9cSHuibin Hong 	atags_set_tag(ATAG_PSTORE, &t);
88ad771a9cSHuibin Hong }
89ad771a9cSHuibin Hong #endif
90ad771a9cSHuibin Hong 
param_parse_pstore(void)91ad771a9cSHuibin Hong int param_parse_pstore(void)
92ad771a9cSHuibin Hong {
93ad771a9cSHuibin Hong 	struct persistent_ram_buffer *rb = NULL;
94ad771a9cSHuibin Hong 	u32 pstore_size = 0;
95ad771a9cSHuibin Hong #if defined(CONFIG_ROCKCHIP_PRELOADER_ATAGS) && (CONFIG_PERSISTENT_RAM_ADDR == 0)
96ad771a9cSHuibin Hong 	struct tag *t;
97ad771a9cSHuibin Hong 
98ad771a9cSHuibin Hong 	gd->pstore_addr = 0;
99ad771a9cSHuibin Hong 	gd->pstore_size = 0;
100ad771a9cSHuibin Hong 
101ad771a9cSHuibin Hong 	t = atags_get_tag(ATAG_PSTORE);
102ad771a9cSHuibin Hong 	if (t) {
103ad771a9cSHuibin Hong 		gd->pstore_addr = t->u.pstore.buf[LOG_UBOOT].addr;
104ad771a9cSHuibin Hong 		gd->pstore_size = t->u.pstore.buf[LOG_UBOOT].size - sizeof(struct persistent_ram_buffer);
105ad771a9cSHuibin Hong 	}
1060a7aeeb2SJoseph Chen #elif (CONFIG_PERSISTENT_RAM_ADDR == 0 || CONFIG_PERSISTENT_RAM_SIZE == 0)
1070a7aeeb2SJoseph Chen 	#error: CONFIG_PERSISTENT_RAM_SIZE and CONFIG_PERSISTENT_RAM_ADDR value should not be 0.
108ad771a9cSHuibin Hong #else
109ad771a9cSHuibin Hong 	gd->pstore_addr = CONFIG_PERSISTENT_RAM_ADDR;
110ad771a9cSHuibin Hong 	gd->pstore_size = CONFIG_PERSISTENT_RAM_SIZE - sizeof(struct persistent_ram_buffer);
111ad771a9cSHuibin Hong #endif
112ad771a9cSHuibin Hong 	if (gd->pstore_addr) {
113ad771a9cSHuibin Hong 		rb = (struct persistent_ram_buffer *)gd->pstore_addr;
114ad771a9cSHuibin Hong 		pstore_size = gd->pstore_size;
115ad771a9cSHuibin Hong 
116ad771a9cSHuibin Hong 		if (rb->sig != PERSISTENT_RAM_SIG) {
117ad771a9cSHuibin Hong 			rb->sig = PERSISTENT_RAM_SIG;
118ad771a9cSHuibin Hong 			rb->start = 0x0;
119ad771a9cSHuibin Hong 			rb->size = 0x0;
120ad771a9cSHuibin Hong 		}
121ad771a9cSHuibin Hong 
122ad771a9cSHuibin Hong 		if (rb->size > pstore_size)
123ad771a9cSHuibin Hong 			rb->size = pstore_size;
124ad771a9cSHuibin Hong 
125ad771a9cSHuibin Hong 		if (rb->start >= pstore_size)
126ad771a9cSHuibin Hong 			rb->start = 0;
127ad771a9cSHuibin Hong 	}
128ad771a9cSHuibin Hong 
129ad771a9cSHuibin Hong 	return 0;
130ad771a9cSHuibin Hong }
131ad771a9cSHuibin Hong 
putc_to_ram(const char c)132ad771a9cSHuibin Hong void putc_to_ram(const char c)
133ad771a9cSHuibin Hong {
134ad771a9cSHuibin Hong 	struct persistent_ram_buffer *rb = (struct persistent_ram_buffer *)gd->pstore_addr;
135ad771a9cSHuibin Hong 	u32 pstore_size = gd->pstore_size;
136ad771a9cSHuibin Hong 	u8 *dst;
137ad771a9cSHuibin Hong 
138ad771a9cSHuibin Hong 	if (!rb || pstore_size == 0)
139ad771a9cSHuibin Hong 		return;
140ad771a9cSHuibin Hong 
141*ba5f195cSHuibin Hong 	if (rb->start >= pstore_size)
142*ba5f195cSHuibin Hong 		rb->start = 0;
143*ba5f195cSHuibin Hong 
144ad771a9cSHuibin Hong 	dst = rb->data + rb->start;
145ad771a9cSHuibin Hong 	*dst = c;
146ad771a9cSHuibin Hong 
147ad771a9cSHuibin Hong 	if (rb->size < pstore_size)
148ad771a9cSHuibin Hong 		rb->size++;
149*ba5f195cSHuibin Hong 	else
150*ba5f195cSHuibin Hong 		rb->size = pstore_size;
151ad771a9cSHuibin Hong 
152ad771a9cSHuibin Hong 	rb->start++;
153ad771a9cSHuibin Hong }
154ad771a9cSHuibin Hong 
puts_to_ram(const char * str)155ad771a9cSHuibin Hong void puts_to_ram(const char *str)
156ad771a9cSHuibin Hong {
157ad771a9cSHuibin Hong 	while (*str) {
158ad771a9cSHuibin Hong 		putc_to_ram(*str++);
159ad771a9cSHuibin Hong 	}
160ad771a9cSHuibin Hong }
161