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