xref: /rk3399_ARM-atf/plat/brcm/board/common/bcm_elog_ddr.c (revision 926cd70a0cc3a0cbf209a87765a8dc0b869798e3)
1*f29d1e0cSSheetal Tigadoli /*
2*f29d1e0cSSheetal Tigadoli  * Copyright 2019-2020 Broadcom.
3*f29d1e0cSSheetal Tigadoli  *
4*f29d1e0cSSheetal Tigadoli  * SPDX-License-Identifier: BSD-3-Clause
5*f29d1e0cSSheetal Tigadoli  */
6*f29d1e0cSSheetal Tigadoli 
7*f29d1e0cSSheetal Tigadoli #include <arch_helpers.h>
8*f29d1e0cSSheetal Tigadoli #include <common/debug.h>
9*f29d1e0cSSheetal Tigadoli 
10*f29d1e0cSSheetal Tigadoli #include <ddr_init.h>
11*f29d1e0cSSheetal Tigadoli #include <scp_cmd.h>
12*f29d1e0cSSheetal Tigadoli #include <scp_utils.h>
13*f29d1e0cSSheetal Tigadoli #include <platform_def.h>
14*f29d1e0cSSheetal Tigadoli 
15*f29d1e0cSSheetal Tigadoli #include "bcm_elog_ddr.h"
16*f29d1e0cSSheetal Tigadoli #include "m0_cfg.h"
17*f29d1e0cSSheetal Tigadoli #include "m0_ipc.h"
18*f29d1e0cSSheetal Tigadoli 
elog_init_ddr_log(void)19*f29d1e0cSSheetal Tigadoli void elog_init_ddr_log(void)
20*f29d1e0cSSheetal Tigadoli {
21*f29d1e0cSSheetal Tigadoli 	struct elog_setup setup = {0};
22*f29d1e0cSSheetal Tigadoli 	struct elog_global_header global;
23*f29d1e0cSSheetal Tigadoli 	struct elog_meta_record rec;
24*f29d1e0cSSheetal Tigadoli 	unsigned int rec_idx = 0;
25*f29d1e0cSSheetal Tigadoli 	uint32_t log_offset;
26*f29d1e0cSSheetal Tigadoli 	uintptr_t metadata;
27*f29d1e0cSSheetal Tigadoli 	char *rec_desc[ELOG_SUPPORTED_REC_CNT] = {"SYSRESET", "THERMAL",
28*f29d1e0cSSheetal Tigadoli 						  "DDR_ECC", "APBOOTLG",
29*f29d1e0cSSheetal Tigadoli 						  "IDM"};
30*f29d1e0cSSheetal Tigadoli 
31*f29d1e0cSSheetal Tigadoli 	/*
32*f29d1e0cSSheetal Tigadoli 	 * If this is warm boot, return immediately.
33*f29d1e0cSSheetal Tigadoli 	 * We expect metadata to be initialized already
34*f29d1e0cSSheetal Tigadoli 	 */
35*f29d1e0cSSheetal Tigadoli 	if (is_warmboot()) {
36*f29d1e0cSSheetal Tigadoli 		WARN("Warmboot detected, skip ELOG metadata initialization\n");
37*f29d1e0cSSheetal Tigadoli 		return;
38*f29d1e0cSSheetal Tigadoli 	}
39*f29d1e0cSSheetal Tigadoli 
40*f29d1e0cSSheetal Tigadoli 	memset(&global, 0, sizeof(global));
41*f29d1e0cSSheetal Tigadoli 
42*f29d1e0cSSheetal Tigadoli 	global.sector_size = ELOG_SECTOR_SIZE;
43*f29d1e0cSSheetal Tigadoli 	global.signature = ELOG_GLOBAL_META_HDR_SIG;
44*f29d1e0cSSheetal Tigadoli 	global.rec_count = ELOG_SUPPORTED_REC_CNT;
45*f29d1e0cSSheetal Tigadoli 
46*f29d1e0cSSheetal Tigadoli 	/* Start of logging area in DDR memory */
47*f29d1e0cSSheetal Tigadoli 	log_offset = ELOG_STORE_OFFSET;
48*f29d1e0cSSheetal Tigadoli 
49*f29d1e0cSSheetal Tigadoli 	/* Shift to the first RECORD header */
50*f29d1e0cSSheetal Tigadoli 	log_offset += 2 * global.sector_size;
51*f29d1e0cSSheetal Tigadoli 
52*f29d1e0cSSheetal Tigadoli 	/* Temporary place to hold metadata */
53*f29d1e0cSSheetal Tigadoli 	metadata = TMP_ELOG_METADATA_BASE;
54*f29d1e0cSSheetal Tigadoli 
55*f29d1e0cSSheetal Tigadoli 	memcpy((void *)metadata, &global, sizeof(global));
56*f29d1e0cSSheetal Tigadoli 	metadata += sizeof(global);
57*f29d1e0cSSheetal Tigadoli 
58*f29d1e0cSSheetal Tigadoli 	while (rec_idx < global.rec_count) {
59*f29d1e0cSSheetal Tigadoli 		memset(&rec, 0, sizeof(rec));
60*f29d1e0cSSheetal Tigadoli 
61*f29d1e0cSSheetal Tigadoli 		rec.type = rec_idx;
62*f29d1e0cSSheetal Tigadoli 		if (rec_idx == ELOG_REC_UART_LOG) {
63*f29d1e0cSSheetal Tigadoli 			rec.format =  ELOG_REC_FMT_ASCII;
64*f29d1e0cSSheetal Tigadoli 			rec.src_mem_type =  ELOG_SRC_MEM_TYPE_DDR;
65*f29d1e0cSSheetal Tigadoli 			rec.alt_src_mem_type =  ELOG_SRC_MEM_TYPE_FS4_SCRATCH;
66*f29d1e0cSSheetal Tigadoli 			rec.src_mem_addr =  BCM_ELOG_BL31_BASE;
67*f29d1e0cSSheetal Tigadoli 			rec.alt_src_mem_addr =  BCM_ELOG_BL2_BASE;
68*f29d1e0cSSheetal Tigadoli 			rec.rec_size =  ELOG_APBOOTLG_REC_SIZE;
69*f29d1e0cSSheetal Tigadoli 		} else if (rec_idx == ELOG_REC_IDM_LOG) {
70*f29d1e0cSSheetal Tigadoli 			rec.type = IDM_ELOG_REC_TYPE;
71*f29d1e0cSSheetal Tigadoli 			rec.format = ELOG_REC_FMT_CUSTOM;
72*f29d1e0cSSheetal Tigadoli 			rec.src_mem_type =  ELOG_SRC_MEM_TYPE_DDR;
73*f29d1e0cSSheetal Tigadoli 			rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
74*f29d1e0cSSheetal Tigadoli 			rec.src_mem_addr =  ELOG_IDM_SRC_MEM_ADDR;
75*f29d1e0cSSheetal Tigadoli 			rec.alt_src_mem_addr =  0x0;
76*f29d1e0cSSheetal Tigadoli 			rec.rec_size =  ELOG_DEFAULT_REC_SIZE;
77*f29d1e0cSSheetal Tigadoli 		} else {
78*f29d1e0cSSheetal Tigadoli 			rec.format = ELOG_REC_FMT_CUSTOM;
79*f29d1e0cSSheetal Tigadoli 			rec.src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
80*f29d1e0cSSheetal Tigadoli 			rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
81*f29d1e0cSSheetal Tigadoli 			rec.src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
82*f29d1e0cSSheetal Tigadoli 			rec.alt_src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
83*f29d1e0cSSheetal Tigadoli 			rec.rec_size = ELOG_DEFAULT_REC_SIZE;
84*f29d1e0cSSheetal Tigadoli 		}
85*f29d1e0cSSheetal Tigadoli 
86*f29d1e0cSSheetal Tigadoli 		rec.nvm_type = LOG_MEDIA_DDR;
87*f29d1e0cSSheetal Tigadoli 		rec.sector_size = ELOG_SECTOR_SIZE;
88*f29d1e0cSSheetal Tigadoli 
89*f29d1e0cSSheetal Tigadoli 		rec.rec_addr = (uint64_t)log_offset;
90*f29d1e0cSSheetal Tigadoli 		log_offset += rec.rec_size;
91*f29d1e0cSSheetal Tigadoli 
92*f29d1e0cSSheetal Tigadoli 		/* Sanity checks */
93*f29d1e0cSSheetal Tigadoli 		if (rec.type > ELOG_MAX_REC_COUNT ||
94*f29d1e0cSSheetal Tigadoli 		    rec.format > ELOG_MAX_REC_FORMAT ||
95*f29d1e0cSSheetal Tigadoli 		    (rec.nvm_type > ELOG_MAX_NVM_TYPE &&
96*f29d1e0cSSheetal Tigadoli 		     rec.nvm_type != ELOG_NVM_DEFAULT) ||
97*f29d1e0cSSheetal Tigadoli 		    !rec.rec_size ||
98*f29d1e0cSSheetal Tigadoli 		    !rec.sector_size ||
99*f29d1e0cSSheetal Tigadoli 		    rec_idx >= ELOG_SUPPORTED_REC_CNT) {
100*f29d1e0cSSheetal Tigadoli 			ERROR("Invalid ELOG record(%u) detected\n", rec_idx);
101*f29d1e0cSSheetal Tigadoli 			return;
102*f29d1e0cSSheetal Tigadoli 		}
103*f29d1e0cSSheetal Tigadoli 
104*f29d1e0cSSheetal Tigadoli 		memset(rec.rec_desc, ' ', sizeof(rec.rec_desc));
105*f29d1e0cSSheetal Tigadoli 
106*f29d1e0cSSheetal Tigadoli 		memcpy(rec.rec_desc, rec_desc[rec_idx],
107*f29d1e0cSSheetal Tigadoli 		       strlen(rec_desc[rec_idx]));
108*f29d1e0cSSheetal Tigadoli 
109*f29d1e0cSSheetal Tigadoli 		memcpy((void *)metadata, &rec, sizeof(rec));
110*f29d1e0cSSheetal Tigadoli 		metadata += sizeof(rec);
111*f29d1e0cSSheetal Tigadoli 
112*f29d1e0cSSheetal Tigadoli 		rec_idx++;
113*f29d1e0cSSheetal Tigadoli 	}
114*f29d1e0cSSheetal Tigadoli 
115*f29d1e0cSSheetal Tigadoli 	setup.params[0] = TMP_ELOG_METADATA_BASE;
116*f29d1e0cSSheetal Tigadoli 	setup.params[1] = (sizeof(global) + global.rec_count * sizeof(rec));
117*f29d1e0cSSheetal Tigadoli 	setup.cmd = ELOG_SETUP_CMD_WRITE_META;
118*f29d1e0cSSheetal Tigadoli 
119*f29d1e0cSSheetal Tigadoli 	flush_dcache_range((uintptr_t)&setup, sizeof(struct elog_setup));
120*f29d1e0cSSheetal Tigadoli 	flush_dcache_range((uintptr_t)setup.params[0], setup.params[1]);
121*f29d1e0cSSheetal Tigadoli 
122*f29d1e0cSSheetal Tigadoli 	/* initialize DDR Logging METADATA if this is NOT warmboot */
123*f29d1e0cSSheetal Tigadoli 	if (!is_warmboot()) {
124*f29d1e0cSSheetal Tigadoli 		if (scp_send_cmd(MCU_IPC_MCU_CMD_ELOG_SETUP,
125*f29d1e0cSSheetal Tigadoli 				 (uint32_t)(uintptr_t)(&setup),
126*f29d1e0cSSheetal Tigadoli 				 SCP_CMD_DEFAULT_TIMEOUT_US)) {
127*f29d1e0cSSheetal Tigadoli 			ERROR("scp_send_cmd: timeout/error for elog setup\n");
128*f29d1e0cSSheetal Tigadoli 			return;
129*f29d1e0cSSheetal Tigadoli 		}
130*f29d1e0cSSheetal Tigadoli 	}
131*f29d1e0cSSheetal Tigadoli 
132*f29d1e0cSSheetal Tigadoli 	NOTICE("MCU Error logging initialized\n");
133*f29d1e0cSSheetal Tigadoli }
134