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
plat_css_get_scmi_info(unsigned int channel_id)72 scmi_channel_plat_info_t *plat_css_get_scmi_info(unsigned int channel_id)
73 {
74 return &n1sdp_scmi_plat_info;
75 }
76
plat_arm_psci_override_pm_ops(plat_psci_ops_t * ops)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
remote_dmc_ecc_setup(uint8_t remote_ddr_size)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
n1sdp_bl31_multichip_setup(void)125 void n1sdp_bl31_multichip_setup(void)
126 {
127 gic600_multichip_init(&n1sdp_multichip_data);
128 }
129
bl31_platform_setup(void)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 */
plat_spmd_handle_group0_interrupt(uint32_t intid)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