xref: /rk3399_ARM-atf/plat/intel/soc/agilex5/soc/agilex5_ddr.c (revision ab5cbea6b3b0f0749154d8063c122e0316580ea3)
1 /*
2  * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stddef.h>
8 #include <stdlib.h>
9 #include <common/debug.h>
10 #include <drivers/delay_timer.h>
11 #include "lib/mmio.h"
12 
13 #include "agilex5_ddr.h"
14 #include "agilex5_iossm_mailbox.h"
15 #include "socfpga_mailbox.h"
16 
17 /*
18  * TODO: We need to leverage the legacy products DDR drivers and consider
19  * the upcoming products like KM and then come up with common source code/driver
20  * architecture to address all the products in one view.
21  */
22 
23 #define SYSMGR_BS_COLD3_DDR_RESET_TYPE_MASK		GENMASK(31, 29)
24 #define SYSMGR_BS_COLD3_DDR_RESET_TYPE_SHIFT		29
25 #define SYSMGR_BS_COLD3_DDR_DBE_MASK			(1 << 1)
26 #define SYSMGR_BS_COLD3_OCRAM_DBE_MASK			(1)
27 #define SYSMGR_BS_POR0_DDR_PROGRESS_MASK		(1)
28 
29 /* MPFE NOC registers */
30 #define F2SDRAM_SIDEBAND_FLAGOUTSET0			0x50
31 #define F2SDRAM_SIDEBAND_FLAGOUTCLR0			0x54
32 #define F2SDRAM_SIDEBAND_FLAGOUTSTATUS0			0x58
33 
34 #define SOCFPGA_F2SDRAM_MGR_ADDRESS			0x18001000
35 #define SOCFPGA_MPFE_SCR_IO96B0				0x18000D00
36 #define SOCFPGA_MPFE_SCR_IO96B1				0x18000D04
37 #define SOCFPGA_MPFE_NOC_SCHED_CSR			0x18000D08
38 
39 #define SIDEBANDMGR_FLAGOUTSET0_REG			(SOCFPGA_F2SDRAM_MGR_ADDRESS \
40 							+ F2SDRAM_SIDEBAND_FLAGOUTSET0)
41 #define SIDEBANDMGR_FLAGOUTSTATUS0_REG			(SOCFPGA_F2SDRAM_MGR_ADDRESS \
42 							+F2SDRAM_SIDEBAND_FLAGOUTSTATUS0)
43 #define SIDEBANDMGR_FLAGOUTCLR0_REG			(SOCFPGA_F2SDRAM_MGR_ADDRESS \
44 							+ F2SDRAM_SIDEBAND_FLAGOUTCLR0)
45 
46 /* Firewall MPU DDR SCR registers */
47 #define FW_MPU_DDR_SCR_EN				0x00
48 #define FW_MPU_DDR_SCR_EN_SET				0x04
49 #define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE		0x10
50 #define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT		0x14
51 #define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT		0x18
52 #define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT		0x1c
53 
54 #define SOCFPGA_FW_DDR_CCU_DMI0_ADDRESS			0x18000800
55 #define SOCFPGA_FW_DDR_CCU_DMI1_ADDRESS			0x18000A00
56 #define SOCFPGA_FW_TBU2NOC_ADDRESS			0x18000C00
57 
58 #define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE		0x90
59 #define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT	0x94
60 #define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT		0x98
61 #define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT	0x9c
62 #define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT_FIELD	0xff
63 
64 /* Firewall F2SDRAM DDR SCR registers */
65 #define FW_F2SDRAM_DDR_SCR_EN				0x00
66 #define FW_F2SDRAM_DDR_SCR_EN_SET			0x04
67 #define FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASE		0x10
68 #define FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASEEXT		0x14
69 #define FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMIT		0x18
70 #define FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMITEXT		0x1c
71 
72 #define FW_MPU_DDR_SCR_WRITEL(data, reg)					\
73 	do {									\
74 		mmio_write_32(SOCFPGA_FW_DDR_CCU_DMI0_ADDRESS + (reg), data);	\
75 		mmio_write_32(SOCFPGA_FW_DDR_CCU_DMI1_ADDRESS + (reg), data);	\
76 	} while (0)
77 
78 #define FW_F2SDRAM_DDR_SCR_WRITEL(data, reg)				\
79 	mmio_write_32(SOCFPGA_FW_TBU2NOC_ADDRESS + (reg), data)
80 
81 /* DDR banks info set */
82 static struct ddr_info ddr_info_set[CONFIG_NR_DRAM_BANKS];
83 
84 /* Reset type */
85 enum reset_type {
86 	POR_RESET,
87 	WARM_RESET,
88 	COLD_RESET,
89 	NCONFIG,
90 	JTAG_CONFIG,
91 	RSU_RECONFIG
92 };
93 
94 /* Get reset type by reading boot scratch register cold3 */
get_reset_type(uint32_t sys_reg)95 static inline enum reset_type get_reset_type(uint32_t sys_reg)
96 {
97 	return ((sys_reg & SYSMGR_BS_COLD3_DDR_RESET_TYPE_MASK) >>
98 		 SYSMGR_BS_COLD3_DDR_RESET_TYPE_SHIFT);
99 }
100 
101 /* Get reset type string */
get_reset_type_str(enum reset_type reset_t)102 const char *get_reset_type_str(enum reset_type reset_t)
103 {
104 	switch (reset_t) {
105 	case POR_RESET:
106 		return "Power-On";
107 	case WARM_RESET:
108 		return "Warm";
109 	case COLD_RESET:
110 		return "Cold";
111 	case NCONFIG:
112 		return "NCONFIG";
113 	case JTAG_CONFIG:
114 		return "JTAG Config";
115 	case RSU_RECONFIG:
116 		return "RSU Reconfig";
117 	default:
118 		return "Unknown";
119 	}
120 }
121 
122 /* DDR hang check before the reset */
is_ddr_init_hang(void)123 static inline bool is_ddr_init_hang(void)
124 {
125 	uint32_t sys_reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_POR_0));
126 
127 	if ((sys_reg & SYSMGR_BS_POR0_DDR_PROGRESS_MASK) != 0) {
128 		INFO("DDR: Hang before this reset\n");
129 		return true;
130 	}
131 
132 	return false;
133 }
134 
135 /* Set the DDR init progress bit */
ddr_init_inprogress(bool start)136 static inline void ddr_init_inprogress(bool start)
137 {
138 	if (start) {
139 		mmio_setbits_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_POR_0),
140 				SYSMGR_BS_POR0_DDR_PROGRESS_MASK);
141 	} else {
142 		mmio_clrbits_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_POR_0),
143 				SYSMGR_BS_POR0_DDR_PROGRESS_MASK);
144 	}
145 }
146 
147 /* Configure the IO96B CSRs address based on the handoff data */
config_io96b_csr_addr(bool is_dualemif,struct io96b_info * io96b_ctrl)148 static void config_io96b_csr_addr(bool is_dualemif, struct io96b_info *io96b_ctrl)
149 {
150 	if (is_dualemif)
151 		io96b_ctrl->num_instance = 2;
152 	else
153 		io96b_ctrl->num_instance = 1;
154 
155 	/* Assign IO96B CSR base address if it is valid */
156 	for (int i = 0; i < io96b_ctrl->num_instance; i++) {
157 		switch (i) {
158 		case 0:
159 			io96b_ctrl->io96b_0.io96b_csr_addr = 0x18400000;
160 			INFO("DDR: IO96B0 0x%llx CSR enabled\n",
161 			     io96b_ctrl->io96b_0.io96b_csr_addr);
162 			break;
163 
164 		case 1:
165 			io96b_ctrl->io96b_1.io96b_csr_addr = 0x18800000;
166 			INFO("DDR: IO96B1 0x%llx CSR enabled\n",
167 			     io96b_ctrl->io96b_1.io96b_csr_addr);
168 			break;
169 
170 		default:
171 			ERROR("%s: Invalid IO96B CSR\n", __func__);
172 		} /* switch */
173 	} /* for */
174 }
175 
hps_ocram_dbe_status(void)176 static inline bool hps_ocram_dbe_status(void)
177 {
178 	uint32_t sys_reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_3));
179 
180 	if ((sys_reg & SYSMGR_BS_COLD3_OCRAM_DBE_MASK) != 0)
181 		return true;
182 
183 	return false;
184 }
185 
ddr_ecc_dbe_status(void)186 static inline bool ddr_ecc_dbe_status(void)
187 {
188 	uint32_t sys_reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_3));
189 
190 	if ((sys_reg & SYSMGR_BS_COLD3_DDR_DBE_MASK) != 0)
191 		return true;
192 
193 	return false;
194 }
195 
sdram_set_firewall_non_f2sdram(void)196 static void sdram_set_firewall_non_f2sdram(void)
197 {
198 	uint32_t i;
199 	phys_size_t value;
200 	uint32_t lower, upper;
201 
202 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
203 		if (ddr_info_set[i].size == 0) {
204 			continue;
205 		}
206 
207 		value = ddr_info_set[i].start;
208 
209 		/*
210 		 * Keep first 1MB of SDRAM memory region as secure region when
211 		 * using ATF flow, where the ATF code is located.
212 		 */
213 		value += SZ_1M;
214 
215 		/* Setting non-secure MPU region base and base extended */
216 		lower = LO(value);
217 		upper = HI(value);
218 
219 		FW_MPU_DDR_SCR_WRITEL(lower,
220 				      FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE +
221 				      (i * 4 * sizeof(uint32_t)));
222 		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
223 				      FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT +
224 				      (i * 4 * sizeof(uint32_t)));
225 
226 		/* Setting non-secure Non-MPU region base and base extended */
227 		FW_MPU_DDR_SCR_WRITEL(lower,
228 				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE +
229 				      (i * 4 * sizeof(uint32_t)));
230 		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
231 				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT +
232 				      (i * 4 * sizeof(uint32_t)));
233 
234 		/* Setting non-secure MPU limit and limit extended */
235 		value = ddr_info_set[i].start + ddr_info_set[i].size - 1;
236 
237 		lower = LO(value);
238 		upper = HI(value);
239 
240 		FW_MPU_DDR_SCR_WRITEL(lower,
241 				      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT +
242 				      (i * 4 * sizeof(uint32_t)));
243 		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
244 				      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT +
245 				      (i * 4 * sizeof(uint32_t)));
246 
247 		/* Setting non-secure Non-MPU limit and limit extended */
248 		FW_MPU_DDR_SCR_WRITEL(lower,
249 				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT +
250 				      (i * 4 * sizeof(uint32_t)));
251 		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
252 				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT +
253 				      (i * 4 * sizeof(uint32_t)));
254 
255 		FW_MPU_DDR_SCR_WRITEL(BIT(i) | BIT(i + 8),
256 				      FW_MPU_DDR_SCR_EN_SET);
257 	}
258 }
259 
sdram_set_firewall_f2sdram(void)260 static void sdram_set_firewall_f2sdram(void)
261 {
262 	uint32_t i;
263 	phys_size_t value;
264 	uint32_t lower, upper;
265 
266 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
267 		if (ddr_info_set[i].size == 0) {
268 			continue;
269 		}
270 
271 		value = ddr_info_set[i].start;
272 
273 		/* Keep first 1MB of SDRAM memory region as secure region when
274 		 * using ATF flow, where the ATF code is located.
275 		 */
276 		value += SZ_1M;
277 
278 		/* Setting base and base extended */
279 		lower = LO(value);
280 		upper = HI(value);
281 		FW_F2SDRAM_DDR_SCR_WRITEL(lower,
282 					  FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASE +
283 					  (i * 4 * sizeof(uint32_t)));
284 		FW_F2SDRAM_DDR_SCR_WRITEL(upper & 0xff,
285 					  FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASEEXT +
286 					  (i * 4 * sizeof(uint32_t)));
287 
288 		/* Setting limit and limit extended */
289 		value = ddr_info_set[i].start + ddr_info_set[i].size - 1;
290 
291 		lower = LO(value);
292 		upper = HI(value);
293 
294 		FW_F2SDRAM_DDR_SCR_WRITEL(lower,
295 					  FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMIT +
296 					  (i * 4 * sizeof(uint32_t)));
297 		FW_F2SDRAM_DDR_SCR_WRITEL(upper & 0xff,
298 					  FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMITEXT +
299 					  (i * 4 * sizeof(uint32_t)));
300 
301 		FW_F2SDRAM_DDR_SCR_WRITEL(BIT(i), FW_F2SDRAM_DDR_SCR_EN_SET);
302 	}
303 }
304 
sdram_set_firewall(void)305 static void sdram_set_firewall(void)
306 {
307 	sdram_set_firewall_non_f2sdram();
308 	sdram_set_firewall_f2sdram();
309 }
310 
311 /*
312  * Agilex5 DDR/IOSSM controller initialization routine
313  */
agilex5_ddr_init(handoff * hoff_ptr)314 int agilex5_ddr_init(handoff *hoff_ptr)
315 {
316 	int ret;
317 	bool full_mem_init = false;
318 	phys_size_t hw_ddr_size;
319 	phys_size_t config_ddr_size;
320 	struct io96b_info io96b_ctrl = {0};
321 	enum reset_type reset_t = get_reset_type(mmio_read_32(SOCFPGA_SYSMGR(
322 						BOOT_SCRATCH_COLD_3)));
323 	bool is_dualport = hoff_ptr->ddr_config & BIT(0);
324 	bool is_dualemif = hoff_ptr->ddr_config & BIT(1);
325 
326 	NOTICE("DDR: Reset type is '%s'\n", get_reset_type_str(reset_t));
327 
328 	/* DDR initialization progress status tracking */
329 	bool is_ddr_hang_bfr_rst = is_ddr_init_hang();
330 
331 	/* Set the DDR initialization progress */
332 	ddr_init_inprogress(true);
333 
334 	/* Configure the IO96B CSR address based on the handoff data */
335 	config_io96b_csr_addr(is_dualemif, &io96b_ctrl);
336 
337 	/* Configuring MPFE sideband manager registers */
338 	/* Dual port setting */
339 	if (is_dualport)
340 		mmio_setbits_32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(4));
341 
342 	/* Dual EMIF setting */
343 	if (is_dualemif) {
344 		/* Set mpfe_lite_active in the system manager. */
345 		mmio_setbits_32(SOCFPGA_SYSMGR(MPFE_CONFIG), BIT(8));
346 
347 		/* Set mpfe_lite_intfcsel select in the system manager. */
348 		mmio_setbits_32(SOCFPGA_SYSMGR(MPFE_CONFIG), BIT(2));
349 
350 		mmio_setbits_32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(5));
351 	}
352 
353 	if (is_dualport || is_dualemif)
354 		INFO("DDR: SIDEBANDMGR_FLAGOUTSTATUS0: 0x%x\n",
355 		     mmio_read_32(SIDEBANDMGR_FLAGOUTSTATUS0_REG));
356 
357 	/* Ensure calibration status passing */
358 	init_mem_cal(&io96b_ctrl);
359 
360 	/* Initiate IOSSM mailbox */
361 	io96b_mb_init(&io96b_ctrl);
362 
363 	/* Need to trigger re-calibration for DDR DBE */
364 	if (ddr_ecc_dbe_status()) {
365 		io96b_ctrl.io96b_0.cal_status = false;
366 		io96b_ctrl.io96b_1.cal_status = false;
367 		io96b_ctrl.overall_cal_status = io96b_ctrl.io96b_0.cal_status ||
368 						io96b_ctrl.io96b_1.cal_status;
369 	}
370 
371 	/* Trigger re-calibration if calibration failed */
372 	if (!(io96b_ctrl.overall_cal_status)) {
373 		NOTICE("DDR: Re-calibration in progress...\n");
374 		trig_mem_cal(&io96b_ctrl);
375 	}
376 	NOTICE("DDR: Calibration success\n");
377 
378 	/* DDR type, DDR size and ECC status */
379 	ret = get_mem_technology(&io96b_ctrl);
380 	if (ret != 0) {
381 		ERROR("DDR: Failed to get DDR type\n");
382 		return ret;
383 	}
384 
385 	ret = get_mem_width_info(&io96b_ctrl);
386 	if (ret != 0) {
387 		ERROR("DDR: Failed to get DDR size\n");
388 		return ret;
389 	}
390 
391 	ret = ecc_enable_status(&io96b_ctrl);
392 	if (ret != 0) {
393 		ERROR("DDR: Failed to get DDR ECC status\n");
394 		return ret;
395 	}
396 
397 	/* DDR size queried from the IOSSM controller */
398 	hw_ddr_size = io96b_ctrl.overall_size;
399 
400 	/* Update the DDR size if it is In-line ECC. */
401 	if (io96b_ctrl.is_inline_ecc)
402 		hw_ddr_size = GET_INLINE_ECC_HW_DDR_SIZE(hw_ddr_size);
403 
404 	/* TODO: To update config_ddr_size by using FDT in the future. */
405 	config_ddr_size = 0x80000000;
406 	ddr_info_set[0].start = DRAM_BASE;
407 	ddr_info_set[0].size = hw_ddr_size;
408 
409 	if (config_ddr_size != hw_ddr_size) {
410 		WARN("DDR: DDR size configured is (%lld MiB)\n", config_ddr_size >> 20);
411 		WARN("DDR: Mismatch with hardware size (%lld MiB).\n", hw_ddr_size >> 20);
412 	}
413 
414 	if (config_ddr_size > hw_ddr_size) {
415 		ERROR("DDR: Confgured DDR size is greater than the hardware size - HANG!!!\n");
416 		while (1)
417 			;
418 	}
419 
420 	/*
421 	 * HPS cold or warm reset? If yes, skip full memory initialization if
422 	 * ECC is enabled to preserve memory content.
423 	 */
424 	if (io96b_ctrl.ecc_status) {
425 		/* Let's check the ECC interrupt status on the DBE (Double Bit Error). */
426 		if (get_ecc_dbe_status(&io96b_ctrl)) {
427 			NOTICE("DDR: ECC-Double Bit Error occurred!!\n");
428 			NOTICE("DDR: Resetting the system to recover!!\n");
429 			mailbox_reset_cold();
430 		}
431 
432 		full_mem_init = hps_ocram_dbe_status() || ddr_ecc_dbe_status() ||
433 				is_ddr_hang_bfr_rst;
434 
435 		if (full_mem_init || !((reset_t == WARM_RESET) || (reset_t == COLD_RESET))) {
436 			ret = bist_mem_init_start(&io96b_ctrl);
437 			if (ret != 0) {
438 				ERROR("DDR: Failed to fully initialize DDR memory\n");
439 				return ret;
440 			}
441 		}
442 		INFO("DDR: ECC initialized successfully\n");
443 	}
444 
445 	sdram_set_firewall();
446 
447 	/*
448 	 * Firewall setting for MPFE CSRs, allow both secure and non-secure
449 	 * transactions.
450 	 */
451 	/* IO96B0_reg */
452 	mmio_setbits_32(SOCFPGA_MPFE_SCR_IO96B0, BIT(0));
453 	/* IO96B1_reg */
454 	mmio_setbits_32(SOCFPGA_MPFE_SCR_IO96B1, BIT(0));
455 	/* noc_scheduler_csr */
456 	mmio_setbits_32(SOCFPGA_MPFE_NOC_SCHED_CSR, BIT(0));
457 
458 	INFO("DDR: firewall init done\n");
459 
460 	/* Ending DDR driver initialization success tracking */
461 	ddr_init_inprogress(false);
462 
463 	NOTICE("###DDR:init success###\n");
464 
465 	return 0;
466 }
467