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 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