1 /* 2 * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <libfdt.h> 10 11 #include <common/bl_common.h> 12 #include <common/debug.h> 13 #include <drivers/arm/css/css_mhu_doorbell.h> 14 #include <drivers/arm/css/scmi.h> 15 #include <drivers/generic_delay_timer.h> 16 #include <lib/fconf/fconf.h> 17 #include <lib/fconf/fconf_dyn_cfg_getter.h> 18 #include <plat/arm/common/plat_arm.h> 19 #include <plat/arm/css/common/css_pm.h> 20 #include <plat/common/platform.h> 21 22 #include <nrd_ras.h> 23 #include <nrd_variant.h> 24 25 nrd_platform_info_t nrd_plat_info; 26 27 static scmi_channel_plat_info_t sgi575_scmi_plat_info = { 28 .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, 29 .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, 30 .db_preserve_mask = 0xfffffffe, 31 .db_modify_mask = 0x1, 32 .ring_doorbell = &mhu_ring_doorbell, 33 }; 34 35 static scmi_channel_plat_info_t plat_rd_scmi_info[] = { 36 { 37 .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, 38 .db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0), 39 .db_preserve_mask = 0xfffffffe, 40 .db_modify_mask = 0x1, 41 .ring_doorbell = &mhuv2_ring_doorbell, 42 }, 43 #if (NRD_CHIP_COUNT > 1) 44 { 45 .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE + 46 NRD_REMOTE_CHIP_MEM_OFFSET(1), 47 .db_reg_addr = PLAT_CSS_MHU_BASE 48 + NRD_REMOTE_CHIP_MEM_OFFSET(1) + SENDER_REG_SET(0), 49 .db_preserve_mask = 0xfffffffe, 50 .db_modify_mask = 0x1, 51 .ring_doorbell = &mhuv2_ring_doorbell, 52 }, 53 #endif 54 #if (NRD_CHIP_COUNT > 2) 55 { 56 .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE + 57 NRD_REMOTE_CHIP_MEM_OFFSET(2), 58 .db_reg_addr = PLAT_CSS_MHU_BASE + 59 NRD_REMOTE_CHIP_MEM_OFFSET(2) + SENDER_REG_SET(0), 60 .db_preserve_mask = 0xfffffffe, 61 .db_modify_mask = 0x1, 62 .ring_doorbell = &mhuv2_ring_doorbell, 63 }, 64 #endif 65 #if (NRD_CHIP_COUNT > 3) 66 { 67 .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE + 68 NRD_REMOTE_CHIP_MEM_OFFSET(3), 69 .db_reg_addr = PLAT_CSS_MHU_BASE + 70 NRD_REMOTE_CHIP_MEM_OFFSET(3) + SENDER_REG_SET(0), 71 .db_preserve_mask = 0xfffffffe, 72 .db_modify_mask = 0x1, 73 .ring_doorbell = &mhuv2_ring_doorbell, 74 }, 75 #endif 76 }; 77 78 static scmi_channel_plat_info_t plat3_rd_scmi_info[] = { 79 { 80 .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE, 81 .db_reg_addr = PLAT_CSS_MHU_BASE + MHU_V3_SENDER_REG_SET(0), 82 .db_preserve_mask = 0xfffffffe, 83 .db_modify_mask = 0x1, 84 .ring_doorbell = &mhu_ring_doorbell, 85 }, 86 #if (NRD_CHIP_COUNT > 1) 87 { 88 .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE + 89 NRD_REMOTE_CHIP_MEM_OFFSET(1), 90 .db_reg_addr = PLAT_CSS_MHU_BASE + 91 NRD_REMOTE_CHIP_MEM_OFFSET(1) + 92 MHU_V3_SENDER_REG_SET(0), 93 .db_preserve_mask = 0xfffffffe, 94 .db_modify_mask = 0x1, 95 .ring_doorbell = &mhu_ring_doorbell, 96 }, 97 #endif 98 #if (NRD_CHIP_COUNT > 2) 99 { 100 .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE + 101 NRD_REMOTE_CHIP_MEM_OFFSET(2), 102 .db_reg_addr = PLAT_CSS_MHU_BASE + 103 NRD_REMOTE_CHIP_MEM_OFFSET(2) + 104 MHU_V3_SENDER_REG_SET(0), 105 .db_preserve_mask = 0xfffffffe, 106 .db_modify_mask = 0x1, 107 .ring_doorbell = &mhu_ring_doorbell, 108 }, 109 #endif 110 #if (NRD_CHIP_COUNT > 3) 111 { 112 .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE + 113 NRD_REMOTE_CHIP_MEM_OFFSET(3), 114 .db_reg_addr = PLAT_CSS_MHU_BASE + 115 NRD_REMOTE_CHIP_MEM_OFFSET(3) + 116 MHU_V3_SENDER_REG_SET(0), 117 .db_preserve_mask = 0xfffffffe, 118 .db_modify_mask = 0x1, 119 .ring_doorbell = &mhu_ring_doorbell, 120 }, 121 #endif 122 }; 123 124 scmi_channel_plat_info_t *plat_css_get_scmi_info(unsigned int channel_id) 125 { 126 if (nrd_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM || 127 nrd_plat_info.platform_id == RD_V1_SID_VER_PART_NUM || 128 nrd_plat_info.platform_id == RD_N2_SID_VER_PART_NUM || 129 nrd_plat_info.platform_id == RD_V2_SID_VER_PART_NUM || 130 nrd_plat_info.platform_id == RD_N2_CFG1_SID_VER_PART_NUM || 131 nrd_plat_info.platform_id == RD_N2_CFG3_SID_VER_PART_NUM) { 132 if (channel_id >= ARRAY_SIZE(plat_rd_scmi_info)) { 133 panic(); 134 } 135 return &plat_rd_scmi_info[channel_id]; 136 } else if (nrd_plat_info.platform_id == RD_V3_SID_VER_PART_NUM || 137 nrd_plat_info.platform_id == RD_V3_CFG1_SID_VER_PART_NUM || 138 nrd_plat_info.platform_id == RD_V3_CFG2_SID_VER_PART_NUM) { 139 if (channel_id >= ARRAY_SIZE(plat3_rd_scmi_info)) { 140 panic(); 141 } 142 return &plat3_rd_scmi_info[channel_id]; 143 } else if (nrd_plat_info.platform_id == SGI575_SSC_VER_PART_NUM) { 144 return &sgi575_scmi_plat_info; 145 } else { 146 panic(); 147 } 148 } 149 150 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, 151 u_register_t arg2, u_register_t arg3) 152 { 153 nrd_plat_info.platform_id = plat_arm_nrd_get_platform_id(); 154 nrd_plat_info.config_id = plat_arm_nrd_get_config_id(); 155 nrd_plat_info.multi_chip_mode = plat_arm_nrd_get_multi_chip_mode(); 156 157 #if RESET_TO_BL31 158 #if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER) 159 /* Set the counter frequency for the generic timer */ 160 write_cntfrq_el0(plat_get_syscnt_freq2()); 161 #endif 162 #endif /* RESET_TO_BL31 */ 163 164 /* Initialize generic timer */ 165 generic_delay_timer_init(); 166 167 #if SPMD_SPM_AT_SEL2 && !RESET_TO_BL31 168 INFO("BL31 FCONF: FW_CONFIG address = 0x%lx\n", (uintptr_t)arg1); 169 /* Initialize BL31's copy of the DTB registry because SPMD needs the 170 * TOS_FW_CONFIG's addresses to make a copy. 171 */ 172 fconf_populate("FW_CONFIG", arg1); 173 174 /* arg1 is supposed to point to SOC_FW_CONFIG */ 175 const struct dyn_cfg_dtb_info_t *soc_fw_config_info; 176 177 soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID); 178 if (soc_fw_config_info != NULL) { 179 arg1 = soc_fw_config_info->config_addr; 180 } 181 #endif /* SPMD_SPM_AT_SEL2 && !RESET_TO_BL31 */ 182 arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); 183 } 184 185 /******************************************************************************* 186 * This function inserts platform information via device tree nodes as, 187 * system-id { 188 * platform-id = <0>; 189 * config-id = <0>; 190 * } 191 ******************************************************************************/ 192 #if RESET_TO_BL31 193 static int append_config_node(uintptr_t fdt_base_addr, uintptr_t fdt_base_size) 194 { 195 void *fdt; 196 int nodeoffset, err; 197 unsigned int platid = 0, platcfg = 0; 198 199 if (fdt_base_addr == 0) { 200 ERROR("NT_FW CONFIG base address is NULL\n"); 201 return -1; 202 } 203 204 fdt = (void *)fdt_base_addr; 205 206 /* Check the validity of the fdt */ 207 if (fdt_check_header(fdt) != 0) { 208 ERROR("Invalid NT_FW_CONFIG DTB passed\n"); 209 return -1; 210 } 211 212 nodeoffset = fdt_subnode_offset(fdt, 0, "system-id"); 213 if (nodeoffset < 0) { 214 ERROR("Failed to get system-id node offset\n"); 215 return -1; 216 } 217 218 platid = plat_arm_nrd_get_platform_id(); 219 err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid); 220 if (err < 0) { 221 ERROR("Failed to set platform-id\n"); 222 return -1; 223 } 224 225 platcfg = plat_arm_nrd_get_config_id(); 226 err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg); 227 if (err < 0) { 228 ERROR("Failed to set config-id\n"); 229 return -1; 230 } 231 232 platcfg = plat_arm_nrd_get_multi_chip_mode(); 233 err = fdt_setprop_u32(fdt, nodeoffset, "multi-chip-mode", platcfg); 234 if (err < 0) { 235 ERROR("Failed to set multi-chip-mode\n"); 236 return -1; 237 } 238 239 flush_dcache_range((uintptr_t)fdt, fdt_base_size); 240 return 0; 241 } 242 #endif 243 244 void nrd_bl31_common_platform_setup(void) 245 { 246 247 arm_bl31_platform_setup(); 248 249 /* Configure the warm reboot SGI for primary core */ 250 css_setup_cpu_pwr_down_intr(); 251 252 #if CSS_SYSTEM_GRACEFUL_RESET 253 /* Register priority level handlers for reboot */ 254 ehf_register_priority_handler(PLAT_REBOOT_PRI, 255 css_reboot_interrupt_handler); 256 #endif 257 258 #if RESET_TO_BL31 259 int ret = append_config_node(NRD_CSS_BL31_PRELOAD_DTB_BASE, 260 NRD_CSS_BL31_PRELOAD_DTB_SIZE); 261 262 if (ret != 0) { 263 panic(); 264 } 265 #endif 266 } 267 268 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 269 { 270 /* 271 * For RD-E1-Edge, only CPU power ON/OFF, PSCI platform callbacks are 272 * supported. 273 */ 274 if (((nrd_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM) && 275 (nrd_plat_info.config_id == RD_E1_EDGE_CONFIG_ID))) { 276 ops->cpu_standby = NULL; 277 ops->system_off = NULL; 278 ops->system_reset = NULL; 279 ops->get_sys_suspend_power_state = NULL; 280 ops->pwr_domain_suspend = NULL; 281 ops->pwr_domain_suspend_finish = NULL; 282 } 283 284 return css_scmi_override_pm_ops(ops); 285 } 286