123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- /*
- * Copyright 2019-2020 Broadcom.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <arch_helpers.h>
- #include <common/debug.h>
- #include <ddr_init.h>
- #include <scp_cmd.h>
- #include <scp_utils.h>
- #include <platform_def.h>
- #include "bcm_elog_ddr.h"
- #include "m0_cfg.h"
- #include "m0_ipc.h"
- void elog_init_ddr_log(void)
- {
- struct elog_setup setup = {0};
- struct elog_global_header global;
- struct elog_meta_record rec;
- unsigned int rec_idx = 0;
- uint32_t log_offset;
- uintptr_t metadata;
- char *rec_desc[ELOG_SUPPORTED_REC_CNT] = {"SYSRESET", "THERMAL",
- "DDR_ECC", "APBOOTLG",
- "IDM"};
- /*
- * If this is warm boot, return immediately.
- * We expect metadata to be initialized already
- */
- if (is_warmboot()) {
- WARN("Warmboot detected, skip ELOG metadata initialization\n");
- return;
- }
- memset(&global, 0, sizeof(global));
- global.sector_size = ELOG_SECTOR_SIZE;
- global.signature = ELOG_GLOBAL_META_HDR_SIG;
- global.rec_count = ELOG_SUPPORTED_REC_CNT;
- /* Start of logging area in DDR memory */
- log_offset = ELOG_STORE_OFFSET;
- /* Shift to the first RECORD header */
- log_offset += 2 * global.sector_size;
- /* Temporary place to hold metadata */
- metadata = TMP_ELOG_METADATA_BASE;
- memcpy((void *)metadata, &global, sizeof(global));
- metadata += sizeof(global);
- while (rec_idx < global.rec_count) {
- memset(&rec, 0, sizeof(rec));
- rec.type = rec_idx;
- if (rec_idx == ELOG_REC_UART_LOG) {
- rec.format = ELOG_REC_FMT_ASCII;
- rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR;
- rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_FS4_SCRATCH;
- rec.src_mem_addr = BCM_ELOG_BL31_BASE;
- rec.alt_src_mem_addr = BCM_ELOG_BL2_BASE;
- rec.rec_size = ELOG_APBOOTLG_REC_SIZE;
- } else if (rec_idx == ELOG_REC_IDM_LOG) {
- rec.type = IDM_ELOG_REC_TYPE;
- rec.format = ELOG_REC_FMT_CUSTOM;
- rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR;
- rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
- rec.src_mem_addr = ELOG_IDM_SRC_MEM_ADDR;
- rec.alt_src_mem_addr = 0x0;
- rec.rec_size = ELOG_DEFAULT_REC_SIZE;
- } else {
- rec.format = ELOG_REC_FMT_CUSTOM;
- rec.src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
- rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
- rec.src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
- rec.alt_src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
- rec.rec_size = ELOG_DEFAULT_REC_SIZE;
- }
- rec.nvm_type = LOG_MEDIA_DDR;
- rec.sector_size = ELOG_SECTOR_SIZE;
- rec.rec_addr = (uint64_t)log_offset;
- log_offset += rec.rec_size;
- /* Sanity checks */
- if (rec.type > ELOG_MAX_REC_COUNT ||
- rec.format > ELOG_MAX_REC_FORMAT ||
- (rec.nvm_type > ELOG_MAX_NVM_TYPE &&
- rec.nvm_type != ELOG_NVM_DEFAULT) ||
- !rec.rec_size ||
- !rec.sector_size ||
- rec_idx >= ELOG_SUPPORTED_REC_CNT) {
- ERROR("Invalid ELOG record(%u) detected\n", rec_idx);
- return;
- }
- memset(rec.rec_desc, ' ', sizeof(rec.rec_desc));
- memcpy(rec.rec_desc, rec_desc[rec_idx],
- strlen(rec_desc[rec_idx]));
- memcpy((void *)metadata, &rec, sizeof(rec));
- metadata += sizeof(rec);
- rec_idx++;
- }
- setup.params[0] = TMP_ELOG_METADATA_BASE;
- setup.params[1] = (sizeof(global) + global.rec_count * sizeof(rec));
- setup.cmd = ELOG_SETUP_CMD_WRITE_META;
- flush_dcache_range((uintptr_t)&setup, sizeof(struct elog_setup));
- flush_dcache_range((uintptr_t)setup.params[0], setup.params[1]);
- /* initialize DDR Logging METADATA if this is NOT warmboot */
- if (!is_warmboot()) {
- if (scp_send_cmd(MCU_IPC_MCU_CMD_ELOG_SETUP,
- (uint32_t)(uintptr_t)(&setup),
- SCP_CMD_DEFAULT_TIMEOUT_US)) {
- ERROR("scp_send_cmd: timeout/error for elog setup\n");
- return;
- }
- }
- NOTICE("MCU Error logging initialized\n");
- }
|