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