blob: 0d60324c6a6a47e65dccae7ad8e4628feb358cbd [file] [log] [blame]
Sieu Mun Tang7bb345c2024-08-26 22:51:16 +08001/*
Jit Loon Lim98f20062025-03-05 10:44:47 +08002 * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
Sieu Mun Tang7bb345c2024-08-26 22:51:16 +08003 *
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 */
83static struct ddr_info ddr_info_set[CONFIG_NR_DRAM_BANKS];
84
85/* Reset type */
86enum 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 */
96static 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 */
103static 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 */
116static 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 */
128static 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
156static 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
166static 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
176static 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
240static 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
285static 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 */
294int 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
Jit Loon Lim98f20062025-03-05 10:44:47 +0800373 /* TODO: To update config_ddr_size by using FDT in the future. */
374 config_ddr_size = 0x80000000;
375 ddr_info_set[0].start = DRAM_BASE;
376 ddr_info_set[0].size = hw_ddr_size;
Sieu Mun Tang7bb345c2024-08-26 22:51:16 +0800377
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}