dm: core: Create a new header file for 'compat' features
[platform/kernel/u-boot.git] / drivers / ddr / altera / sdram_soc64.c
1 // 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>
13 #include <hang.h>
14 #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>
22 #include <dm/device_compat.h>
23 #include <linux/sizes.h>
24
25 #define PGTABLE_OFF     0x4000
26
27 u32 hmc_readl(struct altera_sdram_platdata *plat, u32 reg)
28 {
29         return readl(plat->iomhc + reg);
30 }
31
32 u32 hmc_ecc_readl(struct altera_sdram_platdata *plat, u32 reg)
33 {
34         return readl(plat->hmc + reg);
35 }
36
37 u32 hmc_ecc_writel(struct altera_sdram_platdata *plat,
38                    u32 data, u32 reg)
39 {
40         return writel(data, plat->hmc + reg);
41 }
42
43 u32 ddr_sch_writel(struct altera_sdram_platdata *plat, u32 data,
44                    u32 reg)
45 {
46         return writel(data, plat->ddr_sch + reg);
47 }
48
49 int 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
59 int 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
99 int 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
106 void 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
132 void 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
176 void 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  */
214 phys_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
230 static 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
253 static 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
272 failed:
273         reset_release_bulk(&priv->resets);
274         return -ENODEV;
275 }
276
277 static 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
288 static struct ram_ops altera_sdram_ops = {
289         .get_info = altera_sdram_get_info,
290 };
291
292 static const struct udevice_id altera_sdram_ids[] = {
293         { .compatible = "altr,sdr-ctl-s10" },
294         { .compatible = "intel,sdr-ctl-agilex" },
295         { /* sentinel */ }
296 };
297
298 U_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 };