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