blob: 1d82ceff1e1a63844f768fadf76336b6b75a003a [file] [log] [blame]
Sheetal Tigadoliad0943e2019-12-18 19:44:43 +05301/*
2 * Copyright (c) 2017-2020, Broadcom
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <string.h>
8
9#include <arch_helpers.h>
10#include <common/bl_common.h>
11#include <common/debug.h>
12#include <drivers/delay_timer.h>
13
14#include <bcm_elog_ddr.h>
15#include <brcm_mhu.h>
16#include <brcm_scpi.h>
17#include <chimp.h>
18#include <cmn_plat_util.h>
19#include <ddr_init.h>
20#include <scp.h>
21#include <scp_cmd.h>
22#include <scp_utils.h>
23
24#include "m0_cfg.h"
25#include "m0_ipc.h"
26
27#ifdef BCM_ELOG
28static void prepare_elog(void)
29{
30#if (CLEAN_DDR && !defined(MMU_DISABLED))
31 /*
32 * Now DDR has been initialized. We want to copy all the logs in SRAM
33 * into DDR so we will have much more space to store the logs in the
34 * next boot stage
35 */
36 bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE,
37 MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE)
38 );
39
40 /*
41 * We are almost at the end of BL2, and we can stop log here so we do
42 * not need to add 'bcm_elog_exit' to the standard BL2 code. The
43 * benefit of capturing BL2 logs after this is very minimal in a
44 * production system.
45 */
46 bcm_elog_exit();
47#endif
48
49 /*
50 * Notify CRMU that now it should pull logs from DDR instead of from
51 * FS4 SRAM.
52 */
53 SCP_WRITE_CFG(flash_log.can_use_ddr, 1);
54}
55#endif
56
57bool is_crmu_alive(void)
58{
59 return (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0, SCP_CMD_DEFAULT_TIMEOUT_US)
60 == 0);
61}
62
63bool bcm_scp_issue_sys_reset(void)
64{
65 return (scp_send_cmd(MCU_IPC_MCU_CMD_L1_RESET, 0,
66 SCP_CMD_DEFAULT_TIMEOUT_US));
67}
68
69/*
70 * Note that this is just a temporary implementation until
71 * channels are introduced
72 */
73
74int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
75{
76 int scp_patch_activated, scp_patch_version;
77#ifndef EMULATION_SETUP
78 uint8_t active_ch_bitmap, i;
79#endif
80 uint32_t reset_state = 0;
81 uint32_t mcu_ap_init_param = 0;
82
83 /*
84 * First check if SCP patch has already been loaded
85 * Send NOP command and see if there is a valid response
86 */
87 scp_patch_activated =
88 (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0,
89 SCP_CMD_DEFAULT_TIMEOUT_US) == 0);
90 if (scp_patch_activated) {
91 INFO("SCP Patch is already active.\n");
92
93 reset_state = SCP_READ_CFG(board_cfg.reset_state);
94 mcu_ap_init_param = SCP_READ_CFG(board_cfg.mcu_init_param);
95
96 /* Clear reset state, it's been already read */
97 SCP_WRITE_CFG(board_cfg.reset_state, 0);
98
99 if (mcu_ap_init_param & MCU_PATCH_LOADED_BY_NITRO) {
100 /*
101 * Reset "MCU_PATCH_LOADED_BY_NITRO" flag, but
102 * Preserve any other flags we don't deal with here
103 */
104 INFO("AP booted by Nitro\n");
105 SCP_WRITE_CFG(
106 board_cfg.mcu_init_param,
107 mcu_ap_init_param &
108 ~MCU_PATCH_LOADED_BY_NITRO
109 );
110 }
111 } else {
112 /*
113 * MCU Patch not loaded, so load it.
114 * MCU patch stamps critical points in REG9 (debug test-point)
115 * Display its last content here. This helps to locate
116 * where crash occurred if a CRMU watchdog kicked in.
117 */
118 int ret;
119
120 INFO("MCU Patch Point: 0x%x\n",
121 mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9));
122
123 ret = download_scp_patch((void *)scp_bl2_image_info->image_base,
124 scp_bl2_image_info->image_size);
125 if (ret != 0)
126 return ret;
127
128 VERBOSE("SCP Patch loaded OK.\n");
129
130 ret = scp_send_cmd(MCU_IPC_MCU_CMD_INIT,
131 MCU_PATCH_LOADED_BY_AP,
132 SCP_CMD_SCP_BOOT_TIMEOUT_US);
133 if (ret) {
134 ERROR("SCP Patch could not initialize; error %d\n",
135 ret);
136 return ret;
137 }
138
139 INFO("SCP Patch successfully initialized.\n");
140 }
141
142 scp_patch_version = scp_send_cmd(MCU_IPC_MCU_CMD_GET_FW_VERSION, 0,
143 SCP_CMD_DEFAULT_TIMEOUT_US);
144 INFO("SCP Patch version :0x%x\n", scp_patch_version);
145
146 /* Next block just reports current AVS voltages (if applicable) */
147 {
148 uint16_t vcore_mv, ihost03_mv, ihost12_mv;
149
150 vcore_mv = SCP_READ_CFG16(vcore.millivolts) +
151 SCP_READ_CFG8(vcore.avs_cfg.additive_margin);
152 ihost03_mv = SCP_READ_CFG16(ihost03.millivolts) +
153 SCP_READ_CFG8(ihost03.avs_cfg.additive_margin);
154 ihost12_mv = SCP_READ_CFG16(ihost12.millivolts) +
155 SCP_READ_CFG8(ihost12.avs_cfg.additive_margin);
156
157 if (vcore_mv || ihost03_mv || ihost12_mv) {
158 INFO("AVS voltages from cfg (including margin)\n");
159 if (vcore_mv > 0)
160 INFO("%s\tVCORE: %dmv\n",
161 SCP_READ_CFG8(vcore.avs_cfg.avs_set) ?
162 "*" : "n/a", vcore_mv);
163 if (ihost03_mv > 0)
164 INFO("%s\tIHOST03: %dmv\n",
165 SCP_READ_CFG8(ihost03.avs_cfg.avs_set) ?
166 "*" : "n/a", ihost03_mv);
167 if (ihost12_mv > 0)
168 INFO("%s\tIHOST12: %dmv\n",
169 SCP_READ_CFG8(ihost12.avs_cfg.avs_set) ?
170 "*" : "n/a", ihost12_mv);
171 } else {
172 INFO("AVS settings not applicable\n");
173 }
174 }
175
176#if (CLEAN_DDR && !defined(MMU_DISABLED) && !defined(EMULATION_SETUP))
177 /* This will clean the DDR and enable ECC if set */
178 check_ddr_clean();
179#endif
180
181#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR)
182 elog_init_ddr_log();
183#endif
184
185#ifdef BCM_ELOG
186 /* Prepare ELOG to use DDR */
187 prepare_elog();
188#endif
189
190#ifndef EMULATION_SETUP
191 /* Ask ddr_init to save obtained DDR information into DDR */
192 ddr_info_save();
193#endif
194
195 /*
196 * Configure TMON DDR address.
197 * This cfg is common for all cases
198 */
199 SCP_WRITE_CFG(tmon_cfg.ddr_desc, TMON_SHARED_DDR_ADDRESS);
200
201 if (reset_state == SOFT_RESET_L3 && !mcu_ap_init_param) {
202 INFO("SCP configuration after L3 RESET done.\n");
203 return 0;
204 }
205
206 if (bcm_chimp_is_nic_mode())
207 /* Configure AP WDT to not reset the NIC interface */
208 SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3);
209
210#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR)
211 /* When AP WDog triggers perform L3 reset if DDR err logging enabled */
212 SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3);
213#endif
214
215#ifndef EMULATION_SETUP
216
217#ifdef DDR_SCRUB_ENA
218 ddr_scrub_enable();
219#endif
220 /* Fill the Active channel information */
221 active_ch_bitmap = get_active_ddr_channel();
222 for (i = 0; i < MAX_NR_DDR_CH; i++)
223 SCP_WRITE_CFG(ddr_cfg.ddr_cfg[i],
224 (active_ch_bitmap & BIT(i)) ? 1 : 0);
225#endif
226 return 0;
227}