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