bcm_elog_ddr.c 3.6 KB

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