1 /* 2 * Copyright (c) 2018-2022, 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 <platform_def.h> 18 19 /* 20 * Platform information structure stored in SDS. 21 * This structure holds information about platform's DDR 22 * size which will be used to zero out the memory before 23 * enabling the ECC capability as well as information 24 * about multichip setup 25 * - multichip mode 26 * - secondary_count 27 * - Local DDR size in GB, DDR memory in master board 28 * - Remote DDR size in GB, DDR memory in secondary board 29 */ 30 struct n1sdp_plat_info { 31 bool multichip_mode; 32 uint8_t secondary_count; 33 uint8_t local_ddr_size; 34 uint8_t remote_ddr_size; 35 } __packed; 36 37 static scmi_channel_plat_info_t n1sdp_scmi_plat_info = { 38 .scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE, 39 .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF, 40 .db_preserve_mask = 0xfffffffe, 41 .db_modify_mask = 0x1, 42 .ring_doorbell = &mhu_ring_doorbell 43 }; 44 45 static struct gic600_multichip_data n1sdp_multichip_data __init = { 46 .rt_owner_base = PLAT_ARM_GICD_BASE, 47 .rt_owner = 0, 48 .chip_count = 1, 49 .chip_addrs = { 50 PLAT_ARM_GICD_BASE >> 16, 51 PLAT_ARM_GICD_BASE >> 16 52 }, 53 .spi_ids = { 54 {PLAT_ARM_GICD_BASE, 32, 479}, 55 {PLAT_ARM_GICD_BASE, 512, 959} 56 } 57 }; 58 59 static uintptr_t n1sdp_multichip_gicr_frames[3] = { 60 PLAT_ARM_GICR_BASE, 61 PLAT_ARM_GICR_BASE + PLAT_ARM_REMOTE_CHIP_OFFSET, 62 0 63 }; 64 65 scmi_channel_plat_info_t *plat_css_get_scmi_info(unsigned int channel_id) 66 { 67 return &n1sdp_scmi_plat_info; 68 } 69 70 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 71 { 72 return css_scmi_override_pm_ops(ops); 73 } 74 75 /* 76 * N1SDP platform supports RDIMMs with ECC capability. To use the ECC 77 * capability, the entire DDR memory space has to be zeroed out before 78 * enabling the ECC bits in DMC620. Zeroing out several gigabytes of 79 * memory from SCP is quite time consuming so the following function 80 * is added to zero out the DDR memory from application processor which is 81 * much faster compared to SCP. Local DDR memory is zeroed out during BL2 82 * stage. If remote chip is connected, it's DDR memory is zeroed out here. 83 */ 84 85 void remote_dmc_ecc_setup(uint8_t remote_ddr_size) 86 { 87 uint64_t remote_dram2_size; 88 89 remote_dram2_size = (remote_ddr_size * 1024UL * 1024UL * 1024UL) - 90 N1SDP_REMOTE_DRAM1_SIZE; 91 /* multichip setup */ 92 INFO("Zeroing remote DDR memories\n"); 93 zero_normalmem((void *)N1SDP_REMOTE_DRAM1_BASE, 94 N1SDP_REMOTE_DRAM1_SIZE); 95 flush_dcache_range(N1SDP_REMOTE_DRAM1_BASE, N1SDP_REMOTE_DRAM1_SIZE); 96 zero_normalmem((void *)N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size); 97 flush_dcache_range(N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size); 98 99 INFO("Enabling ECC on remote DMCs\n"); 100 /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */ 101 mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, 102 N1SDP_DMC_MEMC_CMD_CONFIG); 103 mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, 104 N1SDP_DMC_MEMC_CMD_CONFIG); 105 106 /* Enable ECC in DMCs */ 107 mmio_setbits_32(N1SDP_REMOTE_DMC0_ERR0CTLR0_REG, 108 N1SDP_DMC_ERR0CTLR0_ECC_EN); 109 mmio_setbits_32(N1SDP_REMOTE_DMC1_ERR0CTLR0_REG, 110 N1SDP_DMC_ERR0CTLR0_ECC_EN); 111 112 /* Set DMCs to READY state */ 113 mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); 114 mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY); 115 } 116 117 void n1sdp_bl31_multichip_setup(void) 118 { 119 plat_arm_override_gicr_frames(n1sdp_multichip_gicr_frames); 120 gic600_multichip_init(&n1sdp_multichip_data); 121 } 122 123 void bl31_platform_setup(void) 124 { 125 int ret; 126 struct n1sdp_plat_info plat_info; 127 128 ret = sds_init(); 129 if (ret != SDS_OK) { 130 ERROR("SDS initialization failed\n"); 131 panic(); 132 } 133 134 ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID, 135 N1SDP_SDS_PLATFORM_INFO_OFFSET, 136 &plat_info, 137 N1SDP_SDS_PLATFORM_INFO_SIZE, 138 SDS_ACCESS_MODE_NON_CACHED); 139 if (ret != SDS_OK) { 140 ERROR("Error getting platform info from SDS\n"); 141 panic(); 142 } 143 /* Validate plat_info SDS */ 144 if ((plat_info.local_ddr_size == 0) 145 || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) 146 || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB) 147 || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) { 148 ERROR("platform info SDS is corrupted\n"); 149 panic(); 150 } 151 152 if (plat_info.multichip_mode) { 153 n1sdp_multichip_data.chip_count = plat_info.secondary_count + 1; 154 n1sdp_bl31_multichip_setup(); 155 } 156 arm_bl31_platform_setup(); 157 158 /* Check if remote memory is present */ 159 if ((plat_info.multichip_mode) && (plat_info.remote_ddr_size != 0)) 160 remote_dmc_ecc_setup(plat_info.remote_ddr_size); 161 } 162