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