1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2016-2019 Intel Corporation <www.intel.com>
16 #include "sdram_soc64.h"
18 #include <asm/arch/firewall.h>
19 #include <asm/arch/system_manager.h>
20 #include <asm/arch/reset_manager.h>
21 #include <asm/cache.h>
23 #include <dm/device_compat.h>
24 #include <linux/sizes.h>
26 #define PGTABLE_OFF 0x4000
28 u32 hmc_readl(struct altera_sdram_platdata *plat, u32 reg)
30 return readl(plat->iomhc + reg);
33 u32 hmc_ecc_readl(struct altera_sdram_platdata *plat, u32 reg)
35 return readl(plat->hmc + reg);
38 u32 hmc_ecc_writel(struct altera_sdram_platdata *plat,
41 return writel(data, plat->hmc + reg);
44 u32 ddr_sch_writel(struct altera_sdram_platdata *plat, u32 data,
47 return writel(data, plat->ddr_sch + reg);
50 int emif_clear(struct altera_sdram_platdata *plat)
52 hmc_ecc_writel(plat, 0, RSTHANDSHAKECTRL);
54 return wait_for_bit_le32((const void *)(plat->hmc +
56 DDR_HMC_RSTHANDSHAKE_MASK,
60 int emif_reset(struct altera_sdram_platdata *plat)
64 c2s = hmc_ecc_readl(plat, RSTHANDSHAKECTRL) & DDR_HMC_RSTHANDSHAKE_MASK;
65 s2c = hmc_ecc_readl(plat, RSTHANDSHAKESTAT) & DDR_HMC_RSTHANDSHAKE_MASK;
67 debug("DDR: c2s=%08x s2c=%08x nr0=%08x nr1=%08x nr2=%08x dst=%08x\n",
68 c2s, s2c, hmc_readl(plat, NIOSRESERVED0),
69 hmc_readl(plat, NIOSRESERVED1), hmc_readl(plat, NIOSRESERVED2),
70 hmc_readl(plat, DRAMSTS));
72 if (s2c && emif_clear(plat)) {
73 printf("DDR: emif_clear() failed\n");
77 debug("DDR: Triggerring emif reset\n");
78 hmc_ecc_writel(plat, DDR_HMC_CORE2SEQ_INT_REQ, RSTHANDSHAKECTRL);
80 /* if seq2core[3] = 0, we are good */
81 ret = wait_for_bit_le32((const void *)(plat->hmc +
83 DDR_HMC_SEQ2CORE_INT_RESP_MASK,
86 printf("DDR: failed to get ack from EMIF\n");
90 ret = emif_clear(plat);
92 printf("DDR: emif_clear() failed\n");
96 debug("DDR: %s triggered successly\n", __func__);
100 int poll_hmc_clock_status(void)
102 return wait_for_bit_le32((const void *)(socfpga_get_sysmgr_addr() +
103 SYSMGR_SOC64_HMC_CLK),
104 SYSMGR_HMC_CLK_STATUS_MSK, true, 1000, false);
107 void sdram_clear_mem(phys_addr_t addr, phys_size_t size)
111 if (addr % CONFIG_SYS_CACHELINE_SIZE) {
112 printf("DDR: address 0x%llx is not cacheline size aligned.\n",
117 if (size % CONFIG_SYS_CACHELINE_SIZE) {
118 printf("DDR: size 0x%llx is not multiple of cacheline size\n",
123 /* Use DC ZVA instruction to clear memory to zeros by a cache line */
124 for (i = 0; i < size; i = i + CONFIG_SYS_CACHELINE_SIZE) {
125 asm volatile("dc zva, %0"
129 addr += CONFIG_SYS_CACHELINE_SIZE;
133 void sdram_init_ecc_bits(bd_t *bd)
135 phys_size_t size, size_init;
136 phys_addr_t start_addr;
138 unsigned int start = get_timer(0);
142 start_addr = bd->bi_dram[0].start;
143 size = bd->bi_dram[0].size;
145 /* Initialize small block for page table */
146 memset((void *)start_addr, 0, PGTABLE_SIZE + PGTABLE_OFF);
147 gd->arch.tlb_addr = start_addr + PGTABLE_OFF;
148 gd->arch.tlb_size = PGTABLE_SIZE;
149 start_addr += PGTABLE_SIZE + PGTABLE_OFF;
150 size -= (PGTABLE_OFF + PGTABLE_SIZE);
155 size_init = min((phys_addr_t)SZ_1G, (phys_addr_t)size);
156 sdram_clear_mem(start_addr, size_init);
158 start_addr += size_init;
163 if (bank >= CONFIG_NR_DRAM_BANKS)
166 start_addr = bd->bi_dram[bank].start;
167 size = bd->bi_dram[bank].size;
173 printf("SDRAM-ECC: Initialized success with %d ms\n",
174 (unsigned int)get_timer(start));
177 void sdram_size_check(bd_t *bd)
179 phys_size_t total_ram_check = 0;
180 phys_size_t ram_check = 0;
181 phys_addr_t start = 0;
184 /* Sanity check ensure correct SDRAM size specified */
185 debug("DDR: Running SDRAM size sanity check\n");
187 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
188 start = bd->bi_dram[bank].start;
189 while (ram_check < bd->bi_dram[bank].size) {
190 ram_check += get_ram_size((void *)(start + ram_check),
193 total_ram_check += ram_check;
197 /* If the ram_size is 2GB smaller, we can assume the IO space is
198 * not mapped in. gd->ram_size is the actual size of the dram
199 * not the accessible size.
201 if (total_ram_check != gd->ram_size) {
202 puts("DDR: SDRAM size check failed!\n");
206 debug("DDR: SDRAM size check passed!\n");
210 * sdram_calculate_size() - Calculate SDRAM size
212 * Calculate SDRAM device size based on SDRAM controller parameters.
213 * Size is specified in bytes.
215 phys_size_t sdram_calculate_size(struct altera_sdram_platdata *plat)
217 u32 dramaddrw = hmc_readl(plat, DRAMADDRW);
219 phys_size_t size = 1 << (DRAMADDRW_CFG_CS_ADDR_WIDTH(dramaddrw) +
220 DRAMADDRW_CFG_BANK_GRP_ADDR_WIDTH(dramaddrw) +
221 DRAMADDRW_CFG_BANK_ADDR_WIDTH(dramaddrw) +
222 DRAMADDRW_CFG_ROW_ADDR_WIDTH(dramaddrw) +
223 DRAMADDRW_CFG_COL_ADDR_WIDTH(dramaddrw));
225 size *= (2 << (hmc_ecc_readl(plat, DDRIOCTRL) &
226 DDR_HMC_DDRIOCTRL_IOSIZE_MSK));
231 static int altera_sdram_ofdata_to_platdata(struct udevice *dev)
233 struct altera_sdram_platdata *plat = dev->platdata;
236 addr = dev_read_addr_index(dev, 0);
237 if (addr == FDT_ADDR_T_NONE)
239 plat->ddr_sch = (void __iomem *)addr;
241 addr = dev_read_addr_index(dev, 1);
242 if (addr == FDT_ADDR_T_NONE)
244 plat->iomhc = (void __iomem *)addr;
246 addr = dev_read_addr_index(dev, 2);
247 if (addr == FDT_ADDR_T_NONE)
249 plat->hmc = (void __iomem *)addr;
254 static int altera_sdram_probe(struct udevice *dev)
257 struct altera_sdram_priv *priv = dev_get_priv(dev);
259 ret = reset_get_bulk(dev, &priv->resets);
261 dev_err(dev, "Can't get reset: %d\n", ret);
264 reset_deassert_bulk(&priv->resets);
266 if (sdram_mmr_init_full(dev) != 0) {
267 puts("SDRAM init failed.\n");
274 reset_release_bulk(&priv->resets);
278 static int altera_sdram_get_info(struct udevice *dev,
279 struct ram_info *info)
281 struct altera_sdram_priv *priv = dev_get_priv(dev);
283 info->base = priv->info.base;
284 info->size = priv->info.size;
289 static struct ram_ops altera_sdram_ops = {
290 .get_info = altera_sdram_get_info,
293 static const struct udevice_id altera_sdram_ids[] = {
294 { .compatible = "altr,sdr-ctl-s10" },
295 { .compatible = "intel,sdr-ctl-agilex" },
299 U_BOOT_DRIVER(altera_sdram) = {
300 .name = "altr_sdr_ctl",
302 .of_match = altera_sdram_ids,
303 .ops = &altera_sdram_ops,
304 .ofdata_to_platdata = altera_sdram_ofdata_to_platdata,
305 .platdata_auto_alloc_size = sizeof(struct altera_sdram_platdata),
306 .probe = altera_sdram_probe,
307 .priv_auto_alloc_size = sizeof(struct altera_sdram_priv),