blob: a78d927d761849e66e932398a1514f6ed34ade03 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
dongqing.li3d3670e2023-10-17 11:15:45 +08007#include <asm/amlogic/arch/bl31_apis.h>
8#include <asm/amlogic/arch/secure_apb.h>
9#include <amlogic/ramdump.h>
10#include <amlogic/emmc_partitions.h>
Bo Lv72d0e902023-01-02 14:27:34 +000011#include <usb.h>
dongqing.li3d3670e2023-10-17 11:15:45 +080012#include <asm/amlogic/arch/regs.h>
13#include <asm/global_data.h>
14#include <syscon.h>
Bo Lv72d0e902023-01-02 14:27:34 +000015
16#define DEBUG_RAMDUMP 0
17#define AMLOGIC_KERNEL_PANIC 0x0c
18#define AMLOGIC_WATCHDOG_REBOOT 0x0d
Zhongfu Luobef22a72023-12-07 16:30:21 +080019#ifdef CONFIG_USB_STORAGE
dongqing.li3d3670e2023-10-17 11:15:45 +080020static void wait_usb_dev(void);
Zhongfu Luobef22a72023-12-07 16:30:21 +080021#endif
dongqing.li3d3670e2023-10-17 11:15:45 +080022#undef CONFIG_DUMP_COMPRESS_HEAD
Bo Lv72d0e902023-01-02 14:27:34 +000023#ifdef CONFIG_DUMP_COMPRESS_HEAD
24static void dump_info(unsigned int addr, unsigned int size, const char *info)
25{
26 int i = 0;
27
28 printf("\nDUMP %s 0X%08x :", info, addr);
29 for (i = 0; i < size; i += 4) {
30 if (0 == (i % 32))
31 printf("\n[0x%08x] ", addr + i);
32 printf("%08x ", readl(addr + i));
33 }
34 printf("\n\n");
35}
dongqing.li3d3670e2023-10-17 11:15:45 +080036
37int parse_dump_file_v2(const char *base, unsigned long size)
38{
39 struct ram_compress_file_header_v2 *fhead;
40 struct ram_compress_section_header_v2 csh;
41 struct section_info *seg_tbl;
42 unsigned long seg_offset;
43 unsigned int idx;
44 int cnt = 0, csh_size = 0;
45
46 // check ramdump version >= v2.0
47 if ((!strncmp(base, COMPRESS_TAG_HEAD, COMPRESS_TAG_SIZE - 1)) &&
48 (!strncmp(base, COMPRESS_TAG_BL3Z, COMPRESS_TAG_SIZE - 1))) {
49 printf("# Check the crash file head error, exit.\n");
50 return -1;
51 }
52
53 // dump crash section head
54 fhead = (struct ram_compress_file_header_v2 *)base;
55 printf("# total number of segment is %d\n", fhead->section_count);
56 if (fhead->section_count > 10) {
57 printf("# crash file head error. exit.\n");
58 return -1;
59 }
60
61 seg_tbl = malloc(sizeof(struct section_info) * fhead->section_count);
62 printf("# total compress file size is 0x%08lx\n", fhead->file_size);
63 csh_size = sizeof(struct ram_compress_section_header_v2);
64 seg_offset = (unsigned long)fhead + sizeof(struct ram_compress_file_header_v2);
65 printf("# crash file fhead offset is 0x%08lx\n", seg_offset);
66
67 for (cnt = 0; cnt < fhead->section_count; cnt++) {
68 memset(&csh, 0, sizeof(csh));
69 if (seg_offset > ((unsigned long)base + size))
70 continue;
71
72 memcpy((void *)&csh, (char *)seg_offset, sizeof(csh));
73 if (csh.section_index > fhead->section_count) {
74 printf("csh.section_index(%d) > fhead->section_count(%d), error, exit.\n",
75 csh.section_index, fhead->section_count);
76 return -1;
77 }
78
79 if (csh.compress_type == RAM_COMPRESS_ERROR ||
80 csh.compress_type > RAM_COMPRESS_MAX)
81 continue;
82
83 idx = csh.section_index - 1;
84 seg_tbl[idx].offset = seg_offset + sizeof(csh);
85 seg_tbl[idx].type = csh.compress_type;
86 seg_tbl[idx].raw_size = csh.raw_size;
87 seg_tbl[idx].zip_size = csh.zip_size;
88 seg_tbl[idx].val = csh.set_value;
89 seg_offset += csh.zip_size;
90 }
91
92 // dump section table
93 printf("\n-----------------------------------------------------------\n");
94 printf("idx offset type orig size zip size val\n");
95 printf("-----------------------------------------------------------\n");
96 for (cnt = 0; cnt < fhead->section_count; cnt++) {
97 if (seg_tbl[cnt].type == RAM_COMPRESS_ERROR ||
98 seg_tbl[cnt].type > RAM_COMPRESS_MAX)
99 continue;
100 printf(" %2d, 0x%08lx, %2u, 0x%08lx, 0x%08lx, 0x%02x\n",
101 cnt + 1, seg_tbl[cnt].offset,
102 seg_tbl[cnt].type, seg_tbl[cnt].raw_size,
103 seg_tbl[cnt].zip_size, seg_tbl[cnt].val);
104 }
105 printf("-----------------------------------------------------------\n");
106
107 // printf section table
108 for (cnt = 0; cnt < fhead->section_count; cnt++) {
109 if (seg_tbl[cnt].type == RAM_COMPRESS_ERROR ||
110 seg_tbl[cnt].type > RAM_COMPRESS_MAX)
111 continue;
112 dump_info((unsigned int)seg_tbl[cnt].offset - csh_size, csh_size, "crash section head");
113 }
114
115 return 0;
116}
Bo Lv72d0e902023-01-02 14:27:34 +0000117#endif
118
119unsigned long ramdump_base = 0;
120unsigned long ramdump_size = 0;
121unsigned int get_reboot_mode(void)
122{
123 uint32_t reboot_mode_val = ((readl(REG_MDUMP_REBOOT_MODE) >> 12) & 0xf);
124 return reboot_mode_val;
125}
126
127void ramdump_init(void)
128{
dongqing.li3d3670e2023-10-17 11:15:45 +0800129 unsigned int data, reboot_mode;
130
Bo Lv72d0e902023-01-02 14:27:34 +0000131 printf("%s, base reg:0x%08x, size reg:0x%08x\n", __func__,
132 REG_MDUMP_COMPRESS_BASE, REG_MDUMP_COMPRESS_SIZE);
133 ramdump_base = readl(REG_MDUMP_COMPRESS_BASE);
134 ramdump_size = readl(REG_MDUMP_COMPRESS_SIZE);
dongqing.li3d3670e2023-10-17 11:15:45 +0800135#if defined(CONFIG_MDUMP_COMPRESS) && defined(CONFIG_COMPRESSED_ADDR)
136 printf("%s, ramdump_base(0x%08lx) is overwritten as 0x%08x\n",
137 __func__, ramdump_base, CONFIG_COMPRESSED_ADDR);
138 ramdump_base = (unsigned long)CONFIG_COMPRESSED_ADDR;
139#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000140 if (ramdump_base & 0x80) {
141 /* 0x80: The flag indicates that the addr exceeds 4G. */
142 /* real size = size[31:0] + addr[6:0]<<32 */
143 ramdump_size += (ramdump_base & 0x7f) << 32;
144 /* real addr = addr[31:8] << 8 */
145 ramdump_base = (ramdump_base & 0xffffff00) << 8;
146 }
147
dongqing.li3d3670e2023-10-17 11:15:45 +0800148 data = readl(REG_MDUMP_CPUBOOT_STATUS);
149 writel(data & ~RAMDUMP_STICKY_DATA_MASK, REG_MDUMP_CPUBOOT_STATUS);
Bo Lv72d0e902023-01-02 14:27:34 +0000150 printf("%s, add:%lx, size:%lx\n", __func__, ramdump_base, ramdump_size);
151
152#ifdef CONFIG_DUMP_COMPRESS_HEAD
153 dump_info((unsigned int)ramdump_base, 0x80, "bl33 check COMPRESS DATA 1");
154#endif
dongqing.li3d3670e2023-10-17 11:15:45 +0800155
156 reboot_mode = get_reboot_mode();
157 if ((reboot_mode == AMLOGIC_WATCHDOG_REBOOT ||
158 reboot_mode == AMLOGIC_KERNEL_PANIC)) {
159 if (ramdump_base && ramdump_size) {
160#ifdef CONFIG_DUMP_COMPRESS_HEAD
161 parse_dump_file_v2((char *)ramdump_base, ramdump_size);
162#endif
163 ramdump_save_compress_data();
164 }
165 }
Bo Lv72d0e902023-01-02 14:27:34 +0000166}
167
Zhongfu Luobef22a72023-12-07 16:30:21 +0800168#ifdef CONFIG_USB_STORAGE
Bo Lv72d0e902023-01-02 14:27:34 +0000169static void wait_usb_dev(void)
170{
171 int print_cnt = 0, ret;
172
173 while (1) {
174 run_command("usb start", 1);
175 mdelay(2000);
176 run_command("usb reset", 1);
177 ret = usb_stor_scan(1);
178 if (ret) {
dongqing.lia972f8b2024-02-06 11:27:01 +0800179 if (!(print_cnt & 0x1f)) {
Bo Lv72d0e902023-01-02 14:27:34 +0000180 print_cnt++;
181 printf("ramdump: can't find usb device, please insert Udisk.\n\n");
182 }
dongqing.lia972f8b2024-02-06 11:27:01 +0800183 mdelay(15000);
Bo Lv72d0e902023-01-02 14:27:34 +0000184 continue;
185 } else {
186 run_command("usb dev", 1);
187 break;
188 }
189 }
190}
Zhongfu Luobef22a72023-12-07 16:30:21 +0800191#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000192/*
193 * NOTE: this is a default implementation for writing compressed ramdump data
194 * to /data/ partition for Android platform. You can read out dumpfile in
195 * path /data/crashdump-1.bin when enter Android for crash analyze.
196 * by default, /data/ partition for android is EXT4 fs.
197 *
198 * TODO:
199 * If you are using different fs or OS on your platform, implement compress
200 * data save command for your fs and OS in your board.c with same function
201 * name "ramdump_save_compress_data".
202 */
203__weak int ramdump_save_compress_data(void)
204{
205 char cmd[128] = {0};
206 char *env;
207 int ret = 0;
208
dongqing.lia972f8b2024-02-06 11:27:01 +0800209 env = env_get("ramdump_enable");
210 if (!env || strcmp(env, "1") != 0)
211 return 0;
212
Bo Lv72d0e902023-01-02 14:27:34 +0000213 env = env_get("ramdump_location");
214 if (!env)
215 return 0;
216
217 printf("ramdump_location:%s\n", env);
218 /* currently we only support write to usb disk */
219 if (strncmp(env, "usb", 3)) {
220 printf("not supported location\n");
221 return 0;
222 }
Zhongfu Luobef22a72023-12-07 16:30:21 +0800223#ifdef CONFIG_USB_STORAGE
Bo Lv72d0e902023-01-02 14:27:34 +0000224 wait_usb_dev();
Zhongfu Luobef22a72023-12-07 16:30:21 +0800225#endif
dongqing.lia972f8b2024-02-06 11:27:01 +0800226 printf("\nPrepare to save crash file: base=0x%08lx, size=0x%08lx (%ld MB)\n",
227 ramdump_base, ramdump_size, ramdump_size / 1024 / 1024);
Bo Lv72d0e902023-01-02 14:27:34 +0000228 sprintf(cmd, "fatwrite usb 0 %lx crashdump-1.bin %lx\n",
229 ramdump_base, ramdump_size);
230 printf("CMD:%s\n", cmd);
dongqing.lia972f8b2024-02-06 11:27:01 +0800231#ifdef CONFIG_USB_STORAGE
232 printf("It may take about 3 minutes, please wait...\n");
Bo Lv72d0e902023-01-02 14:27:34 +0000233 ret = run_command(cmd, 0);
dongqing.li3d3670e2023-10-17 11:15:45 +0800234 if (ret != 0) {
235 printf("run fatwrite usb ERROR!\n");
236 return -1;
237 }
238 printf("run fatwrite usb OK!\n");
dongqing.lia972f8b2024-02-06 11:27:01 +0800239#else
240 printf("CONFIG_USB_STORAGE is not defined! Could it be in PRODUCT mode?\n");
241 printf("ERROR: The usb drv is not available!\n");
242#endif
243 printf("Rebooting in 5 seconds ...\n\n\n");
dongqing.li3d3670e2023-10-17 11:15:45 +0800244 mdelay(5000);
dongqing.lia972f8b2024-02-06 11:27:01 +0800245 run_command("reboot", 1);
246 return ret;
Bo Lv72d0e902023-01-02 14:27:34 +0000247}
248
249static void ramdump_env_setup(unsigned long addr, unsigned long size)
250{
251 unsigned int data[10] = {
252 0x8E9C929F, 0x9E9C9791,
253 0xD28C9191, 0x97949B8D,
254 0x888B92, 0xCEBB97,
255 0x938E9B90, 0x978D8D97,
256 0xC8009B8A, 0xB99CDB
257 };
dongqing.lia972f8b2024-02-06 11:27:01 +0800258 char *line, *o;
Bo Lv72d0e902023-01-02 14:27:34 +0000259 unsigned char *p;
260 int i;
261
262 p = (unsigned char *)data;
263 for (i = 0; i < 40; i++)
264 p[i] = ~(p[i] - 1);
265
266 /*
267 * TODO: Make sure address for fdt_high and initrd_high
268 * are suitable for all boards
269 *
270 * usually kernel load address is 0x010800000
271 * Make sure:
272 * (kernel image size + ramdisk size) <
273 * (initrd_high - 0x010800000)
274 * dts file size < (fdt_high - initrd_high)
275 */
dongqing.li3d3670e2023-10-17 11:15:45 +0800276 //env_set("initrd_high", "0x0BB00000");
277 //env_set("fdt_high", "0x0BE00000");
Bo Lv72d0e902023-01-02 14:27:34 +0000278 line = env_get("bootargs");
279 if (!line)
280 return;
281
282 i = strlen(line);
283 o = malloc(i + 128);
284 if (!o)
285 return;
286
287 memset(o, 0, i + 128);
dongqing.lia972f8b2024-02-06 11:27:01 +0800288 sprintf(o, "%s=%s ramdump=%lx,%lx %s\n",
289 (char *)data, (char *)(data + 6), addr, size, line);
Bo Lv72d0e902023-01-02 14:27:34 +0000290 env_set("bootargs", o);
dongqing.lia972f8b2024-02-06 11:27:01 +0800291 free(o);
292 line = NULL;
Bo Lv72d0e902023-01-02 14:27:34 +0000293
294#if DEBUG_RAMDUMP
295 run_command("printenv bootargs", 1);
dongqing.lia972f8b2024-02-06 11:27:01 +0800296 printf("\n");
Bo Lv72d0e902023-01-02 14:27:34 +0000297#endif
Bo Lv72d0e902023-01-02 14:27:34 +0000298}
299
dongqing.li3d3670e2023-10-17 11:15:45 +0800300static int overwrite_bl33z_rsvmem_info(unsigned long addr, unsigned long size)
301{
302 int address_cells = 0;
303 unsigned long align_size = PAGE_ALIGN(size);
304 char cmd[0x80];
305
306 address_cells = fdt_address_cells(gd->fdt_blob, 0);
307 if (address_cells < 1) {
308 printf("%s, bad #address-cells !\n", __func__);
309 return -1;
310 }
311 printf("%s, get fdt #address-cells = %d\n", __func__, address_cells);
312
313 memset(cmd, 0, sizeof(cmd));
314 if (address_cells == 2)
315 sprintf(cmd,
316 "fdt set /reserved-memory/ramdump_bl33z reg '<0x0 0x%08lx 0x0 0x%08lx>'",
317 addr, align_size);
318 else
319 sprintf(cmd, "fdt set /reserved-memory/ramdump_bl33z reg '<0x%08lx 0x%08lx>'",
320 addr, align_size);
321
322 printf("%s\n", cmd);
323 run_command(cmd, 0);
324
325 printf("fdt set /reserved-memory/ramdump_bl33z status okay\n");
326 run_command("fdt set /reserved-memory/ramdump_bl33z status okay", 0);
327
328 return 0;
329}
330
331static int reduce_dts_reserved_memory(void)
332{
333 int address_cells = 0;
334
335 address_cells = fdt_address_cells(gd->fdt_blob, 0);
336 if (address_cells < 1) {
337 printf("%s, bad #address-cells !\n", __func__);
338 return -1;
339 }
340 printf("%s, get fdt #address-cells = %d\n", __func__, address_cells);
341 if (address_cells == 2) {
342 printf("\nReduce dts reserved memory:\n");
343 printf(" * disabled logo_reserved\n");
344 run_command("fdt set /reserved-memory/linux,meson-fb reg '<0x0 0x0 0x0 0x0>'", 0);
345 printf(" * disabled vdin1_cma_reserved\n");
346 run_command("fdt set /reserved-memory/linux,vdin1_cma reg '<0x0 0x0 0x0 0x0>'", 0);
347 printf(" * disabled ion_cma_reserved\n");
348 run_command("fdt set /reserved-memory/linux,ion-dev size '<0 0>'", 0);
349 printf(" * disabled dsp_fw_reserved\n");
350 run_command("fdt set /reserved-memory/linux,dsp_fw size '<0 0>'", 0);
351 printf(" * disabled lcd_tcon_reserved\n");
352 run_command("fdt set /reserved-memory/linux,lcd_tcon reg '<0x0 0x0 0x0 0x0>'", 0);
353 printf(" * reduce codec_mm_cma_reserved\n");
354 run_command("fdt set /reserved-memory/linux,codec_mm_cma size '<0x0 0x5000000>'", 0);
355 printf(" * reduce ion_fb_reserved, display\n");
356 run_command("fdt set /reserved-memory/linux,ion-fb size '<0x0 0x1000000>'", 0);
357 } else {
358 printf("\nReduce dts reserved memory:\n");
359 printf(" * disabled logo_reserved\n");
360 run_command("fdt set /reserved-memory/linux,meson-fb reg '<0x0 0x0>'", 0);
361 printf(" * disabled vdin1_cma_reserved\n");
362 run_command("fdt set /reserved-memory/linux,vdin1_cma reg '<0x0 0x0>'", 0);
363 printf(" * disabled ion_cma_reserved\n");
364 run_command("fdt set /reserved-memory/linux,ion-dev size '<0>'", 0);
365 printf(" * disabled dsp_fw_reserved\n");
366 run_command("fdt set /reserved-memory/linux,dsp_fw size '<0>'", 0);
367 printf(" * disabled lcd_tcon_reserved\n");
368 run_command("fdt set /reserved-memory/linux,lcd_tcon reg '<0x0 0x0>'", 0);
369 printf(" * reduce codec_mm_cma_reserved\n");
370 run_command("fdt set /reserved-memory/linux,codec_mm_cma size '<0x5000000>'", 0);
371 printf(" * reduce ion_fb_reserved, display\n");
372 run_command("fdt set /reserved-memory/linux,ion-fb size '<0x1000000>'", 0);
373 }
374
375 //run_command("fdt print /reserved-memory", 0);
376 return 0;
377}
378
Bo Lv72d0e902023-01-02 14:27:34 +0000379void check_ramdump(void)
380{
381 unsigned long size = 0;
382 unsigned long addr = 0;
383 char *env;
384 int reboot_mode;
dongqing.li3d3670e2023-10-17 11:15:45 +0800385 char str[128] = "";
386 unsigned int ddr_scramble_reg = 0xfe02e030;
Bo Lv72d0e902023-01-02 14:27:34 +0000387
388 env = env_get("ramdump_enable");
389 printf("%s, ramdump_enable = %s\n", __func__, env);
390 if (env) {
391 if (!strcmp(env, "1")) {
392 reboot_mode = get_reboot_mode();
393 if ((reboot_mode == AMLOGIC_WATCHDOG_REBOOT ||
394 reboot_mode == AMLOGIC_KERNEL_PANIC)) {
395 addr = ramdump_base;
396 size = ramdump_size;
397 printf("%s, addr:%lx, size:%lx\n",
398 __func__, addr, size);
399 if (addr && size) {
400 ramdump_env_setup(addr, size);
401#ifdef CONFIG_DUMP_COMPRESS_HEAD
402 dump_info((unsigned int)ramdump_base, 0x80, "bl33 check COMPRESS DATA 2");
403#endif
dongqing.li3d3670e2023-10-17 11:15:45 +0800404 env = env_get("ramdump_location");
dongqing.lia972f8b2024-02-06 11:27:01 +0800405 if (!strncmp(env, "data", 4)) {
dongqing.li3d3670e2023-10-17 11:15:45 +0800406 printf("Crash file will save to Android /data.\n");
407 reduce_dts_reserved_memory();
408 overwrite_bl33z_rsvmem_info(addr, size);
409 env_set("initrd_high", "0x0BB00000");
410 env_set("fdt_high", "0x0BE00000");
411 }
412 } else {
413 ramdump_env_setup(0, 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000414 }
415 } else {
416 ramdump_env_setup(0, 0);
417 }
dongqing.li3d3670e2023-10-17 11:15:45 +0800418#ifndef CONFIG_MDUMP_COMPRESS
419 //ramdump bl33z
Bo Lv72d0e902023-01-02 14:27:34 +0000420 printf("%s, fdt: rsvmem ramdump_bl33z enable.\n", __func__);
421 run_command("fdt set /reserved-memory/ramdump_bl33z status okay", 0);
422#endif
dongqing.li3d3670e2023-10-17 11:15:45 +0800423 //ddr scramble
424 sprintf(str, "setenv initargs ${initargs} scramble_reg=0x%08x",
425 ddr_scramble_reg);
426 printf("set_scramble: %s\n", str);
427 run_command(str, 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000428 }
429 }
430}