Prepare v2024.10
[platform/kernel/u-boot.git] / drivers / ddr / altera / sdram_soc64.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2016-2022 Intel Corporation <www.intel.com>
4  *
5  */
6
7 #include <cpu_func.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <div64.h>
11 #include <fdtdec.h>
12 #include <hang.h>
13 #include <init.h>
14 #include <log.h>
15 #include <ram.h>
16 #include <reset.h>
17 #include "sdram_soc64.h"
18 #include <wait_bit.h>
19 #include <asm/arch/firewall.h>
20 #include <asm/arch/system_manager.h>
21 #include <asm/arch/reset_manager.h>
22 #include <asm/cache.h>
23 #include <asm/global_data.h>
24 #include <asm/io.h>
25 #include <dm/device_compat.h>
26 #include <linux/sizes.h>
27
28 #define PGTABLE_OFF     0x4000
29
30 u32 hmc_readl(struct altera_sdram_plat *plat, u32 reg)
31 {
32         return readl(plat->iomhc + reg);
33 }
34
35 u32 hmc_ecc_readl(struct altera_sdram_plat *plat, u32 reg)
36 {
37         return readl(plat->hmc + reg);
38 }
39
40 u32 hmc_ecc_writel(struct altera_sdram_plat *plat,
41                    u32 data, u32 reg)
42 {
43         return writel(data, plat->hmc + reg);
44 }
45
46 u32 ddr_sch_writel(struct altera_sdram_plat *plat, u32 data,
47                    u32 reg)
48 {
49         return writel(data, plat->ddr_sch + reg);
50 }
51
52 int emif_clear(struct altera_sdram_plat *plat)
53 {
54         hmc_ecc_writel(plat, 0, RSTHANDSHAKECTRL);
55
56         return wait_for_bit_le32((const void *)(plat->hmc +
57                                  RSTHANDSHAKESTAT),
58                                  DDR_HMC_RSTHANDSHAKE_MASK,
59                                  false, 1000, false);
60 }
61
62 int emif_reset(struct altera_sdram_plat *plat)
63 {
64         u32 c2s, s2c, ret;
65
66         c2s = hmc_ecc_readl(plat, RSTHANDSHAKECTRL) & DDR_HMC_RSTHANDSHAKE_MASK;
67         s2c = hmc_ecc_readl(plat, RSTHANDSHAKESTAT) & DDR_HMC_RSTHANDSHAKE_MASK;
68
69         debug("DDR: c2s=%08x s2c=%08x nr0=%08x nr1=%08x nr2=%08x dst=%08x\n",
70               c2s, s2c, hmc_readl(plat, NIOSRESERVED0),
71               hmc_readl(plat, NIOSRESERVED1), hmc_readl(plat, NIOSRESERVED2),
72               hmc_readl(plat, DRAMSTS));
73
74         if (s2c && emif_clear(plat)) {
75                 printf("DDR: emif_clear() failed\n");
76                 return -1;
77         }
78
79         debug("DDR: Triggerring emif reset\n");
80         hmc_ecc_writel(plat, DDR_HMC_CORE2SEQ_INT_REQ, RSTHANDSHAKECTRL);
81
82         /* if seq2core[3] = 0, we are good */
83         ret = wait_for_bit_le32((const void *)(plat->hmc +
84                                  RSTHANDSHAKESTAT),
85                                  DDR_HMC_SEQ2CORE_INT_RESP_MASK,
86                                  false, 1000, false);
87         if (ret) {
88                 printf("DDR: failed to get ack from EMIF\n");
89                 return ret;
90         }
91
92         ret = emif_clear(plat);
93         if (ret) {
94                 printf("DDR: emif_clear() failed\n");
95                 return ret;
96         }
97
98         debug("DDR: %s triggered successly\n", __func__);
99         return 0;
100 }
101
102 #if !IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
103 int poll_hmc_clock_status(void)
104 {
105         return wait_for_bit_le32((const void *)(socfpga_get_sysmgr_addr() +
106                                  SYSMGR_SOC64_HMC_CLK),
107                                  SYSMGR_HMC_CLK_STATUS_MSK, true, 1000, false);
108 }
109 #endif
110
111 void sdram_clear_mem(phys_addr_t addr, phys_size_t size)
112 {
113         phys_size_t i;
114
115         if (addr % CONFIG_SYS_CACHELINE_SIZE) {
116                 printf("DDR: address 0x%llx is not cacheline size aligned.\n",
117                        addr);
118                 hang();
119         }
120
121         if (size % CONFIG_SYS_CACHELINE_SIZE) {
122                 printf("DDR: size 0x%llx is not multiple of cacheline size\n",
123                        size);
124                 hang();
125         }
126
127         /* Use DC ZVA instruction to clear memory to zeros by a cache line */
128         for (i = 0; i < size; i = i + CONFIG_SYS_CACHELINE_SIZE) {
129                 asm volatile("dc zva, %0"
130                      :
131                      : "r"(addr)
132                      : "memory");
133                 addr += CONFIG_SYS_CACHELINE_SIZE;
134         }
135 }
136
137 void sdram_init_ecc_bits(struct bd_info *bd)
138 {
139         phys_size_t size, size_init;
140         phys_addr_t start_addr;
141         int bank = 0;
142         unsigned int start = get_timer(0);
143
144         icache_enable();
145
146         start_addr = bd->bi_dram[0].start;
147         size = bd->bi_dram[0].size;
148
149         /* Initialize small block for page table */
150         memset((void *)start_addr, 0, PGTABLE_SIZE + PGTABLE_OFF);
151         gd->arch.tlb_addr = start_addr + PGTABLE_OFF;
152         gd->arch.tlb_size = PGTABLE_SIZE;
153         start_addr += PGTABLE_SIZE + PGTABLE_OFF;
154         size -= (PGTABLE_OFF + PGTABLE_SIZE);
155         dcache_enable();
156
157         while (1) {
158                 while (size) {
159                         size_init = min((phys_addr_t)SZ_1G, (phys_addr_t)size);
160                         sdram_clear_mem(start_addr, size_init);
161                         size -= size_init;
162                         start_addr += size_init;
163                         schedule();
164                 }
165
166                 bank++;
167                 if (bank >= CONFIG_NR_DRAM_BANKS)
168                         break;
169
170                 start_addr = bd->bi_dram[bank].start;
171                 size = bd->bi_dram[bank].size;
172         }
173
174         dcache_disable();
175         icache_disable();
176
177         printf("SDRAM-ECC: Initialized success with %d ms\n",
178                (unsigned int)get_timer(start));
179 }
180
181 void sdram_size_check(struct bd_info *bd)
182 {
183         phys_size_t total_ram_check = 0;
184         phys_size_t ram_check = 0;
185         phys_addr_t start = 0;
186         phys_size_t size, remaining_size;
187         int bank;
188
189         /* Sanity check ensure correct SDRAM size specified */
190         debug("DDR: Running SDRAM size sanity check\n");
191
192         for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
193                 start = bd->bi_dram[bank].start;
194                 remaining_size = bd->bi_dram[bank].size;
195                 while (ram_check < bd->bi_dram[bank].size) {
196                         size = min((phys_addr_t)SZ_1G,
197                                    (phys_addr_t)remaining_size);
198
199                         /*
200                          * Ensure the size is power of two, this is requirement
201                          * to run get_ram_size() / memory test
202                          */
203                         if (size != 0 && ((size & (size - 1)) == 0)) {
204                                 ram_check += get_ram_size((void *)
205                                                 (start + ram_check), size);
206                                 remaining_size = bd->bi_dram[bank].size -
207                                                         ram_check;
208                         } else {
209                                 puts("DDR: Memory test requires SDRAM size ");
210                                 puts("in power of two!\n");
211                                 hang();
212                         }
213                 }
214
215                 total_ram_check += ram_check;
216                 ram_check = 0;
217         }
218
219         /* If the ram_size is 2GB smaller, we can assume the IO space is
220          * not mapped in.  gd->ram_size is the actual size of the dram
221          * not the accessible size.
222          */
223         if (total_ram_check != gd->ram_size) {
224                 puts("DDR: SDRAM size check failed!\n");
225                 hang();
226         }
227
228         debug("DDR: SDRAM size check passed!\n");
229 }
230
231 /**
232  * sdram_calculate_size() - Calculate SDRAM size
233  *
234  * Calculate SDRAM device size based on SDRAM controller parameters.
235  * Size is specified in bytes.
236  */
237 phys_size_t sdram_calculate_size(struct altera_sdram_plat *plat)
238 {
239         u32 dramaddrw = hmc_readl(plat, DRAMADDRW);
240
241         phys_size_t size = (phys_size_t)1 <<
242                         (DRAMADDRW_CFG_CS_ADDR_WIDTH(dramaddrw) +
243                          DRAMADDRW_CFG_BANK_GRP_ADDR_WIDTH(dramaddrw) +
244                          DRAMADDRW_CFG_BANK_ADDR_WIDTH(dramaddrw) +
245                          DRAMADDRW_CFG_ROW_ADDR_WIDTH(dramaddrw) +
246                          DRAMADDRW_CFG_COL_ADDR_WIDTH(dramaddrw));
247
248         size *= (2 << (hmc_ecc_readl(plat, DDRIOCTRL) &
249                         DDR_HMC_DDRIOCTRL_IOSIZE_MSK));
250
251         return size;
252 }
253
254 void sdram_set_firewall(struct bd_info *bd)
255 {
256         u32 i;
257         phys_size_t value;
258         u32 lower, upper;
259
260         for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
261                 if (!bd->bi_dram[i].size)
262                         continue;
263
264                 value = bd->bi_dram[i].start;
265
266                 /* Keep first 1MB of SDRAM memory region as secure region when
267                  * using ATF flow, where the ATF code is located.
268                  */
269                 if (IS_ENABLED(CONFIG_SPL_ATF) && i == 0)
270                         value += SZ_1M;
271
272                 /* Setting non-secure MPU region base and base extended */
273                 lower = lower_32_bits(value);
274                 upper = upper_32_bits(value);
275                 FW_MPU_DDR_SCR_WRITEL(lower,
276                                       FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE +
277                                       (i * 4 * sizeof(u32)));
278                 FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
279                                       FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT +
280                                       (i * 4 * sizeof(u32)));
281
282                 /* Setting non-secure Non-MPU region base and base extended */
283                 FW_MPU_DDR_SCR_WRITEL(lower,
284                                       FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE +
285                                       (i * 4 * sizeof(u32)));
286                 FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
287                                       FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT +
288                                       (i * 4 * sizeof(u32)));
289
290                 /* Setting non-secure MPU limit and limit extexded */
291                 value = bd->bi_dram[i].start + bd->bi_dram[i].size - 1;
292
293                 lower = lower_32_bits(value);
294                 upper = upper_32_bits(value);
295
296                 FW_MPU_DDR_SCR_WRITEL(lower,
297                                       FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT +
298                                       (i * 4 * sizeof(u32)));
299                 FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
300                                       FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT +
301                                       (i * 4 * sizeof(u32)));
302
303                 /* Setting non-secure Non-MPU limit and limit extexded */
304                 FW_MPU_DDR_SCR_WRITEL(lower,
305                                       FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT +
306                                       (i * 4 * sizeof(u32)));
307                 FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
308                                       FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT +
309                                       (i * 4 * sizeof(u32)));
310
311                 FW_MPU_DDR_SCR_WRITEL(BIT(i) | BIT(i + 8),
312                                       FW_MPU_DDR_SCR_EN_SET);
313         }
314 }
315
316 static int altera_sdram_of_to_plat(struct udevice *dev)
317 {
318         struct altera_sdram_plat *plat = dev_get_plat(dev);
319         fdt_addr_t addr;
320
321         /* These regs info are part of DDR handoff in bitstream */
322 #if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
323         return 0;
324 #endif
325
326         addr = dev_read_addr_index(dev, 0);
327         if (addr == FDT_ADDR_T_NONE)
328                 return -EINVAL;
329         plat->ddr_sch = (void __iomem *)addr;
330
331         addr = dev_read_addr_index(dev, 1);
332         if (addr == FDT_ADDR_T_NONE)
333                 return -EINVAL;
334         plat->iomhc = (void __iomem *)addr;
335
336         addr = dev_read_addr_index(dev, 2);
337         if (addr == FDT_ADDR_T_NONE)
338                 return -EINVAL;
339         plat->hmc = (void __iomem *)addr;
340
341         return 0;
342 }
343
344 static int altera_sdram_probe(struct udevice *dev)
345 {
346         int ret;
347         struct altera_sdram_priv *priv = dev_get_priv(dev);
348
349         ret = reset_get_bulk(dev, &priv->resets);
350         if (ret) {
351                 dev_err(dev, "Can't get reset: %d\n", ret);
352                 return -ENODEV;
353         }
354         reset_deassert_bulk(&priv->resets);
355
356         if (sdram_mmr_init_full(dev) != 0) {
357                 puts("SDRAM init failed.\n");
358                 goto failed;
359         }
360
361         return 0;
362
363 failed:
364         reset_release_bulk(&priv->resets);
365         return -ENODEV;
366 }
367
368 static int altera_sdram_get_info(struct udevice *dev,
369                                  struct ram_info *info)
370 {
371         struct altera_sdram_priv *priv = dev_get_priv(dev);
372
373         info->base = priv->info.base;
374         info->size = priv->info.size;
375
376         return 0;
377 }
378
379 static struct ram_ops altera_sdram_ops = {
380         .get_info = altera_sdram_get_info,
381 };
382
383 static const struct udevice_id altera_sdram_ids[] = {
384         { .compatible = "altr,sdr-ctl-s10" },
385         { .compatible = "intel,sdr-ctl-agilex" },
386         { .compatible = "intel,sdr-ctl-n5x" },
387         { /* sentinel */ }
388 };
389
390 U_BOOT_DRIVER(altera_sdram) = {
391         .name = "altr_sdr_ctl",
392         .id = UCLASS_RAM,
393         .of_match = altera_sdram_ids,
394         .ops = &altera_sdram_ops,
395         .of_to_plat = altera_sdram_of_to_plat,
396         .plat_auto      = sizeof(struct altera_sdram_plat),
397         .probe = altera_sdram_probe,
398         .priv_auto      = sizeof(struct altera_sdram_priv),
399 };