1 /* 2 * Copyright (c) 2018-2025, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <common/debug.h> 8 #include <drivers/arm/css/css_mhu_doorbell.h> 9 #include <drivers/arm/css/scmi.h> 10 #include <drivers/arm/css/sds.h> 11 #include <drivers/arm/gic600_multichip.h> 12 #include <lib/mmio.h> 13 #include <lib/utils.h> 14 #include <plat/arm/common/plat_arm.h> 15 16 #include "n1sdp_def.h" 17 #include "n1sdp_private.h" 18 #include <platform_def.h> 19 20 #define RT_OWNER 0 21 22 /* 23 * Platform information structure stored in SDS. 24 * This structure holds information about platform's DDR 25 * size which will be used to zero out the memory before 26 * enabling the ECC capability as well as information 27 * about multichip setup 28 * - multichip mode 29 * - secondary_count 30 * - Local DDR size in GB, DDR memory in master board 31 * - Remote DDR size in GB, DDR memory in secondary board 32 */ 33 struct n1sdp_plat_info { 34 bool multichip_mode; 35 uint8_t secondary_count; 36 uint8_t local_ddr_size; 37 uint8_t remote_ddr_size; 38 } __packed; 39 40 static scmi_channel_plat_info_t n1sdp_scmi_plat_info = { 41 .scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE, 42 .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, 43 .db_preserve_mask = 0xfffffffe, 44 .db_modify_mask = 0x1, 45 .ring_doorbell = &mhu_ring_doorbell 46 }; 47 48 static struct gic600_multichip_data n1sdp_multichip_data __init = { 49 .base_addrs = { 50 PLAT_ARM_GICD_BASE 51 }, 52 .rt_owner = RT_OWNER, 53 .chip_count = 1, 54 .chip_addrs = { 55 [RT_OWNER] = { 56 PLAT_ARM_GICD_BASE >> 16, 57 PLAT_ARM_GICD_BASE >> 16 58 } 59 }, 60 .spi_ids = { 61 {PLAT_ARM_GICD_BASE, 32, 511}, 62 {PLAT_ARM_GICD_BASE, 512, 991} 63 } 64 }; 65 66 static uintptr_t n1sdp_multichip_gicr_frames[3] = { 67 PLAT_ARM_GICR_BASE, 68 PLAT_ARM_GICR_BASE + PLAT_ARM_REMOTE_CHIP_OFFSET, 69 0 70 }; 71 72 scmi_channel_plat_info_t *plat_css_get_scmi_info(unsigned int channel_id) 73 { 74 return &n1sdp_scmi_plat_info; 75 } 76 77 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 78 { 79 ops->pwr_domain_off = n1sdp_pwr_domain_off; 80 return css_scmi_override_pm_ops(ops); 81 } 82 83 /* 84 * N1SDP platform supports RDIMMs with ECC capability. To use the ECC 85 * capability, the entire DDR memory space has to be zeroed out before 86 * enabling the ECC bits in DMC620. Zeroing out several gigabytes of 87 * memory from SCP is quite time consuming so the following function 88 * is added to zero out the DDR memory from application processor which is 89 * much faster compared to SCP. Local DDR memory is zeroed out during BL2 90 * stage. If remote chip is connected, it's DDR memory is zeroed out here. 91 */ 92 93 void remote_dmc_ecc_setup(uint8_t remote_ddr_size) 94 { 95 uint64_t remote_dram2_size; 96 97 remote_dram2_size = (remote_ddr_size * 1024UL * 1024UL * 1024UL) - 98 N1SDP_REMOTE_DRAM1_SIZE; 99 /* multichip setup */ 100 INFO("Zeroing remote DDR memories\n"); 101 zero_normalmem((void *)N1SDP_REMOTE_DRAM1_BASE, 102 N1SDP_REMOTE_DRAM1_SIZE); 103 flush_dcache_range(N1SDP_REMOTE_DRAM1_BASE, N1SDP_REMOTE_DRAM1_SIZE); 104 zero_normalmem((void *)N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size); 105 flush_dcache_range(N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size); 106 107 INFO("Enabling ECC on remote DMCs\n"); 108 /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ 109 mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, 110 N1SDP_DMC_MEMC_CMD_CONFIG); 111 mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, 112 N1SDP_DMC_MEMC_CMD_CONFIG); 113 114 /* Enable ECC in DMCs */ 115 mmio_setbits_32(N1SDP_REMOTE_DMC0_ERR0CTLR0_REG, 116 N1SDP_DMC_ERR0CTLR0_ECC_EN); 117 mmio_setbits_32(N1SDP_REMOTE_DMC1_ERR0CTLR0_REG, 118 N1SDP_DMC_ERR0CTLR0_ECC_EN); 119 120 /* Set DMCs to READY state */ 121 mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); 122 mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); 123 } 124 125 void n1sdp_bl31_multichip_setup(void) 126 { 127 gic600_multichip_init(&n1sdp_multichip_data); 128 } 129 130 void bl31_platform_setup(void) 131 { 132 int ret; 133 struct n1sdp_plat_info plat_info; 134 135 ret = sds_init(SDS_SCP_AP_REGION_ID); 136 if (ret != SDS_OK) { 137 ERROR("SDS initialization failed\n"); 138 panic(); 139 } 140 141 ret = sds_struct_read(SDS_SCP_AP_REGION_ID, 142 N1SDP_SDS_PLATFORM_INFO_STRUCT_ID, 143 N1SDP_SDS_PLATFORM_INFO_OFFSET, 144 &plat_info, 145 N1SDP_SDS_PLATFORM_INFO_SIZE, 146 SDS_ACCESS_MODE_NON_CACHED); 147 if (ret != SDS_OK) { 148 ERROR("Error getting platform info from SDS\n"); 149 panic(); 150 } 151 /* Validate plat_info SDS */ 152 if ((plat_info.local_ddr_size == 0) 153 || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) 154 || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) 155 || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) { 156 ERROR("platform info SDS is corrupted\n"); 157 panic(); 158 } 159 160 if (plat_info.multichip_mode) { 161 n1sdp_multichip_data.chip_count = plat_info.secondary_count + 1; 162 n1sdp_bl31_multichip_setup(); 163 } 164 arm_bl31_platform_setup(); 165 166 /* 167 * Initialise the GIC's frame. Hide the second frame when not operating 168 * in multichip mode. 169 */ 170 if (!plat_info.multichip_mode) { 171 n1sdp_multichip_gicr_frames[1] = 0; 172 } 173 gic_set_gicr_frames(n1sdp_multichip_gicr_frames); 174 175 /* Check if remote memory is present */ 176 if ((plat_info.multichip_mode) && (plat_info.remote_ddr_size != 0)) 177 remote_dmc_ecc_setup(plat_info.remote_ddr_size); 178 } 179 180 #if defined(SPD_spmd) && (SPMC_AT_EL3 == 0) 181 /* 182 * A dummy implementation of the platform handler for Group0 secure interrupt. 183 */ 184 int plat_spmd_handle_group0_interrupt(uint32_t intid) 185 { 186 (void)intid; 187 return -1; 188 } 189 #endif /*defined(SPD_spmd) && (SPMC_AT_EL3 == 0)*/ 190