blob: 1f7ead0c674798ca4eb82d6e636f42a5ab3f267c [file] [log] [blame]
Ley Foon Tan25572cf2019-11-27 15:55:26 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2016-2019 Intel Corporation <www.intel.com>
4 *
5 */
6
7#include <common.h>
8#include <cpu_func.h>
9#include <dm.h>
10#include <errno.h>
11#include <div64.h>
12#include <fdtdec.h>
Simon Glassf11478f2019-12-28 10:45:07 -070013#include <hang.h>
Ley Foon Tan25572cf2019-11-27 15:55:26 +080014#include <ram.h>
15#include <reset.h>
16#include "sdram_soc64.h"
17#include <wait_bit.h>
18#include <asm/arch/firewall.h>
19#include <asm/arch/system_manager.h>
20#include <asm/arch/reset_manager.h>
21#include <asm/io.h>
Simon Glass9bc15642020-02-03 07:36:16 -070022#include <dm/device_compat.h>
Ley Foon Tan25572cf2019-11-27 15:55:26 +080023#include <linux/sizes.h>
24
25#define PGTABLE_OFF 0x4000
26
27u32 hmc_readl(struct altera_sdram_platdata *plat, u32 reg)
28{
29 return readl(plat->iomhc + reg);
30}
31
32u32 hmc_ecc_readl(struct altera_sdram_platdata *plat, u32 reg)
33{
34 return readl(plat->hmc + reg);
35}
36
37u32 hmc_ecc_writel(struct altera_sdram_platdata *plat,
38 u32 data, u32 reg)
39{
40 return writel(data, plat->hmc + reg);
41}
42
43u32 ddr_sch_writel(struct altera_sdram_platdata *plat, u32 data,
44 u32 reg)
45{
46 return writel(data, plat->ddr_sch + reg);
47}
48
49int emif_clear(struct altera_sdram_platdata *plat)
50{
51 hmc_ecc_writel(plat, 0, RSTHANDSHAKECTRL);
52
53 return wait_for_bit_le32((const void *)(plat->hmc +
54 RSTHANDSHAKESTAT),
55 DDR_HMC_RSTHANDSHAKE_MASK,
56 false, 1000, false);
57}
58
59int emif_reset(struct altera_sdram_platdata *plat)
60{
61 u32 c2s, s2c, ret;
62
63 c2s = hmc_ecc_readl(plat, RSTHANDSHAKECTRL) & DDR_HMC_RSTHANDSHAKE_MASK;
64 s2c = hmc_ecc_readl(plat, RSTHANDSHAKESTAT) & DDR_HMC_RSTHANDSHAKE_MASK;
65
66 debug("DDR: c2s=%08x s2c=%08x nr0=%08x nr1=%08x nr2=%08x dst=%08x\n",
67 c2s, s2c, hmc_readl(plat, NIOSRESERVED0),
68 hmc_readl(plat, NIOSRESERVED1), hmc_readl(plat, NIOSRESERVED2),
69 hmc_readl(plat, DRAMSTS));
70
71 if (s2c && emif_clear(plat)) {
72 printf("DDR: emif_clear() failed\n");
73 return -1;
74 }
75
76 debug("DDR: Triggerring emif reset\n");
77 hmc_ecc_writel(plat, DDR_HMC_CORE2SEQ_INT_REQ, RSTHANDSHAKECTRL);
78
79 /* if seq2core[3] = 0, we are good */
80 ret = wait_for_bit_le32((const void *)(plat->hmc +
81 RSTHANDSHAKESTAT),
82 DDR_HMC_SEQ2CORE_INT_RESP_MASK,
83 false, 1000, false);
84 if (ret) {
85 printf("DDR: failed to get ack from EMIF\n");
86 return ret;
87 }
88
89 ret = emif_clear(plat);
90 if (ret) {
91 printf("DDR: emif_clear() failed\n");
92 return ret;
93 }
94
95 debug("DDR: %s triggered successly\n", __func__);
96 return 0;
97}
98
99int poll_hmc_clock_status(void)
100{
101 return wait_for_bit_le32((const void *)(socfpga_get_sysmgr_addr() +
102 SYSMGR_SOC64_HMC_CLK),
103 SYSMGR_HMC_CLK_STATUS_MSK, true, 1000, false);
104}
105
106void sdram_clear_mem(phys_addr_t addr, phys_size_t size)
107{
108 phys_size_t i;
109
110 if (addr % CONFIG_SYS_CACHELINE_SIZE) {
111 printf("DDR: address 0x%llx is not cacheline size aligned.\n",
112 addr);
113 hang();
114 }
115
116 if (size % CONFIG_SYS_CACHELINE_SIZE) {
117 printf("DDR: size 0x%llx is not multiple of cacheline size\n",
118 size);
119 hang();
120 }
121
122 /* Use DC ZVA instruction to clear memory to zeros by a cache line */
123 for (i = 0; i < size; i = i + CONFIG_SYS_CACHELINE_SIZE) {
124 asm volatile("dc zva, %0"
125 :
126 : "r"(addr)
127 : "memory");
128 addr += CONFIG_SYS_CACHELINE_SIZE;
129 }
130}
131
132void sdram_init_ecc_bits(bd_t *bd)
133{
134 phys_size_t size, size_init;
135 phys_addr_t start_addr;
136 int bank = 0;
137 unsigned int start = get_timer(0);
138
139 icache_enable();
140
141 start_addr = bd->bi_dram[0].start;
142 size = bd->bi_dram[0].size;
143
144 /* Initialize small block for page table */
145 memset((void *)start_addr, 0, PGTABLE_SIZE + PGTABLE_OFF);
146 gd->arch.tlb_addr = start_addr + PGTABLE_OFF;
147 gd->arch.tlb_size = PGTABLE_SIZE;
148 start_addr += PGTABLE_SIZE + PGTABLE_OFF;
149 size -= (PGTABLE_OFF + PGTABLE_SIZE);
150 dcache_enable();
151
152 while (1) {
153 while (size) {
154 size_init = min((phys_addr_t)SZ_1G, (phys_addr_t)size);
155 sdram_clear_mem(start_addr, size_init);
156 size -= size_init;
157 start_addr += size_init;
158 WATCHDOG_RESET();
159 }
160
161 bank++;
162 if (bank >= CONFIG_NR_DRAM_BANKS)
163 break;
164
165 start_addr = bd->bi_dram[bank].start;
166 size = bd->bi_dram[bank].size;
167 }
168
169 dcache_disable();
170 icache_disable();
171
172 printf("SDRAM-ECC: Initialized success with %d ms\n",
173 (unsigned int)get_timer(start));
174}
175
176void sdram_size_check(bd_t *bd)
177{
178 phys_size_t total_ram_check = 0;
179 phys_size_t ram_check = 0;
180 phys_addr_t start = 0;
181 int bank;
182
183 /* Sanity check ensure correct SDRAM size specified */
184 debug("DDR: Running SDRAM size sanity check\n");
185
186 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
187 start = bd->bi_dram[bank].start;
188 while (ram_check < bd->bi_dram[bank].size) {
189 ram_check += get_ram_size((void *)(start + ram_check),
190 (phys_size_t)SZ_1G);
191 }
192 total_ram_check += ram_check;
193 ram_check = 0;
194 }
195
196 /* If the ram_size is 2GB smaller, we can assume the IO space is
197 * not mapped in. gd->ram_size is the actual size of the dram
198 * not the accessible size.
199 */
200 if (total_ram_check != gd->ram_size) {
201 puts("DDR: SDRAM size check failed!\n");
202 hang();
203 }
204
205 debug("DDR: SDRAM size check passed!\n");
206}
207
208/**
209 * sdram_calculate_size() - Calculate SDRAM size
210 *
211 * Calculate SDRAM device size based on SDRAM controller parameters.
212 * Size is specified in bytes.
213 */
214phys_size_t sdram_calculate_size(struct altera_sdram_platdata *plat)
215{
216 u32 dramaddrw = hmc_readl(plat, DRAMADDRW);
217
218 phys_size_t size = 1 << (DRAMADDRW_CFG_CS_ADDR_WIDTH(dramaddrw) +
219 DRAMADDRW_CFG_BANK_GRP_ADDR_WIDTH(dramaddrw) +
220 DRAMADDRW_CFG_BANK_ADDR_WIDTH(dramaddrw) +
221 DRAMADDRW_CFG_ROW_ADDR_WIDTH(dramaddrw) +
222 DRAMADDRW_CFG_COL_ADDR_WIDTH(dramaddrw));
223
224 size *= (2 << (hmc_ecc_readl(plat, DDRIOCTRL) &
225 DDR_HMC_DDRIOCTRL_IOSIZE_MSK));
226
227 return size;
228}
229
230static int altera_sdram_ofdata_to_platdata(struct udevice *dev)
231{
232 struct altera_sdram_platdata *plat = dev->platdata;
233 fdt_addr_t addr;
234
235 addr = dev_read_addr_index(dev, 0);
236 if (addr == FDT_ADDR_T_NONE)
237 return -EINVAL;
238 plat->ddr_sch = (void __iomem *)addr;
239
240 addr = dev_read_addr_index(dev, 1);
241 if (addr == FDT_ADDR_T_NONE)
242 return -EINVAL;
243 plat->iomhc = (void __iomem *)addr;
244
245 addr = dev_read_addr_index(dev, 2);
246 if (addr == FDT_ADDR_T_NONE)
247 return -EINVAL;
248 plat->hmc = (void __iomem *)addr;
249
250 return 0;
251}
252
253static int altera_sdram_probe(struct udevice *dev)
254{
255 int ret;
256 struct altera_sdram_priv *priv = dev_get_priv(dev);
257
258 ret = reset_get_bulk(dev, &priv->resets);
259 if (ret) {
260 dev_err(dev, "Can't get reset: %d\n", ret);
261 return -ENODEV;
262 }
263 reset_deassert_bulk(&priv->resets);
264
265 if (sdram_mmr_init_full(dev) != 0) {
266 puts("SDRAM init failed.\n");
267 goto failed;
268 }
269
270 return 0;
271
272failed:
273 reset_release_bulk(&priv->resets);
274 return -ENODEV;
275}
276
277static int altera_sdram_get_info(struct udevice *dev,
278 struct ram_info *info)
279{
280 struct altera_sdram_priv *priv = dev_get_priv(dev);
281
282 info->base = priv->info.base;
283 info->size = priv->info.size;
284
285 return 0;
286}
287
288static struct ram_ops altera_sdram_ops = {
289 .get_info = altera_sdram_get_info,
290};
291
292static const struct udevice_id altera_sdram_ids[] = {
293 { .compatible = "altr,sdr-ctl-s10" },
Ley Foon Tan4ddb9092019-11-27 15:55:27 +0800294 { .compatible = "intel,sdr-ctl-agilex" },
Ley Foon Tan25572cf2019-11-27 15:55:26 +0800295 { /* sentinel */ }
296};
297
298U_BOOT_DRIVER(altera_sdram) = {
299 .name = "altr_sdr_ctl",
300 .id = UCLASS_RAM,
301 .of_match = altera_sdram_ids,
302 .ops = &altera_sdram_ops,
303 .ofdata_to_platdata = altera_sdram_ofdata_to_platdata,
304 .platdata_auto_alloc_size = sizeof(struct altera_sdram_platdata),
305 .probe = altera_sdram_probe,
306 .priv_auto_alloc_size = sizeof(struct altera_sdram_priv),
307};