ram: aspeed: Add AST2600 DRAM control support
[platform/kernel/u-boot.git] / drivers / ram / aspeed / sdram_ast2600.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) ASPEED Technology Inc.
4  */
5 #include <common.h>
6 #include <clk.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <ram.h>
10 #include <regmap.h>
11 #include <reset.h>
12 #include <asm/io.h>
13 #include <asm/arch/scu_ast2600.h>
14 #include <asm/arch/sdram_ast2600.h>
15 #include <linux/err.h>
16 #include <linux/kernel.h>
17 #include <dt-bindings/clock/ast2600-clock.h>
18
19 #define DDR_PHY_TBL_CHG_ADDR            0xaeeddeea
20 #define DDR_PHY_TBL_END                 0xaeededed
21
22 #if defined(CONFIG_ASPEED_DDR4_800)
23 u32 ast2600_sdramphy_config[165] = {
24         0x1e6e0100,     // start address
25         0x00000000,     // phyr000
26         0x0c002062,     // phyr004
27         0x1a7a0063,     // phyr008
28         0x5a7a0063,     // phyr00c
29         0x1a7a0063,     // phyr010
30         0x1a7a0063,     // phyr014
31         0x20000000,     // phyr018
32         0x20000000,     // phyr01c
33         0x20000000,     // phyr020
34         0x20000000,     // phyr024
35         0x00000008,     // phyr028
36         0x00000000,     // phyr02c
37         0x00077600,     // phyr030
38         0x00000000,     // phyr034
39         0x00000000,     // phyr038
40         0x20000000,     // phyr03c
41         0x50506000,     // phyr040
42         0x50505050,     // phyr044
43         0x00002f07,     // phyr048
44         0x00003080,     // phyr04c
45         0x04000000,     // phyr050
46         0x00000200,     // phyr054
47         0x03140201,     // phyr058
48         0x04800000,     // phyr05c
49         0x0800044e,     // phyr060
50         0x00000000,     // phyr064
51         0x00180008,     // phyr068
52         0x00e00400,     // phyr06c
53         0x00140206,     // phyr070
54         0x1d4c0000,     // phyr074
55         0x493e0107,     // phyr078
56         0x08060404,     // phyr07c
57         0x90000a00,     // phyr080
58         0x06420618,     // phyr084
59         0x00001002,     // phyr088
60         0x05701016,     // phyr08c
61         0x10000000,     // phyr090
62         0xaeeddeea,     // change address
63         0x1e6e019c,     // new address
64         0x20202020,     // phyr09c
65         0x20202020,     // phyr0a0
66         0x00002020,     // phyr0a4
67         0x00002020,     // phyr0a8
68         0x00000001,     // phyr0ac
69         0xaeeddeea,     // change address
70         0x1e6e01cc,     // new address
71         0x01010101,     // phyr0cc
72         0x01010101,     // phyr0d0
73         0x80808080,     // phyr0d4
74         0x80808080,     // phyr0d8
75         0xaeeddeea,     // change address
76         0x1e6e0288,     // new address
77         0x80808080,     // phyr188
78         0x80808080,     // phyr18c
79         0x80808080,     // phyr190
80         0x80808080,     // phyr194
81         0xaeeddeea,     // change address
82         0x1e6e02f8,     // new address
83         0x90909090,     // phyr1f8
84         0x88888888,     // phyr1fc
85         0xaeeddeea,     // change address
86         0x1e6e0300,     // new address
87         0x00000000,     // phyr200
88         0xaeeddeea,     // change address
89         0x1e6e0194,     // new address
90         0x80118260,     // phyr094
91         0xaeeddeea,     // change address
92         0x1e6e019c,     // new address
93         0x20202020,     // phyr09c
94         0x20202020,     // phyr0a0
95         0x00002020,     // phyr0a4
96         0x80000000,     // phyr0a8
97         0x00000001,     // phyr0ac
98         0xaeeddeea,     // change address
99         0x1e6e0318,     // new address
100         0x09222719,     // phyr218
101         0x00aa4403,     // phyr21c
102         0xaeeddeea,     // change address
103         0x1e6e0198,     // new address
104         0x08060000,     // phyr098
105         0xaeeddeea,     // change address
106         0x1e6e01b0,     // new address
107         0x00000000,     // phyr0b0
108         0x00000000,     // phyr0b4
109         0x00000000,     // phyr0b8
110         0x00000000,     // phyr0bc
111         0x00000000,     // phyr0c0
112         0x00000000,     // phyr0c4
113         0x000aff2c,     // phyr0c8
114         0xaeeddeea,     // change address
115         0x1e6e01dc,     // new address
116         0x00080000,     // phyr0dc
117         0x00000000,     // phyr0e0
118         0xaa55aa55,     // phyr0e4
119         0x55aa55aa,     // phyr0e8
120         0xaaaa5555,     // phyr0ec
121         0x5555aaaa,     // phyr0f0
122         0xaa55aa55,     // phyr0f4
123         0x55aa55aa,     // phyr0f8
124         0xaaaa5555,     // phyr0fc
125         0x5555aaaa,     // phyr100
126         0xaa55aa55,     // phyr104
127         0x55aa55aa,     // phyr108
128         0xaaaa5555,     // phyr10c
129         0x5555aaaa,     // phyr110
130         0xaa55aa55,     // phyr114
131         0x55aa55aa,     // phyr118
132         0xaaaa5555,     // phyr11c
133         0x5555aaaa,     // phyr120
134         0x20202020,     // phyr124
135         0x20202020,     // phyr128
136         0x20202020,     // phyr12c
137         0x20202020,     // phyr130
138         0x20202020,     // phyr134
139         0x20202020,     // phyr138
140         0x20202020,     // phyr13c
141         0x20202020,     // phyr140
142         0x20202020,     // phyr144
143         0x20202020,     // phyr148
144         0x20202020,     // phyr14c
145         0x20202020,     // phyr150
146         0x20202020,     // phyr154
147         0x20202020,     // phyr158
148         0x20202020,     // phyr15c
149         0x20202020,     // phyr160
150         0x20202020,     // phyr164
151         0x20202020,     // phyr168
152         0x20202020,     // phyr16c
153         0x20202020,     // phyr170
154         0xaeeddeea,     // change address
155         0x1e6e0298,     // new address
156         0x20200800,     // phyr198
157         0x20202020,     // phyr19c
158         0x20202020,     // phyr1a0
159         0x20202020,     // phyr1a4
160         0x20202020,     // phyr1a8
161         0x20202020,     // phyr1ac
162         0x20202020,     // phyr1b0
163         0x20202020,     // phyr1b4
164         0x20202020,     // phyr1b8
165         0x20202020,     // phyr1bc
166         0x20202020,     // phyr1c0
167         0x20202020,     // phyr1c4
168         0x20202020,     // phyr1c8
169         0x20202020,     // phyr1cc
170         0x20202020,     // phyr1d0
171         0x20202020,     // phyr1d4
172         0x20202020,     // phyr1d8
173         0x20202020,     // phyr1dc
174         0x20202020,     // phyr1e0
175         0x20202020,     // phyr1e4
176         0x00002020,     // phyr1e8
177         0xaeeddeea,     // change address
178         0x1e6e0304,     // new address
179         0x00000800,     // phyr204
180         0xaeeddeea,     // change address
181         0x1e6e027c,     // new address
182         0x4e400000,     // phyr17c
183         0x59595959,     // phyr180
184         0x40404040,     // phyr184
185         0xaeeddeea,     // change address
186         0x1e6e02f4,     // new address
187         0x00000059,     // phyr1f4
188         0xaeededed,     // end
189 };
190 #else
191 u32 ast2600_sdramphy_config[165] = {
192         0x1e6e0100,     // start address
193         0x00000000,     // phyr000
194         0x0c002062,     // phyr004
195         0x1a7a0063,     // phyr008
196         0x5a7a0063,     // phyr00c
197         0x1a7a0063,     // phyr010
198         0x1a7a0063,     // phyr014
199         0x20000000,     // phyr018
200         0x20000000,     // phyr01c
201         0x20000000,     // phyr020
202         0x20000000,     // phyr024
203         0x00000008,     // phyr028
204         0x00000000,     // phyr02c
205         0x00077600,     // phyr030
206         0x00000000,     // phyr034
207         0x00000000,     // phyr038
208         0x20000000,     // phyr03c
209         0x50506000,     // phyr040
210         0x50505050,     // phyr044
211         0x00002f07,     // phyr048
212         0x00003080,     // phyr04c
213         0x04000000,     // phyr050
214         0x00000200,     // phyr054
215         0x03140501,     // phyr058-rtt:40
216         0x04800000,     // phyr05c
217         0x0800044e,     // phyr060
218         0x00000000,     // phyr064
219         0x00180008,     // phyr068
220         0x00e00400,     // phyr06c
221         0x00140206,     // phyr070
222         0x1d4c0000,     // phyr074
223         0x493e0107,     // phyr078
224         0x08060404,     // phyr07c
225         0x90000a00,     // phyr080
226         0x06420c30,     // phyr084
227         0x00001002,     // phyr088
228         0x05701016,     // phyr08c
229         0x10000000,     // phyr090
230         0xaeeddeea,     // change address
231         0x1e6e019c,     // new address
232         0x20202020,     // phyr09c
233         0x20202020,     // phyr0a0
234         0x00002020,     // phyr0a4
235         0x00002020,     // phyr0a8
236         0x00000001,     // phyr0ac
237         0xaeeddeea,     // change address
238         0x1e6e01cc,     // new address
239         0x01010101,     // phyr0cc
240         0x01010101,     // phyr0d0
241         0x80808080,     // phyr0d4
242         0x80808080,     // phyr0d8
243         0xaeeddeea,     // change address
244         0x1e6e0288,     // new address
245         0x80808080,     // phyr188
246         0x80808080,     // phyr18c
247         0x80808080,     // phyr190
248         0x80808080,     // phyr194
249         0xaeeddeea,     // change address
250         0x1e6e02f8,     // new address
251         0x90909090,     // phyr1f8
252         0x88888888,     // phyr1fc
253         0xaeeddeea,     // change address
254         0x1e6e0300,     // new address
255         0x00000000,     // phyr200
256         0xaeeddeea,     // change address
257         0x1e6e0194,     // new address
258         0x801112e0,     // phyr094 - bit12=1,15=0,- write window is ok
259         0xaeeddeea,     // change address
260         0x1e6e019c,     // new address
261         0x20202020,     // phyr09c
262         0x20202020,     // phyr0a0
263         0x00002020,     // phyr0a4
264         0x80000000,     // phyr0a8
265         0x00000001,     // phyr0ac
266         0xaeeddeea,     // change address
267         0x1e6e0318,     // new address
268         0x09222719,     // phyr218
269         0x00aa4403,     // phyr21c
270         0xaeeddeea,     // change address
271         0x1e6e0198,     // new address
272         0x08060000,     // phyr098
273         0xaeeddeea,     // change address
274         0x1e6e01b0,     // new address
275         0x00000000,     // phyr0b0
276         0x00000000,     // phyr0b4
277         0x00000000,     // phyr0b8
278         0x00000000,     // phyr0bc
279         0x00000000,     // phyr0c0 - ori
280         0x00000000,     // phyr0c4
281         0x000aff2c,     // phyr0c8
282         0xaeeddeea,     // change address
283         0x1e6e01dc,     // new address
284         0x00080000,     // phyr0dc
285         0x00000000,     // phyr0e0
286         0xaa55aa55,     // phyr0e4
287         0x55aa55aa,     // phyr0e8
288         0xaaaa5555,     // phyr0ec
289         0x5555aaaa,     // phyr0f0
290         0xaa55aa55,     // phyr0f4
291         0x55aa55aa,     // phyr0f8
292         0xaaaa5555,     // phyr0fc
293         0x5555aaaa,     // phyr100
294         0xaa55aa55,     // phyr104
295         0x55aa55aa,     // phyr108
296         0xaaaa5555,     // phyr10c
297         0x5555aaaa,     // phyr110
298         0xaa55aa55,     // phyr114
299         0x55aa55aa,     // phyr118
300         0xaaaa5555,     // phyr11c
301         0x5555aaaa,     // phyr120
302         0x20202020,     // phyr124
303         0x20202020,     // phyr128
304         0x20202020,     // phyr12c
305         0x20202020,     // phyr130
306         0x20202020,     // phyr134
307         0x20202020,     // phyr138
308         0x20202020,     // phyr13c
309         0x20202020,     // phyr140
310         0x20202020,     // phyr144
311         0x20202020,     // phyr148
312         0x20202020,     // phyr14c
313         0x20202020,     // phyr150
314         0x20202020,     // phyr154
315         0x20202020,     // phyr158
316         0x20202020,     // phyr15c
317         0x20202020,     // phyr160
318         0x20202020,     // phyr164
319         0x20202020,     // phyr168
320         0x20202020,     // phyr16c
321         0x20202020,     // phyr170
322         0xaeeddeea,     // change address
323         0x1e6e0298,     // new address
324         0x20200800,     // phyr198
325         0x20202020,     // phyr19c
326         0x20202020,     // phyr1a0
327         0x20202020,     // phyr1a4
328         0x20202020,     // phyr1a8
329         0x20202020,     // phyr1ac
330         0x20202020,     // phyr1b0
331         0x20202020,     // phyr1b4
332         0x20202020,     // phyr1b8
333         0x20202020,     // phyr1bc
334         0x20202020,     // phyr1c0
335         0x20202020,     // phyr1c4
336         0x20202020,     // phyr1c8
337         0x20202020,     // phyr1cc
338         0x20202020,     // phyr1d0
339         0x20202020,     // phyr1d4
340         0x20202020,     // phyr1d8
341         0x20202020,     // phyr1dc
342         0x20202020,     // phyr1e0
343         0x20202020,     // phyr1e4
344         0x00002020,     // phyr1e8
345         0xaeeddeea,     // change address
346         0x1e6e0304,     // new address
347         0x00000800,     // phyr204
348         0xaeeddeea,     // change address
349         0x1e6e027c,     // new address
350         0x4e400000,     // phyr17c
351         0x59595959,     // phyr180
352         0x40404040,     // phyr184
353         0xaeeddeea,     // change address
354         0x1e6e02f4,     // new address
355         0x00000059,     // phyr1f4
356         0xaeededed,     // end
357 };
358 #endif
359
360 /* MPLL configuration */
361 #define SCU_MPLL_FREQ_400M      0x0008405F
362 #define SCU_MPLL_EXT_400M       0x0000002F
363 #define SCU_MPLL_FREQ_333M      0x00488299
364 #define SCU_MPLL_EXT_333M       0x0000014C
365 #define SCU_MPLL_FREQ_200M      0x0078007F
366 #define SCU_MPLL_EXT_200M       0x0000003F
367 #define SCU_MPLL_FREQ_100M      0x0078003F
368 #define SCU_MPLL_EXT_100M       0x0000001F
369
370 #if defined(CONFIG_ASPEED_DDR4_1600)
371 #define SCU_MPLL_FREQ_CFG       SCU_MPLL_FREQ_400M
372 #define SCU_MPLL_EXT_CFG        SCU_MPLL_EXT_400M
373 #elif defined(CONFIG_ASPEED_DDR4_1333)
374 #define SCU_MPLL_FREQ_CFG       SCU_MPLL_FREQ_333M
375 #define SCU_MPLL_EXT_CFG        SCU_MPLL_EXT_333M
376 #elif defined(CONFIG_ASPEED_DDR4_800)
377 #define SCU_MPLL_FREQ_CFG       SCU_MPLL_FREQ_200M
378 #define SCU_MPLL_EXT_CFG        SCU_MPLL_EXT_200M
379 #elif defined(CONFIG_ASPEED_DDR4_400)
380 #define SCU_MPLL_FREQ_CFG       SCU_MPLL_FREQ_100M
381 #define SCU_MPLL_EXT_CFG        SCU_MPLL_EXT_100M
382 #else
383 #error "undefined DDR4 target rate\n"
384 #endif
385
386 /*
387  * AC timing and SDRAM mode register setting
388  * for real chip are derived from the model GDDR4-1600
389  */
390 #define DDR4_MR01_MODE  0x03010510
391 #define DDR4_MR23_MODE  0x00000000
392 #define DDR4_MR45_MODE  0x04000000
393 #define DDR4_MR6_MODE   0x00000400
394 #define DDR4_TRFC_1600  0x467299f1
395 #define DDR4_TRFC_1333  0x3a5f80c9
396 #define DDR4_TRFC_800   0x23394c78
397 #define DDR4_TRFC_400   0x111c263c
398
399 #if defined(CONFIG_ASPEED_DDR4_1600)
400 #define DDR4_TRFC               DDR4_TRFC_1600
401 #define DDR4_PHY_TRAIN_TRFC     0xc30
402 #elif defined(CONFIG_ASPEED_DDR4_1333)
403 #define DDR4_TRFC               DDR4_TRFC_1333
404 #define DDR4_PHY_TRAIN_TRFC     0xa25
405 #elif defined(CONFIG_ASPEED_DDR4_800)
406 #define DDR4_TRFC               DDR4_TRFC_800
407 #define DDR4_PHY_TRAIN_TRFC     0x618
408 #elif defined(CONFIG_ASPEED_DDR4_400)
409 #define DDR4_TRFC               DDR4_TRFC_400
410 #define DDR4_PHY_TRAIN_TRFC     0x30c
411 #else
412 #error "undefined tRFC setting"
413 #endif
414
415 /* supported SDRAM size */
416 #define SDRAM_SIZE_1KB          (1024U)
417 #define SDRAM_SIZE_1MB          (SDRAM_SIZE_1KB * SDRAM_SIZE_1KB)
418 #define SDRAM_MIN_SIZE          (256 * SDRAM_SIZE_1MB)
419 #define SDRAM_MAX_SIZE          (2048 * SDRAM_SIZE_1MB)
420
421 DECLARE_GLOBAL_DATA_PTR;
422
423 static const u32 ddr4_ac_timing[4] = {
424         0x040e0307, 0x0f4711f1, 0x0e060304, 0x00001240 };
425 static const u32 ddr_max_grant_params[4] = {
426         0x44444444, 0x44444444, 0x44444444, 0x44444444 };
427
428 struct dram_info {
429         struct ram_info info;
430         struct clk ddr_clk;
431         struct ast2600_sdrammc_regs *regs;
432         struct ast2600_scu *scu;
433         struct ast2600_ddr_phy *phy;
434         void __iomem *phy_setting;
435         void __iomem *phy_status;
436         ulong clock_rate;
437 };
438
439 static void ast2600_sdramphy_kick_training(struct dram_info *info)
440 {
441         u32 data;
442         struct ast2600_sdrammc_regs *regs = info->regs;
443
444         writel(SDRAM_PHYCTRL0_NRST, &regs->phy_ctrl[0]);
445         udelay(5);
446         writel(SDRAM_PHYCTRL0_NRST | SDRAM_PHYCTRL0_INIT, &regs->phy_ctrl[0]);
447         udelay(1000);
448
449         while (1) {
450                 data = readl(&regs->phy_ctrl[0]) & SDRAM_PHYCTRL0_INIT;
451                 if (~data)
452                         break;
453         }
454 }
455
456 /**
457  * @brief       load DDR-PHY configurations table to the PHY registers
458  * @param[in]   p_tbl - pointer to the configuration table
459  * @param[in]   info - pointer to the DRAM info struct
460  *
461  * There are two sets of MRS (Mode Registers) configuration in ast2600 memory
462  * system: one is in the SDRAM MC (memory controller) which is used in run
463  * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
464  * training.
465  */
466 static void ast2600_sdramphy_init(u32 *p_tbl, struct dram_info *info)
467 {
468         u32 reg_base = (u32)info->phy_setting;
469         u32 addr = p_tbl[0];
470         u32 data;
471         int i = 1;
472
473         writel(0, &info->regs->phy_ctrl[0]);
474         udelay(10);
475
476         while (1) {
477                 if (addr < reg_base) {
478                         debug("invalid DDR-PHY addr: 0x%08x\n", addr);
479                         break;
480                 }
481                 data = p_tbl[i++];
482
483                 if (data == DDR_PHY_TBL_END) {
484                         break;
485                 } else if (data == DDR_PHY_TBL_CHG_ADDR) {
486                         addr = p_tbl[i++];
487                 } else {
488                         writel(data, addr);
489                         addr += 4;
490                 }
491         }
492
493         data = readl(info->phy_setting + 0x84) & ~GENMASK(16, 0);
494         data |= DDR4_PHY_TRAIN_TRFC;
495         writel(data, info->phy_setting + 0x84);
496 }
497
498 static int ast2600_sdramphy_check_status(struct dram_info *info)
499 {
500         u32 value, tmp;
501         u32 reg_base = (u32)info->phy_status;
502         int need_retrain = 0;
503
504         debug("\nSDRAM PHY training report:\n");
505
506         /* training status */
507         value = readl(reg_base + 0x00);
508         debug("rO_DDRPHY_reg offset 0x00 = 0x%08x\n", value);
509
510         if (value & BIT(3))
511                 debug("\tinitial PVT calibration fail\n");
512
513         if (value & BIT(5))
514                 debug("\truntime calibration fail\n");
515
516         /* PU & PD */
517         value = readl(reg_base + 0x30);
518         debug("rO_DDRPHY_reg offset 0x30 = 0x%08x\n", value);
519         debug("  PU = 0x%02x\n", value & 0xff);
520         debug("  PD = 0x%02x\n", (value >> 16) & 0xff);
521
522         /* read eye window */
523         value = readl(reg_base + 0x68);
524         if (0 == (value & GENMASK(7, 0)))
525                 need_retrain = 1;
526
527         debug("rO_DDRPHY_reg offset 0x68 = 0x%08x\n", value);
528         debug("  rising edge of read data eye training pass window\n");
529         tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 255;
530         debug("    B0:%d%%\n", tmp);
531         tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 255;
532         debug("    B1:%d%%\n", tmp);
533
534         value = readl(reg_base + 0xC8);
535         debug("rO_DDRPHY_reg offset 0xC8 = 0x%08x\n", value);
536         debug("  falling edge of read data eye training pass window\n");
537         tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 255;
538         debug("    B0:%d%%\n", tmp);
539         tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 255;
540         debug("    B1:%d%%\n", tmp);
541
542         /* write eye window */
543         value = readl(reg_base + 0x7c);
544         if (0 == (value & GENMASK(7, 0)))
545                 need_retrain = 1;
546
547         debug("rO_DDRPHY_reg offset 0x7C = 0x%08x\n", value);
548         debug("  rising edge of write data eye training pass window\n");
549         tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 255;
550         debug("    B0:%d%%\n", tmp);
551         tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 255;
552         debug("    B1:%d%%\n", tmp);
553
554         /* read Vref training result */
555         value = readl(reg_base + 0x88);
556         debug("rO_DDRPHY_reg offset 0x88 = 0x%08x\n", value);
557         debug("  read Vref training result\n");
558         tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 127;
559         debug("    B0:%d%%\n", tmp);
560         tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 127;
561         debug("    B1:%d%%\n", tmp);
562
563         /* write Vref training result */
564         value = readl(reg_base + 0x90);
565         debug("rO_DDRPHY_reg offset 0x90 = 0x%08x\n", value);
566
567         /* gate train */
568         value = readl(reg_base + 0x50);
569         if ((0 == (value & GENMASK(15, 0))) ||
570             (0 == (value & GENMASK(31, 16)))) {
571                 need_retrain = 1;
572         }
573
574         debug("rO_DDRPHY_reg offset 0x50 = 0x%08x\n", value);
575
576         return need_retrain;
577 }
578
579 #ifndef CONFIG_ASPEED_BYPASS_SELFTEST
580 #define MC_TEST_PATTERN_N 8
581 static u32 as2600_sdrammc_test_pattern[MC_TEST_PATTERN_N] = {
582         0xcc33cc33, 0xff00ff00, 0xaa55aa55, 0x88778877,
583         0x92cc4d6e, 0x543d3cde, 0xf1e843c7, 0x7c61d253 };
584
585 #define TIMEOUT_DRAM    5000000
586 int ast2600_sdrammc_dg_test(struct dram_info *info, unsigned int datagen, u32 mode)
587 {
588         unsigned int data;
589         unsigned int timeout = 0;
590         struct ast2600_sdrammc_regs *regs = info->regs;
591
592         writel(0, &regs->ecc_test_ctrl);
593
594         if (mode == 0)
595                 writel(0x00000085 | (datagen << 3), &regs->ecc_test_ctrl);
596         else
597                 writel(0x000000C1 | (datagen << 3), &regs->ecc_test_ctrl);
598
599         do {
600                 data = readl(&regs->ecc_test_ctrl) & GENMASK(13, 12);
601
602                 if (data & BIT(13))
603                         return 0;
604
605                 if (++timeout > TIMEOUT_DRAM) {
606                         debug("Timeout!!\n");
607                         writel(0, &regs->ecc_test_ctrl);
608                         return -1;
609                 }
610         } while (!data);
611
612         writel(0, &regs->ecc_test_ctrl);
613
614         return 0;
615 }
616
617 int ast2600_sdrammc_cbr_test(struct dram_info *info)
618 {
619         u32 i;
620         struct ast2600_sdrammc_regs *regs = info->regs;
621
622         clrsetbits_le32(&regs->test_addr, GENMASK(30, 4), 0x7ffff0);
623
624         /* single */
625         for (i = 0; i < 8; i++)
626                 if (ast2600_sdrammc_dg_test(info, i, 0))
627                         return -1;
628
629         /* burst */
630         for (i = 0; i < 8; i++)
631                 if (ast2600_sdrammc_dg_test(info, i, i))
632                         return -1;
633
634         return 0;
635 }
636
637 static int ast2600_sdrammc_test(struct dram_info *info)
638 {
639         struct ast2600_sdrammc_regs *regs = info->regs;
640
641         u32 pass_cnt = 0;
642         u32 fail_cnt = 0;
643         u32 target_cnt = 2;
644         u32 test_cnt = 0;
645         u32 pattern;
646         u32 i = 0;
647         bool finish = false;
648
649         debug("sdram mc test:\n");
650         while (!finish) {
651                 pattern = as2600_sdrammc_test_pattern[i++];
652                 i = i % MC_TEST_PATTERN_N;
653                 debug("  pattern = %08X : ", pattern);
654                 writel(pattern, &regs->test_init_val);
655
656                 if (ast2600_sdrammc_cbr_test(info)) {
657                         debug("fail\n");
658                         fail_cnt++;
659                 } else {
660                         debug("pass\n");
661                         pass_cnt++;
662                 }
663
664                 if (++test_cnt == target_cnt)
665                         finish = true;
666         }
667         debug("statistics: pass/fail/total:%d/%d/%d\n", pass_cnt, fail_cnt,
668               target_cnt);
669
670         return fail_cnt;
671 }
672 #endif
673
674 /*
675  * scu500[14:13]
676  *      2b'00: VGA memory size = 16MB
677  *      2b'01: VGA memory size = 16MB
678  *      2b'10: VGA memory size = 32MB
679  *      2b'11: VGA memory size = 64MB
680  *
681  * mcr04[3:2]
682  *      2b'00: VGA memory size = 8MB
683  *      2b'01: VGA memory size = 16MB
684  *      2b'10: VGA memory size = 32MB
685  *      2b'11: VGA memory size = 64MB
686  */
687 static size_t ast2600_sdrammc_get_vga_mem_size(struct dram_info *info)
688 {
689         u32 vga_hwconf;
690         size_t vga_mem_size_base = 8 * 1024 * 1024;
691
692         vga_hwconf =
693                 (readl(&info->scu->hwstrap1) & SCU_HWSTRAP1_VGA_MEM_MASK) >>
694                  SCU_HWSTRAP1_VGA_MEM_SHIFT;
695
696         if (vga_hwconf == 0) {
697                 vga_hwconf = 1;
698                 writel(vga_hwconf << SCU_HWSTRAP1_VGA_MEM_SHIFT,
699                        &info->scu->hwstrap1);
700         }
701
702         clrsetbits_le32(&info->regs->config, SDRAM_CONF_VGA_SIZE_MASK,
703                         ((vga_hwconf << SDRAM_CONF_VGA_SIZE_SHIFT) &
704                          SDRAM_CONF_VGA_SIZE_MASK));
705
706         /* no need to reserve VGA memory if efuse[VGA disable] is set */
707         if (readl(&info->scu->efuse) & SCU_EFUSE_DIS_VGA)
708                 return 0;
709
710         return vga_mem_size_base << vga_hwconf;
711 }
712
713 /*
714  * Find out RAM size and save it in dram_info
715  *
716  * The procedure is taken from Aspeed SDK
717  */
718 static void ast2600_sdrammc_calc_size(struct dram_info *info)
719 {
720         /* The controller supports 256/512/1024/2048 MB ram */
721         size_t ram_size = SDRAM_MIN_SIZE;
722         const int write_test_offset = 0x100000;
723         u32 test_pattern = 0xdeadbeef;
724         u32 cap_param = SDRAM_CONF_CAP_2048M;
725         u32 refresh_timing_param = DDR4_TRFC;
726         const u32 write_addr_base = CONFIG_SYS_SDRAM_BASE + write_test_offset;
727
728         for (ram_size = SDRAM_MAX_SIZE; ram_size > SDRAM_MIN_SIZE;
729              ram_size >>= 1) {
730                 writel(test_pattern, write_addr_base + (ram_size >> 1));
731                 test_pattern = (test_pattern >> 4) | (test_pattern << 28);
732         }
733
734         /* One last write to overwrite all wrapped values */
735         writel(test_pattern, write_addr_base);
736
737         /* Reset the pattern and see which value was really written */
738         test_pattern = 0xdeadbeef;
739         for (ram_size = SDRAM_MAX_SIZE; ram_size > SDRAM_MIN_SIZE;
740              ram_size >>= 1) {
741                 if (readl(write_addr_base + (ram_size >> 1)) == test_pattern)
742                         break;
743
744                 --cap_param;
745                 refresh_timing_param >>= 8;
746                 test_pattern = (test_pattern >> 4) | (test_pattern << 28);
747         }
748
749         clrsetbits_le32(&info->regs->ac_timing[1],
750                         (SDRAM_AC_TRFC_MASK << SDRAM_AC_TRFC_SHIFT),
751                         ((refresh_timing_param & SDRAM_AC_TRFC_MASK)
752                          << SDRAM_AC_TRFC_SHIFT));
753
754         info->info.base = CONFIG_SYS_SDRAM_BASE;
755         info->info.size = ram_size - ast2600_sdrammc_get_vga_mem_size(info);
756
757         clrsetbits_le32(&info->regs->config, SDRAM_CONF_CAP_MASK,
758                         ((cap_param << SDRAM_CONF_CAP_SHIFT) & SDRAM_CONF_CAP_MASK));
759 }
760
761 static int ast2600_sdrammc_init_ddr4(struct dram_info *info)
762 {
763         const u32 power_ctrl = MCR34_CKE_EN | MCR34_AUTOPWRDN_EN |
764                 MCR34_MREQ_BYPASS_DIS | MCR34_RESETN_DIS |
765                 MCR34_ODT_EN | MCR34_ODT_AUTO_ON |
766                 (0x1 << MCR34_ODT_EXT_SHIFT);
767
768         /* init SDRAM-PHY only on real chip */
769         ast2600_sdramphy_init(ast2600_sdramphy_config, info);
770         writel((MCR34_CKE_EN | MCR34_MREQI_DIS | MCR34_RESETN_DIS),
771                &info->regs->power_ctrl);
772         udelay(5);
773         ast2600_sdramphy_kick_training(info);
774         udelay(500);
775         writel(SDRAM_RESET_DLL_ZQCL_EN, &info->regs->refresh_timing);
776
777         writel(MCR30_SET_MR(3), &info->regs->mode_setting_control);
778         writel(MCR30_SET_MR(6), &info->regs->mode_setting_control);
779         writel(MCR30_SET_MR(5), &info->regs->mode_setting_control);
780         writel(MCR30_SET_MR(4), &info->regs->mode_setting_control);
781         writel(MCR30_SET_MR(2), &info->regs->mode_setting_control);
782         writel(MCR30_SET_MR(1), &info->regs->mode_setting_control);
783         writel(MCR30_SET_MR(0) | MCR30_RESET_DLL_DELAY_EN,
784                &info->regs->mode_setting_control);
785
786         writel(SDRAM_REFRESH_EN | SDRAM_RESET_DLL_ZQCL_EN |
787                (0x5f << SDRAM_REFRESH_PERIOD_SHIFT),
788                &info->regs->refresh_timing);
789
790         /* wait self-refresh idle */
791         while (readl(&info->regs->power_ctrl) &
792                MCR34_SELF_REFRESH_STATUS_MASK)
793                 ;
794
795         writel(SDRAM_REFRESH_EN | SDRAM_LOW_PRI_REFRESH_EN |
796                SDRAM_REFRESH_ZQCS_EN |
797                (0x5f << SDRAM_REFRESH_PERIOD_SHIFT) |
798                (0x42aa << SDRAM_REFRESH_PERIOD_ZQCS_SHIFT),
799                &info->regs->refresh_timing);
800
801         writel(power_ctrl, &info->regs->power_ctrl);
802         udelay(500);
803
804         return 0;
805 }
806
807 static void ast2600_sdrammc_unlock(struct dram_info *info)
808 {
809         writel(SDRAM_UNLOCK_KEY, &info->regs->protection_key);
810         while (!readl(&info->regs->protection_key))
811                 ;
812 }
813
814 static void ast2600_sdrammc_lock(struct dram_info *info)
815 {
816         writel(~SDRAM_UNLOCK_KEY, &info->regs->protection_key);
817         while (readl(&info->regs->protection_key))
818                 ;
819 }
820
821 static void ast2600_sdrammc_common_init(struct ast2600_sdrammc_regs *regs)
822 {
823         int i;
824
825         writel(MCR34_MREQI_DIS | MCR34_RESETN_DIS, &regs->power_ctrl);
826         writel(SDRAM_VIDEO_UNLOCK_KEY, &regs->gm_protection_key);
827         writel(0x10 << MCR38_RW_MAX_GRANT_CNT_RQ_SHIFT,
828                &regs->arbitration_ctrl);
829         writel(0xFFBBFFF4, &regs->req_limit_mask);
830
831         for (i = 0; i < ARRAY_SIZE(ddr_max_grant_params); ++i)
832                 writel(ddr_max_grant_params[i], &regs->max_grant_len[i]);
833
834         writel(MCR50_RESET_ALL_INTR, &regs->intr_ctrl);
835
836         writel(0x07FFFFFF, &regs->ecc_range_ctrl);
837
838         writel(0, &regs->ecc_test_ctrl);
839         writel(0x80000001, &regs->test_addr);
840         writel(0, &regs->test_fail_dq_bit);
841         writel(0, &regs->test_init_val);
842
843         writel(0xFFFFFFFF, &regs->req_input_ctrl);
844         writel(0, &regs->req_high_pri_ctrl);
845
846         udelay(600);
847
848 #ifdef CONFIG_ASPEED_DDR4_DUALX8
849         writel(0x37, &regs->config);
850 #else
851         writel(0x17, &regs->config);
852 #endif
853
854         /* load controller setting */
855         for (i = 0; i < ARRAY_SIZE(ddr4_ac_timing); ++i)
856                 writel(ddr4_ac_timing[i], &regs->ac_timing[i]);
857
858         writel(DDR4_MR01_MODE, &regs->mr01_mode_setting);
859         writel(DDR4_MR23_MODE, &regs->mr23_mode_setting);
860         writel(DDR4_MR45_MODE, &regs->mr45_mode_setting);
861         writel(DDR4_MR6_MODE, &regs->mr6_mode_setting);
862 }
863
864 /*
865  * Update size info according to the ECC HW setting
866  *
867  * Assume SDRAM has been initialized by SPL or the host.  To get the RAM size, we
868  * don't need to calculate the ECC size again but read from MCR04 and derive the
869  * size from its value.
870  */
871 static void ast2600_sdrammc_update_size(struct dram_info *info)
872 {
873         struct ast2600_sdrammc_regs *regs = info->regs;
874         u32 conf = readl(&regs->config);
875         u32 cap_param;
876         size_t ram_size = SDRAM_MAX_SIZE;
877         size_t hw_size;
878
879         cap_param = (conf & SDRAM_CONF_CAP_MASK) >> SDRAM_CONF_CAP_SHIFT;
880         switch (cap_param) {
881         case SDRAM_CONF_CAP_2048M:
882                 ram_size = 2048 * SDRAM_SIZE_1MB;
883                 break;
884         case SDRAM_CONF_CAP_1024M:
885                 ram_size = 1024 * SDRAM_SIZE_1MB;
886                 break;
887         case SDRAM_CONF_CAP_512M:
888                 ram_size = 512 * SDRAM_SIZE_1MB;
889                 break;
890         case SDRAM_CONF_CAP_256M:
891                 ram_size = 256 * SDRAM_SIZE_1MB;
892                 break;
893         }
894
895         info->info.base = CONFIG_SYS_SDRAM_BASE;
896         info->info.size = ram_size - ast2600_sdrammc_get_vga_mem_size(info);
897
898         if (0 == (conf & SDRAM_CONF_ECC_SETUP))
899                 return;
900
901         hw_size = readl(&regs->ecc_range_ctrl) & SDRAM_ECC_RANGE_ADDR_MASK;
902         hw_size += (1 << SDRAM_ECC_RANGE_ADDR_SHIFT);
903
904         info->info.size = hw_size;
905 }
906
907 #ifdef CONFIG_ASPEED_ECC
908 static void ast2600_sdrammc_ecc_enable(struct dram_info *info)
909 {
910         struct ast2600_sdrammc_regs *regs = info->regs;
911         size_t conf_size;
912         u32 reg;
913
914         conf_size = CONFIG_ASPEED_ECC_SIZE * SDRAM_SIZE_1MB;
915         if (conf_size > info->info.size) {
916                 printf("warning: ECC configured %dMB but actual size is %dMB\n",
917                        CONFIG_ASPEED_ECC_SIZE,
918                        info->info.size / SDRAM_SIZE_1MB);
919                 conf_size = info->info.size;
920         } else if (conf_size == 0) {
921                 conf_size = info->info.size;
922         }
923
924         info->info.size = (((conf_size / 9) * 8) >> 20) << 20;
925         writel(((info->info.size >> 20) - 1) << 20, &regs->ecc_range_ctrl);
926         reg = readl(&regs->config) | SDRAM_CONF_ECC_SETUP;
927         writel(reg, &regs->config);
928
929         writel(0, &regs->test_init_val);
930         writel(0x80000001, &regs->test_addr);
931         writel(0x221, &regs->ecc_test_ctrl);
932         while (0 == (readl(&regs->ecc_test_ctrl) & BIT(12)))
933                 ;
934         writel(0, &regs->ecc_test_ctrl);
935         writel(BIT(31), &regs->intr_ctrl);
936         writel(0, &regs->intr_ctrl);
937 }
938 #endif
939
940 static int ast2600_sdrammc_probe(struct udevice *dev)
941 {
942         int ret;
943         u32 reg;
944         struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
945         struct ast2600_sdrammc_regs *regs = priv->regs;
946         struct udevice *clk_dev;
947
948         /* find SCU base address from clock device */
949         ret = uclass_get_device_by_driver(UCLASS_CLK,
950                                           DM_DRIVER_GET(aspeed_ast2600_scu), &clk_dev);
951         if (ret) {
952                 debug("clock device not defined\n");
953                 return ret;
954         }
955
956         priv->scu = devfdt_get_addr_ptr(clk_dev);
957         if (IS_ERR(priv->scu)) {
958                 debug("%s(): can't get SCU\n", __func__);
959                 return PTR_ERR(priv->scu);
960         }
961
962         if (readl(&priv->scu->dram_hdshk) & SCU_DRAM_HDSHK_RDY) {
963                 printf("already initialized, ");
964                 ast2600_sdrammc_update_size(priv);
965                 return 0;
966         }
967
968         reg = readl(&priv->scu->mpll);
969         reg &= ~(SCU_PLL_BYPASS | SCU_PLL_DIV_MASK |
970                  SCU_PLL_DENUM_MASK | SCU_PLL_NUM_MASK);
971         reg |= (SCU_PLL_RST | SCU_PLL_OFF | SCU_MPLL_FREQ_CFG);
972         writel(reg, &priv->scu->mpll);
973         writel(SCU_MPLL_EXT_CFG, &priv->scu->mpll_ext);
974         udelay(100);
975         reg &= ~(SCU_PLL_RST | SCU_PLL_OFF);
976         writel(reg, &priv->scu->mpll);
977
978         while ((readl(&priv->scu->mpll_ext) & BIT(31)) == 0)
979                 ;
980
981         ast2600_sdrammc_unlock(priv);
982         ast2600_sdrammc_common_init(regs);
983 L_ast2600_sdramphy_train:
984         ast2600_sdrammc_init_ddr4(priv);
985
986         /* make sure DDR-PHY is ready before access */
987         do {
988                 reg = readl(priv->phy_status) & BIT(1);
989         } while (reg == 0);
990
991         if (ast2600_sdramphy_check_status(priv) != 0) {
992                 printf("DDR4 PHY training fail, retrain\n");
993                 goto L_ast2600_sdramphy_train;
994         }
995
996         ast2600_sdrammc_calc_size(priv);
997
998 #ifndef CONFIG_ASPEED_BYPASS_SELFTEST
999         if (ast2600_sdrammc_test(priv) != 0) {
1000                 printf("%s: DDR4 init fail\n", __func__);
1001                 return -EINVAL;
1002         }
1003 #endif
1004
1005 #ifdef CONFIG_ASPEED_ECC
1006         ast2600_sdrammc_ecc_enable(priv);
1007 #endif
1008
1009         writel(readl(&priv->scu->dram_hdshk) | SCU_DRAM_HDSHK_RDY,
1010                &priv->scu->dram_hdshk);
1011
1012         clrbits_le32(&regs->intr_ctrl, MCR50_RESET_ALL_INTR);
1013         ast2600_sdrammc_lock(priv);
1014         return 0;
1015 }
1016
1017 static int ast2600_sdrammc_of_to_plat(struct udevice *dev)
1018 {
1019         struct dram_info *priv = dev_get_priv(dev);
1020
1021         priv->regs = (void *)(uintptr_t)devfdt_get_addr_index(dev, 0);
1022         priv->phy_setting = (void *)(uintptr_t)devfdt_get_addr_index(dev, 1);
1023         priv->phy_status = (void *)(uintptr_t)devfdt_get_addr_index(dev, 2);
1024
1025         priv->clock_rate = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
1026                                           "clock-frequency", 0);
1027         if (!priv->clock_rate) {
1028                 debug("DDR Clock Rate not defined\n");
1029                 return -EINVAL;
1030         }
1031
1032         return 0;
1033 }
1034
1035 static int ast2600_sdrammc_get_info(struct udevice *dev, struct ram_info *info)
1036 {
1037         struct dram_info *priv = dev_get_priv(dev);
1038
1039         *info = priv->info;
1040
1041         return 0;
1042 }
1043
1044 static struct ram_ops ast2600_sdrammc_ops = {
1045         .get_info = ast2600_sdrammc_get_info,
1046 };
1047
1048 static const struct udevice_id ast2600_sdrammc_ids[] = {
1049         { .compatible = "aspeed,ast2600-sdrammc" },
1050         { }
1051 };
1052
1053 U_BOOT_DRIVER(sdrammc_ast2600) = {
1054         .name = "aspeed_ast2600_sdrammc",
1055         .id = UCLASS_RAM,
1056         .of_match = ast2600_sdrammc_ids,
1057         .ops = &ast2600_sdrammc_ops,
1058         .of_to_plat = ast2600_sdrammc_of_to_plat,
1059         .probe = ast2600_sdrammc_probe,
1060         .priv_auto = sizeof(struct dram_info),
1061 };