blob: ee66c72157a628d088ea43f6d8e30e3e9e085a20 [file] [log] [blame]
Tingting Menga1a24f12025-02-21 21:49:41 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2025 Altera Corporation <www.altera.com>
4 *
5 */
6
7#include <stdlib.h>
8#include <div64.h>
9#include <dm.h>
10#include <errno.h>
11#include <fdtdec.h>
12#include <hang.h>
13#include <log.h>
14#include <ram.h>
15#include <reset.h>
16#include <wait_bit.h>
17#include <wdt.h>
18#include <linux/bitfield.h>
19#include <linux/sizes.h>
20#include <asm/arch/firewall.h>
21#include <asm/arch/reset_manager.h>
22#include <asm/arch/system_manager.h>
23#include <asm/global_data.h>
24#include <asm/io.h>
25#include "iossm_mailbox.h"
26#include "sdram_soc64.h"
27
28DECLARE_GLOBAL_DATA_PTR;
29
30/* MPFE NOC registers */
31#define F2SDRAM_SIDEBAND_FLAGOUTSET0 0x50
32#define F2SDRAM_SIDEBAND_FLAGOUTSTATUS0 0x58
33#define SIDEBANDMGR_FLAGOUTSET0_REG SOCFPGA_F2SDRAM_MGR_ADDRESS +\
34 F2SDRAM_SIDEBAND_FLAGOUTSET0
35#define SIDEBANDMGR_FLAGOUTSTATUS0_REG SOCFPGA_F2SDRAM_MGR_ADDRESS +\
36 F2SDRAM_SIDEBAND_FLAGOUTSTATUS0
37#define BOOT_SCRATCH_COLD3_REG (socfpga_get_sysmgr_addr() +\
38 SYSMGR_SOC64_BOOT_SCRATCH_COLD3)
39#define PORT_EMIF_CONFIG_OFFSET 4
40#define EMIF_PLL_MASK GENMASK(19, 16)
41
42#define IO96B0_DUAL_PORT_MASK BIT(0)
43#define IO96B0_DUAL_EMIF_MASK BIT(1)
44
45#define FIREWALL_MPFE_SCR_IO96B0_REG 0x18000d00
46#define FIREWALL_MPFE_SCR_IO96B1_REG 0x18000d04
47#define FIREWALL_MPFE_NOC_CSR_REG 0x18000d08
48
49#define MEMORY_BANK_MAX_COUNT 3
50
51/* Reset type */
52enum reset_type {
53 POR_RESET,
54 WARM_RESET,
55 COLD_RESET,
56 NCONFIG,
57 JTAG_CONFIG,
58 RSU_RECONFIG
59};
60
61phys_addr_t io96b_csr_reg_addr[] = {
62 0x18400000, /* IO96B_0 CSR registers address */
63 0x18800000 /* IO96B_1 CSR registers address */
64};
65
66struct dram_bank_info_s {
67 phys_addr_t start;
68 phys_size_t max_size;
69};
70
71struct dram_bank_info_s dram_bank_info[MEMORY_BANK_MAX_COUNT] = {
72 {0x80000000, 0x80000000}, /* Memory Bank 0 */
73 {0x880000000, 0x780000000}, /* Memory Bank 1 */
74 {0x8800000000, 0x7800000000} /* Memory Bank 2 */
75};
76
77static enum reset_type get_reset_type(u32 reg)
78{
79 return FIELD_GET(ALT_SYSMGR_SCRATCH_REG_3_DDR_RESET_TYPE_MASK, reg);
80}
81
82static void update_io96b_assigned_to_hps(bool dual_port_flag, bool dual_emif_flag)
83{
84 clrsetbits_le32(BOOT_SCRATCH_COLD3_REG,
85 ALT_SYSMGR_SCRATCH_REG_3_DDR_PORT_EMIF_INFO_MASK,
86 FIELD_PREP(ALT_SYSMGR_SCRATCH_REG_3_DDR_PORT_INFO_MASK, dual_port_flag) |
87 FIELD_PREP(ALT_SYSMGR_SCRATCH_REG_3_DDR_EMIF_INFO_MASK, dual_emif_flag));
88
89 debug("%s: update dual port dual emif info: 0x%x\n", __func__,
90 readl(BOOT_SCRATCH_COLD3_REG));
91}
92
93static void set_mpfe_config(void)
94{
95 /* Set mpfe_lite_intfcsel */
96 setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_MPFE_CONFIG, BIT(2));
97
98 /* Set mpfe_lite_active */
99 setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_MPFE_CONFIG, BIT(8));
100
101 debug("%s: mpfe_config: 0x%x\n", __func__,
102 readl(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_MPFE_CONFIG));
103}
104
105static bool is_ddr_init_hang(void)
106{
107 u32 reg = readl(socfpga_get_sysmgr_addr() +
108 SYSMGR_SOC64_BOOT_SCRATCH_POR0);
109
110 debug("%s: 0x%x\n", __func__, reg);
111
112 if (reg & ALT_SYSMGR_SCRATCH_REG_POR_0_DDR_PROGRESS_MASK)
113 return true;
114
115 return false;
116}
117
118static void ddr_init_inprogress(bool start)
119{
120 if (start)
121 setbits_le32(socfpga_get_sysmgr_addr() +
122 SYSMGR_SOC64_BOOT_SCRATCH_POR0,
123 ALT_SYSMGR_SCRATCH_REG_POR_0_DDR_PROGRESS_MASK);
124 else
125 clrbits_le32(socfpga_get_sysmgr_addr() +
126 SYSMGR_SOC64_BOOT_SCRATCH_POR0,
127 ALT_SYSMGR_SCRATCH_REG_POR_0_DDR_PROGRESS_MASK);
128}
129
130static void populate_ddr_handoff(struct udevice *dev, struct io96b_info *io96b_ctrl)
131{
132 struct altera_sdram_plat *plat = dev_get_plat(dev);
133 int i;
134 u32 len = SOC64_HANDOFF_SDRAM_LEN;
135 u32 handoff_table[len];
136
137 /* Read handoff for DDR configuration */
138 socfpga_handoff_read((void *)SOC64_HANDOFF_SDRAM, handoff_table, len);
139
140 /* Read handoff - dual port */
141 plat->dualport = FIELD_GET(IO96B0_DUAL_PORT_MASK, handoff_table[PORT_EMIF_CONFIG_OFFSET]);
142 debug("%s: dualport from handoff: 0x%x\n", __func__, plat->dualport);
143
144 if (plat->dualport)
145 io96b_ctrl->num_port = 2;
146 else
147 io96b_ctrl->num_port = 1;
148
149 /* Read handoff - dual EMIF */
150 plat->dualemif = FIELD_GET(IO96B0_DUAL_EMIF_MASK, handoff_table[PORT_EMIF_CONFIG_OFFSET]);
151 debug("%s: dualemif from handoff: 0x%x\n", __func__, plat->dualemif);
152
153 if (plat->dualemif)
154 io96b_ctrl->num_instance = 2;
155 else
156 io96b_ctrl->num_instance = 1;
157
158 io96b_ctrl->io96b_pll = FIELD_GET(EMIF_PLL_MASK,
159 handoff_table[PORT_EMIF_CONFIG_OFFSET]);
160 debug("%s: io96b enabled pll from handoff: 0x%x\n", __func__, io96b_ctrl->io96b_pll);
161
162 update_io96b_assigned_to_hps(plat->dualport, plat->dualemif);
163
164 /* Assign IO96B CSR base address if it is valid */
165 for (i = 0; i < io96b_ctrl->num_instance; i++) {
166 io96b_ctrl->io96b[i].io96b_csr_addr = io96b_csr_reg_addr[i];
167 debug("%s: IO96B 0x%llx CSR enabled\n", __func__,
168 io96b_ctrl->io96b[i].io96b_csr_addr);
169 }
170}
171
172static void config_mpfe_sideband_mgr(struct udevice *dev)
173{
174 struct altera_sdram_plat *plat = dev_get_plat(dev);
175
176 /* Dual port setting */
177 if (plat->dualport)
178 setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(4));
179
180 /* Dual EMIF setting */
181 if (plat->dualemif) {
182 set_mpfe_config();
183 setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(5));
184 }
185
186 debug("%s: SIDEBANDMGR_FLAGOUTSTATUS0: 0x%x\n", __func__,
187 readl(SIDEBANDMGR_FLAGOUTSTATUS0_REG));
188}
189
190static void config_ccu_mgr(struct udevice *dev)
191{
192 int ret = 0;
193 struct altera_sdram_plat *plat = dev_get_plat(dev);
194
195 if (plat->dualport || plat->dualemif) {
196 debug("%s: config interleaving on ccu reg\n", __func__);
197 ret = uclass_get_device_by_name(UCLASS_NOP,
198 "socfpga-ccu-ddr-interleaving-on", &dev);
199 } else {
200 debug("%s: config interleaving off ccu reg\n", __func__);
201 ret = uclass_get_device_by_name(UCLASS_NOP,
202 "socfpga-ccu-ddr-interleaving-off", &dev);
203 }
204
205 if (ret) {
206 printf("interleaving on/off ccu settings init failed: %d\n", ret);
207 hang();
208 }
209}
210
211static void config_firewall_mpfe_csr(struct udevice *dev)
212{
213 int ret = 0;
214
215 debug("%s: config Firewall setting for MPFE CSR\n", __func__);
216 ret = uclass_get_device_by_name(UCLASS_NOP,
217 "socfpga-noc-fw-mpfe-csr", &dev);
218
219 if (ret) {
220 printf("Firewall setting for MPFE CSR init failed: %d\n", ret);
221 hang();
222 }
223}
224
225static bool hps_ocram_dbe_status(void)
226{
227 u32 reg = readl(BOOT_SCRATCH_COLD3_REG);
228
229 if (reg & ALT_SYSMGR_SCRATCH_REG_3_OCRAM_DBE_MASK)
230 return true;
231
232 return false;
233}
234
235int sdram_mmr_init_full(struct udevice *dev)
236{
237 int i, ret = 0;
238 phys_size_t hw_size;
239 struct altera_sdram_plat *plat = dev_get_plat(dev);
240 struct altera_sdram_priv *priv = dev_get_priv(dev);
241 struct io96b_info *io96b_ctrl = malloc(sizeof(*io96b_ctrl));
242
243 u32 reg = readl(BOOT_SCRATCH_COLD3_REG);
244 enum reset_type reset_t = get_reset_type(reg);
245 bool full_mem_init = false;
246
247 /* DDR initialization progress status tracking */
248 bool is_ddr_hang_be4_rst = is_ddr_init_hang();
249
250 debug("DDR: SDRAM init in progress ...\n");
251 ddr_init_inprogress(true);
252
253 gd->bd = (struct bd_info *)malloc(sizeof(struct bd_info));
254 memset(gd->bd, '\0', sizeof(struct bd_info));
255
256 debug("DDR: Address MPFE 0x%llx\n", plat->mpfe_base_addr);
257
258 /* Populating DDR handoff data */
259 debug("DDR: Checking SDRAM configuration in progress ...\n");
260 populate_ddr_handoff(dev, io96b_ctrl);
261
262 /* Configuring MPFE sideband manager registers - dual port & dual emif */
263 config_mpfe_sideband_mgr(dev);
264
265 /* Configuring Interleave/Non-interleave ccu registers */
266 config_ccu_mgr(dev);
267
268 /* Configure if polling is needed for IO96B GEN PLL locked */
269 io96b_ctrl->ckgen_lock = true;
270
271 /* Ensure calibration status passing */
272 init_mem_cal(io96b_ctrl);
273
274 printf("DDR: Calibration success\n");
275
276 /* Initiate IOSSM mailbox */
277 io96b_mb_init(io96b_ctrl);
278
279 /* DDR type, DDR size and ECC status) */
280 ret = get_mem_technology(io96b_ctrl);
281 if (ret) {
282 printf("DDR: Failed to get DDR type\n");
283
284 goto err;
285 }
286
287 ret = get_mem_width_info(io96b_ctrl);
288 if (ret) {
289 printf("DDR: Failed to get DDR size\n");
290
291 goto err;
292 }
293
Tingting Mengdc6c9272025-04-15 14:50:51 +0800294 ret = ecc_enable_status(io96b_ctrl);
295 if (ret) {
296 printf("DDR: Failed to get ECC enabled status\n");
297
298 goto err;
299 }
300
301 hw_size = io96b_ctrl->overall_size;
Tingting Menga1a24f12025-02-21 21:49:41 +0800302
303 /* Get bank configuration from devicetree */
304 ret = fdtdec_decode_ram_size(gd->fdt_blob, NULL, 0, NULL,
305 (phys_size_t *)&gd->ram_size, gd->bd);
306 if (ret) {
307 puts("DDR: Failed to decode memory node\n");
308 ret = -ENXIO;
309
310 goto err;
311 }
312
Tingting Mengdc6c9272025-04-15 14:50:51 +0800313 if (io96b_ctrl->inline_ecc)
314 hw_size = CALC_INLINE_ECC_HW_SIZE(hw_size);
315
Tingting Menga1a24f12025-02-21 21:49:41 +0800316 if (gd->ram_size > hw_size) {
317 printf("DDR: Warning: DRAM size from device tree (%lld MiB) exceeds\n",
318 gd->ram_size >> 20);
319 printf(" the actual hardware capacity(%lld MiB). Memory configuration will be\n",
320 hw_size >> 20);
321 printf(" adjusted to match the detected hardware size.\n");
322 gd->ram_size = 0;
323 }
324
325 if (gd->ram_size > 0 && gd->ram_size != hw_size) {
326 printf("DDR: Warning: DRAM size from device tree (%lld MiB)\n",
327 gd->ram_size >> 20);
328 printf(" mismatch with hardware capacity(%lld MiB).\n",
329 hw_size >> 20);
330 }
331
332 if (gd->ram_size == 0 && hw_size > 0) {
333 phys_size_t remaining_size, size_counter = 0;
334 u8 config_dram_banks;
335
336 if (CONFIG_NR_DRAM_BANKS > MEMORY_BANK_MAX_COUNT) {
337 printf("DDR: Warning: CONFIG_NR_DRAM_BANKS(%d) is bigger than Max Memory Bank count(%d).\n",
338 CONFIG_NR_DRAM_BANKS, MEMORY_BANK_MAX_COUNT);
339 printf(" Max Memory Bank count is in use instead of CONFIG_NR_DRAM_BANKS.\n");
340 config_dram_banks = MEMORY_BANK_MAX_COUNT;
341 } else {
342 config_dram_banks = CONFIG_NR_DRAM_BANKS;
343 }
344
345 for (i = 0; i < config_dram_banks; i++) {
346 remaining_size = hw_size - size_counter;
347 if (remaining_size <= dram_bank_info[i].max_size) {
348 gd->bd->bi_dram[i].start = dram_bank_info[i].start;
349 gd->bd->bi_dram[i].size = remaining_size;
350 debug("Memory bank[%d] Starting address: 0x%llx size: 0x%llx\n",
351 i, gd->bd->bi_dram[i].start, gd->bd->bi_dram[i].size);
352 break;
353 }
354
355 gd->bd->bi_dram[i].start = dram_bank_info[i].start;
356 gd->bd->bi_dram[i].size = dram_bank_info[i].max_size;
357
358 debug("Memory bank[%d] Starting address: 0x%llx size: 0x%llx\n",
359 i, gd->bd->bi_dram[i].start, gd->bd->bi_dram[i].size);
360 size_counter += gd->bd->bi_dram[i].size;
361 }
362
363 gd->ram_size = hw_size;
364 }
365
366 printf("%s: %lld MiB\n", io96b_ctrl->ddr_type, gd->ram_size >> 20);
367
Tingting Menga1a24f12025-02-21 21:49:41 +0800368 /* Is HPS cold or warm reset? If yes, Skip full memory initialization if ECC
369 * enabled to preserve memory content
370 */
371 if (io96b_ctrl->ecc_status) {
372 if (ecc_interrupt_status(io96b_ctrl)) {
373 if (CONFIG_IS_ENABLED(WDT)) {
374 struct udevice *wdt;
375
376 printf("DDR: ECC error recover start now\n");
377 ret = uclass_first_device_err(UCLASS_WDT, &wdt);
378 if (ret) {
379 printf("DDR: Failed to trigger watchdog reset\n");
380 hang();
381 }
382
383 wdt_expire_now(wdt, 0);
384 }
385 hang();
386 }
387
388 full_mem_init = hps_ocram_dbe_status() | is_ddr_hang_be4_rst;
389 if (full_mem_init || !(reset_t == WARM_RESET || reset_t == COLD_RESET)) {
390 ret = bist_mem_init_start(io96b_ctrl);
391 if (ret) {
392 printf("DDR: Failed to fully initialize DDR memory\n");
393
394 goto err;
395 }
396 }
397
398 printf("SDRAM-ECC: Initialized success\n");
399 }
400
401 sdram_size_check(gd->bd);
402 printf("DDR: size check success\n");
403
404 sdram_set_firewall(gd->bd);
405
406 /* Firewall setting for MPFE CSR */
407 config_firewall_mpfe_csr(dev);
408
409 printf("DDR: firewall init success\n");
410
411 priv->info.base = gd->bd->bi_dram[0].start;
412 priv->info.size = gd->ram_size;
413
414 /* Ending DDR driver initialization success tracking */
415 ddr_init_inprogress(false);
416
417 printf("DDR: init success\n");
418
419err:
420 free(io96b_ctrl);
421
422 return ret;
423}