]> git.sur5r.net Git - u-boot/blob - arch/arm/mach-uniphier/dram/umc-ld20.c
ARM: uniphier: update DRAM init code for LD20 SoC (3rd)
[u-boot] / arch / arm / mach-uniphier / dram / umc-ld20.c
1 /*
2  * Copyright (C) 2016 Socionext Inc.
3  *
4  * based on commit a7a36122aa072fe1bb06e02b73b3634b7a6c555a of Diag
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <linux/bitops.h>
11 #include <linux/err.h>
12 #include <linux/io.h>
13 #include <linux/sizes.h>
14 #include <asm/processor.h>
15
16 #include "../init.h"
17 #include "ddrphy-ld20-regs.h"
18 #include "umc64-regs.h"
19
20 #define DRAM_CH_NR      3
21
22 enum dram_freq {
23         DRAM_FREQ_1866M,
24         DRAM_FREQ_NR,
25 };
26
27 enum dram_size {
28         DRAM_SZ_256M,
29         DRAM_SZ_512M,
30         DRAM_SZ_NR,
31 };
32
33 enum dram_board {               /* board type */
34         DRAM_BOARD_LD20_REF,    /* LD20 reference */
35         DRAM_BOARD_LD20_GLOBAL, /* LD20 TV */
36         DRAM_BOARD_LD20_C1,     /* LD20 TV C1 */
37         DRAM_BOARD_LD21_REF,    /* LD21 reference */
38         DRAM_BOARD_LD21_GLOBAL, /* LD21 TV */
39         DRAM_BOARD_NR,
40 };
41
42 /* PHY */
43 static const int ddrphy_adrctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
44         {268 - 262, 268 - 263, 268 - 378},      /* LD20 reference */
45         {268 - 262, 268 - 263, 268 - 378},      /* LD20 TV */
46         {268 - 262, 268 - 263, 268 - 378},      /* LD20 TV C1 */
47         {268 - 212, 268 - 268, /* No CH2 */},   /* LD21 reference */
48         {268 - 212, 268 - 268, /* No CH2 */},   /* LD21 TV */
49 };
50
51 static const int ddrphy_dlltrimclk[DRAM_BOARD_NR][DRAM_CH_NR] = {
52         {268, 268, 268},                        /* LD20 reference */
53         {268, 268, 268},                        /* LD20 TV */
54         {189, 189, 189},                        /* LD20 TV C1 */
55         {268, 268 + 252, /* No CH2 */},         /* LD21 reference */
56         {268, 268 + 202, /* No CH2 */},         /* LD21 TV */
57 };
58
59 static const int ddrphy_dllrecalib[DRAM_BOARD_NR][DRAM_CH_NR] = {
60         {268 - 378, 268 - 263, 268 - 378},      /* LD20 reference */
61         {268 - 378, 268 - 263, 268 - 378},      /* LD20 TV */
62         {268 - 378, 268 - 263, 268 - 378},      /* LD20 TV C1 */
63         {268 - 212, 268 - 536, /* No CH2 */},   /* LD21 reference */
64         {268 - 212, 268 - 536, /* No CH2 */},   /* LD21 TV */
65 };
66
67 static const u32 ddrphy_phy_pad_ctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
68         {0x50B840B1, 0x50B840B1, 0x50B840B1},   /* LD20 reference */
69         {0x50BB40B1, 0x50BB40B1, 0x50BB40B1},   /* LD20 TV */
70         {0x50BB40B1, 0x50BB40B1, 0x50BB40B1},   /* LD20 TV C1 */
71         {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 reference */
72         {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 TV */
73 };
74
75 static const u32 ddrphy_scl_gate_timing[DRAM_CH_NR] = {
76         0x00000140, 0x00000180, 0x00000140
77 };
78
79 static const int ddrphy_op_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
80         { /* LD20 reference */
81                 {
82                         2, 1, 0, 1, 2, 1, 1, 1,
83                         2, 1, 1, 2, 1, 1, 1, 1,
84                         1, 2, 1, 1, 1, 2, 1, 1,
85                         2, 2, 0, 1, 1, 2, 2, 1,
86                 },
87                 {
88                         1, 1, 0, 1, 2, 2, 1, 1,
89                         1, 1, 1, 1, 1, 1, 1, 1,
90                         1, 1, 0, 0, 1, 1, 0, 0,
91                         0, 1, 1, 1, 2, 1, 2, 1,
92                 },
93                 {
94                         2, 2, 0, 2, 1, 1, 2, 1,
95                         1, 1, 0, 1, 1, -1, 1, 1,
96                         2, 2, 2, 2, 1, 1, 1, 1,
97                         1, 1, 1, 0, 2, 2, 1, 2,
98                 },
99         },
100         { /* LD20 TV */
101                 {
102                         2, 1, 0, 1, 2, 1, 1, 1,
103                         2, 1, 1, 2, 1, 1, 1, 1,
104                         1, 2, 1, 1, 1, 2, 1, 1,
105                         2, 2, 0, 1, 1, 2, 2, 1,
106                 },
107                 {
108                         1, 1, 0, 1, 2, 2, 1, 1,
109                         1, 1, 1, 1, 1, 1, 1, 1,
110                         1, 1, 0, 0, 1, 1, 0, 0,
111                         0, 1, 1, 1, 2, 1, 2, 1,
112                 },
113                 {
114                         2, 2, 0, 2, 1, 1, 2, 1,
115                         1, 1, 0, 1, 1, -1, 1, 1,
116                         2, 2, 2, 2, 1, 1, 1, 1,
117                         1, 1, 1, 0, 2, 2, 1, 2,
118                 },
119         },
120         { /* LD20 TV C1 */
121                 {
122                         2, 1, 0, 1, 2, 1, 1, 1,
123                         2, 1, 1, 2, 1, 1, 1, 1,
124                         1, 2, 1, 1, 1, 2, 1, 1,
125                         2, 2, 0, 1, 1, 2, 2, 1,
126                 },
127                 {
128                         1, 1, 0, 1, 2, 2, 1, 1,
129                         1, 1, 1, 1, 1, 1, 1, 1,
130                         1, 1, 0, 0, 1, 1, 0, 0,
131                         0, 1, 1, 1, 2, 1, 2, 1,
132                 },
133                 {
134                         2, 2, 0, 2, 1, 1, 2, 1,
135                         1, 1, 0, 1, 1, -1, 1, 1,
136                         2, 2, 2, 2, 1, 1, 1, 1,
137                         1, 1, 1, 0, 2, 2, 1, 2,
138                 },
139         },
140         { /* LD21 reference */
141                 {
142                         1, 1, 0, 1, 1, 1, 1, 1,
143                         1, 0, 0, 0, 1, 1, 0, 2,
144                         1, 1, 0, 0, 1, 1, 1, 1,
145                         1, 0, 0, 0, 1, 0, 0, 1,
146                 },
147                 {       1, 0, 2, 1, 1, 1, 1, 0,
148                         1, 0, 0, 1, 0, 1, 0, 0,
149                         1, 0, 1, 0, 1, 1, 1, 0,
150                         1, 1, 1, 1, 0, 1, 0, 0,
151                 },
152                 /* No CH2 */
153         },
154         { /* LD21 TV */
155                 {
156                         1, 1, 0, 1, 1, 1, 1, 1,
157                         1, 0, 0, 0, 1, 1, 0, 2,
158                         1, 1, 0, 0, 1, 1, 1, 1,
159                         1, 0, 0, 0, 1, 0, 0, 1,
160                 },
161                 {       1, 0, 2, 1, 1, 1, 1, 0,
162                         1, 0, 0, 1, 0, 1, 0, 0,
163                         1, 0, 1, 0, 1, 1, 1, 0,
164                         1, 1, 1, 1, 0, 1, 0, 0,
165                 },
166                 /* No CH2 */
167         },
168 };
169
170 static int ddrphy_ip_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
171         { /* LD20 reference */
172                 {
173                         3, 3, 3, 2, 3, 2, 0, 2,
174                         2, 3, 3, 1, 2, 2, 2, 2,
175                         2, 2, 2, 2, 0, 1, 1, 1,
176                         2, 2, 2, 2, 3, 0, 2, 2,
177                 },
178                 {
179                         2, 2, 1, 1, -1, 1, 1, 1,
180                         2, 0, 2, 2, 2, 1, 0, 2,
181                         2, 1, 2, 1, 0, 1, 1, 1,
182                         2, 2, 2, 2, 2, 2, 2, 2,
183                 },
184                 {
185                         2, 2, 3, 2, 1, 2, 2, 2,
186                         2, 3, 4, 2, 3, 4, 3, 3,
187                         2, 2, 1, 2, 1, 1, 1, 1,
188                         2, 2, 2, 2, 1, 2, 2, 1,
189                 },
190         },
191         { /* LD20 TV */
192                 {
193                         3, 3, 3, 2, 3, 2, 0, 2,
194                         2, 3, 3, 1, 2, 2, 2, 2,
195                         2, 2, 2, 2, 0, 1, 1, 1,
196                         2, 2, 2, 2, 3, 0, 2, 2,
197                 },
198                 {
199                         2, 2, 1, 1, -1, 1, 1, 1,
200                         2, 0, 2, 2, 2, 1, 0, 2,
201                         2, 1, 2, 1, 0, 1, 1, 1,
202                         2, 2, 2, 2, 2, 2, 2, 2,
203                 },
204                 {
205                         2, 2, 3, 2, 1, 2, 2, 2,
206                         2, 3, 4, 2, 3, 4, 3, 3,
207                         2, 2, 1, 2, 1, 1, 1, 1,
208                         2, 2, 2, 2, 1, 2, 2, 1,
209                 },
210         },
211         { /* LD20 TV C1 */
212                 {
213                         3, 3, 3, 2, 3, 2, 0, 2,
214                         2, 3, 3, 1, 2, 2, 2, 2,
215                         2, 2, 2, 2, 0, 1, 1, 1,
216                         2, 2, 2, 2, 3, 0, 2, 2,
217                 },
218                 {
219                         2, 2, 1, 1, -1, 1, 1, 1,
220                         2, 0, 2, 2, 2, 1, 0, 2,
221                         2, 1, 2, 1, 0, 1, 1, 1,
222                         2, 2, 2, 2, 2, 2, 2, 2,
223                 },
224                 {
225                         2, 2, 3, 2, 1, 2, 2, 2,
226                         2, 3, 4, 2, 3, 4, 3, 3,
227                         2, 2, 1, 2, 1, 1, 1, 1,
228                         2, 2, 2, 2, 1, 2, 2, 1,
229                 },
230         },
231         { /* LD21 reference */
232                 {
233                         2, 2, 2, 2, 1, 2, 2, 2,
234                         2, 3, 3, 2, 2, 2, 2, 2,
235                         2, 1, 2, 2, 1, 1, 1, 1,
236                         2, 2, 2, 3, 1, 2, 2, 2,
237                 },
238                 {
239                         3, 4, 4, 1, 0, 1, 1, 1,
240                         1, 2, 1, 2, 2, 3, 3, 2,
241                         1, 0, 2, 1, 1, 0, 1, 0,
242                         0, 1, 0, 0, 1, 1, 0, 1,
243                 },
244                 /* No CH2 */
245         },
246         { /* LD21 TV */
247                 {
248                         2, 2, 2, 2, 1, 2, 2, 2,
249                         2, 3, 3, 2, 2, 2, 2, 2,
250                         2, 1, 2, 2, 1, 1, 1, 1,
251                         2, 2, 2, 3, 1, 2, 2, 2,
252                 },
253                 {
254                         3, 4, 4, 1, 0, 1, 1, 1,
255                         1, 2, 1, 2, 2, 3, 3, 2,
256                         1, 0, 2, 1, 1, 0, 1, 0,
257                         0, 1, 0, 0, 1, 1, 0, 1,
258                 },
259                 /* No CH2 */
260         },
261 };
262
263 /* DDR PHY */
264 static void ddrphy_select_lane(void __iomem *phy_base, unsigned int lane,
265                                unsigned int bit)
266 {
267         WARN_ON(lane >= (1 << PHY_LANE_SEL_LANE_WIDTH));
268         WARN_ON(bit >= (1 << PHY_LANE_SEL_BIT_WIDTH));
269
270         writel((bit << PHY_LANE_SEL_BIT_SHIFT) |
271                (lane << PHY_LANE_SEL_LANE_SHIFT),
272                phy_base + PHY_LANE_SEL);
273 }
274
275 static void ddrphy_init(void __iomem *phy_base, enum dram_board board, int ch)
276 {
277         writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
278         while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1)))
279                 cpu_relax();
280         writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
281
282         writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3);
283         writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1);
284         ddrphy_select_lane(phy_base, 0, 0);
285         writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
286         writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
287         ddrphy_select_lane(phy_base, 6, 0);
288         writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
289         writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
290         ddrphy_select_lane(phy_base, 12, 0);
291         writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
292         writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
293         ddrphy_select_lane(phy_base, 18, 0);
294         writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
295         writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
296         writel(0x00000001, phy_base + PHY_SCL_WINDOW_TRIM);
297         writel(0x00000000, phy_base + PHY_UNQ_ANALOG_DLL_1);
298         writel(ddrphy_phy_pad_ctrl[board][ch], phy_base + PHY_PAD_CTRL);
299         writel(0x00000070, phy_base + PHY_VREF_TRAINING);
300         writel(0x01000075, phy_base + PHY_SCL_CONFIG_1);
301         writel(0x00000501, phy_base + PHY_SCL_CONFIG_2);
302         writel(0x00000000, phy_base + PHY_SCL_CONFIG_3);
303         writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
304         writel(0x00000000, phy_base + PHY_SCL_CONFIG_4);
305         writel(ddrphy_scl_gate_timing[ch], phy_base + PHY_SCL_GATE_TIMING);
306         writel(0x02a000a0, phy_base + PHY_WRLVL_DYN_ODT);
307         writel(0x00840004, phy_base + PHY_WRLVL_ON_OFF);
308         writel(0x0000020d, phy_base + PHY_DLL_ADRCTRL);
309         ddrphy_select_lane(phy_base, 0, 0);
310         writel(0x0000008d, phy_base + PHY_DLL_TRIM_CLK);
311         writel(0xa800100d, phy_base + PHY_DLL_RECALIB);
312         writel(0x00005076, phy_base + PHY_SCL_LATENCY);
313 }
314
315 static int ddrphy_to_dly_step(void __iomem *phy_base, unsigned int freq,
316                               int delay)
317 {
318         int mdl;
319
320         mdl = (readl(phy_base + PHY_DLL_ADRCTRL) & PHY_DLL_ADRCTRL_MDL_MASK) >>
321                                                 PHY_DLL_ADRCTRL_MDL_SHIFT;
322
323         return DIV_ROUND_CLOSEST((long)freq * delay * mdl, 2 * 1000000L);
324 }
325
326 static void ddrphy_set_delay(void __iomem *phy_base, unsigned int reg,
327                              u32 mask, u32 incr, int dly_step)
328 {
329         u32 tmp;
330
331         tmp = readl(phy_base + reg);
332         tmp &= ~mask;
333         tmp |= min_t(u32, abs(dly_step), mask);
334
335         if (dly_step >= 0)
336                 tmp |= incr;
337         else
338                 tmp &= ~incr;
339
340         writel(tmp, phy_base + reg);
341 }
342
343 static void ddrphy_set_dll_recalib(void __iomem *phy_base, int dly_step)
344 {
345         ddrphy_set_delay(phy_base, PHY_DLL_RECALIB,
346                          PHY_DLL_RECALIB_TRIM_MASK, PHY_DLL_RECALIB_INCR,
347                          dly_step);
348 }
349
350 static void ddrphy_set_dll_adrctrl(void __iomem *phy_base, int dly_step)
351 {
352         ddrphy_set_delay(phy_base, PHY_DLL_ADRCTRL,
353                          PHY_DLL_ADRCTRL_TRIM_MASK, PHY_DLL_ADRCTRL_INCR,
354                          dly_step);
355 }
356
357 static void ddrphy_set_dll_trim_clk(void __iomem *phy_base, int dly_step)
358 {
359         ddrphy_select_lane(phy_base, 0, 0);
360
361         ddrphy_set_delay(phy_base, PHY_DLL_TRIM_CLK,
362                          PHY_DLL_TRIM_CLK_MASK, PHY_DLL_TRIM_CLK_INCR,
363                          dly_step);
364 }
365
366 static void ddrphy_init_tail(void __iomem *phy_base, enum dram_board board,
367                              unsigned int freq, int ch)
368 {
369         int step;
370
371         step = ddrphy_to_dly_step(phy_base, freq, ddrphy_adrctrl[board][ch]);
372         ddrphy_set_dll_adrctrl(phy_base, step);
373
374         step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dlltrimclk[board][ch]);
375         ddrphy_set_dll_trim_clk(phy_base, step);
376
377         step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dllrecalib[board][ch]);
378         ddrphy_set_dll_recalib(phy_base, step);
379 }
380
381 static void ddrphy_shift_one_dq(void __iomem *phy_base, unsigned int reg,
382                                 u32 mask, u32 incr, int shift_val)
383 {
384         u32 tmp;
385         int val;
386
387         tmp = readl(phy_base + reg);
388
389         val = tmp & mask;
390         if (!(tmp & incr))
391                 val = -val;
392
393         val += shift_val;
394
395         tmp &= ~(incr | mask);
396         tmp |= min_t(u32, abs(val), mask);
397         if (val >= 0)
398                 tmp |= incr;
399
400         writel(tmp, phy_base + reg);
401 }
402
403 static void ddrphy_shift_dq(void __iomem *phy_base, unsigned int reg,
404                             u32 mask, u32 incr, u32 override,
405                             const int *shift_val_array)
406 {
407         u32 tmp;
408         int dx, bit;
409
410         tmp = readl(phy_base + reg);
411         tmp |= override;
412         writel(tmp, phy_base + reg);
413
414         for (dx = 0; dx < 4; dx++) {
415                 for (bit = 0; bit < 8; bit++) {
416                         ddrphy_select_lane(phy_base,
417                                            (PHY_BITLVL_DLY_WIDTH + 1) * dx,
418                                            bit);
419
420                         ddrphy_shift_one_dq(phy_base, reg, mask, incr,
421                                             shift_val_array[dx * 8 + bit]);
422                 }
423         }
424
425         ddrphy_select_lane(phy_base, 0, 0);
426 }
427
428 static int ddrphy_training(void __iomem *phy_base, enum dram_board board,
429                            int ch)
430 {
431         writel(0x0000000f, phy_base + PHY_WRLVL_AUTOINC_TRIM);
432         writel(0x00010000, phy_base + PHY_DLL_TRIM_2);
433         writel(0x50000000, phy_base + PHY_SCL_START);
434
435         while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
436                 cpu_relax();
437
438         writel(0x00000000, phy_base + PHY_DISABLE_GATING_FOR_SCL);
439         writel(0xff00ff00, phy_base + PHY_SCL_DATA_0);
440         writel(0xff00ff00, phy_base + PHY_SCL_DATA_1);
441         writel(0xFBF8FFFF, phy_base + PHY_SCL_START_ADDR);
442         writel(0x11000000, phy_base + PHY_SCL_START);
443
444         while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
445                 cpu_relax();
446
447         writel(0xFBF0FFFF, phy_base + PHY_SCL_START_ADDR);
448         writel(0x30500000, phy_base + PHY_SCL_START);
449
450         while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
451                 cpu_relax();
452
453         writel(0x00000001, phy_base + PHY_DISABLE_GATING_FOR_SCL);
454         writel(0x00000010, phy_base + PHY_SCL_MAIN_CLK_DELTA);
455         writel(0x789b3de0, phy_base + PHY_SCL_DATA_0);
456         writel(0xf10e4a56, phy_base + PHY_SCL_DATA_1);
457         writel(0x11000000, phy_base + PHY_SCL_START);
458
459         while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
460                 cpu_relax();
461
462         writel(0x34000000, phy_base + PHY_SCL_START);
463
464         while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
465                 cpu_relax();
466
467         writel(0x00000003, phy_base + PHY_DISABLE_GATING_FOR_SCL);
468
469         writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
470         writel(0x00003270, phy_base + PHY_DYNAMIC_BIT_LVL);
471         writel(0x011BD0C4, phy_base + PHY_DSCL_CNT);
472
473         /* shift ip_dq trim */
474         ddrphy_shift_dq(phy_base,
475                         PHY_IP_DQ_DQS_BITWISE_TRIM,
476                         PHY_IP_DQ_DQS_BITWISE_TRIM_MASK,
477                         PHY_IP_DQ_DQS_BITWISE_TRIM_INC,
478                         PHY_IP_DQ_DQS_BITWISE_TRIM_OVERRIDE,
479                         ddrphy_ip_dq_shift_val[board][ch]);
480
481         /* shift op_dq trim */
482         ddrphy_shift_dq(phy_base,
483                         PHY_OP_DQ_DM_DQS_BITWISE_TRIM,
484                         PHY_OP_DQ_DM_DQS_BITWISE_TRIM_MASK,
485                         PHY_OP_DQ_DM_DQS_BITWISE_TRIM_INC,
486                         PHY_OP_DQ_DM_DQS_BITWISE_TRIM_OVERRIDE,
487                         ddrphy_op_dq_shift_val[board][ch]);
488
489         return 0;
490 }
491
492 /* UMC */
493 static const u32 umc_initctla[DRAM_FREQ_NR] = {0x71016D11};
494 static const u32 umc_initctlb[DRAM_FREQ_NR] = {0x07E390AC};
495 static const u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF};
496 static const u32 umc_drmmr0[DRAM_FREQ_NR] = {0x00000114};
497 static const u32 umc_drmmr2[DRAM_FREQ_NR] = {0x000002a0};
498
499 static const u32 umc_memconf0a[DRAM_FREQ_NR][DRAM_SZ_NR] = {
500         /*  256MB       512MB */
501         {0x00000601, 0x00000801},       /* 1866 MHz */
502 };
503
504 static const u32 umc_memconf0b[DRAM_FREQ_NR][DRAM_SZ_NR] = {
505         /*  256MB       512MB */
506         {0x00000120, 0x00000130},       /* 1866 MHz */
507 };
508
509 static const u32 umc_memconfch[DRAM_FREQ_NR][DRAM_SZ_NR] = {
510         /*  256MB       512MB */
511         {0x00033603, 0x00033803},       /* 1866 MHz */
512 };
513
514 static const u32 umc_cmdctla[DRAM_FREQ_NR] = {0x060D0D20};
515 static const u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x2D211C08};
516 static const u32 umc_cmdctlc[DRAM_FREQ_NR] = {0x00150C04};
517 static const u32 umc_cmdctle[DRAM_FREQ_NR][DRAM_SZ_NR] = {
518         /*  256MB       512MB */
519         {0x0049071D, 0x0078071D},       /* 1866 MHz */
520 };
521
522 static const u32 umc_rdatactl[DRAM_FREQ_NR] = {0x00000610};
523 static const u32 umc_wdatactl[DRAM_FREQ_NR] = {0x00000204};
524 static const u32 umc_odtctl[DRAM_FREQ_NR] = {0x02000002};
525 static const u32 umc_dataset[DRAM_FREQ_NR] = {0x04000000};
526
527 static const u32 umc_flowctla[DRAM_FREQ_NR] = {0x0081E01E};
528 static const u32 umc_directbusctrla[DRAM_CH_NR] = {
529         0x00000000, 0x00000001, 0x00000001
530 };
531
532 static void umc_poll_phy_init_complete(void __iomem *dc_base)
533 {
534         /* Wait for PHY Init Complete */
535         while (!(readl(dc_base + UMC_DFISTCTLC) & BIT(0)))
536                 cpu_relax();
537 }
538
539 static int umc_dc_init(void __iomem *dc_base, unsigned int freq,
540                        unsigned long size, int ch)
541 {
542         enum dram_freq freq_e;
543         enum dram_size size_e;
544
545         switch (freq) {
546         case 1866:
547                 freq_e = DRAM_FREQ_1866M;
548                 break;
549         default:
550                 pr_err("unsupported DRAM frequency %ud MHz\n", freq);
551                 return -EINVAL;
552         }
553
554         switch (size) {
555         case 0:
556                 return 0;
557         case SZ_256M:
558                 size_e = DRAM_SZ_256M;
559                 break;
560         case SZ_512M:
561                 size_e = DRAM_SZ_512M;
562                 break;
563         default:
564                 pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
565                        size, ch);
566                 return -EINVAL;
567         }
568
569         writel(0x00000001, dc_base + UMC_DFICSOVRRD);
570         writel(0x00000000, dc_base + UMC_DFITURNOFF);
571
572         writel(umc_initctla[freq_e], dc_base + UMC_INITCTLA);
573         writel(umc_initctlb[freq_e], dc_base + UMC_INITCTLB);
574         writel(umc_initctlc[freq_e], dc_base + UMC_INITCTLC);
575
576         writel(umc_drmmr0[freq_e], dc_base + UMC_DRMMR0);
577         writel(0x00000004, dc_base + UMC_DRMMR1);
578         writel(umc_drmmr2[freq_e], dc_base + UMC_DRMMR2);
579         writel(0x00000000, dc_base + UMC_DRMMR3);
580
581         writel(umc_memconf0a[freq_e][size_e], dc_base + UMC_MEMCONF0A);
582         writel(umc_memconf0b[freq_e][size_e], dc_base + UMC_MEMCONF0B);
583         writel(umc_memconfch[freq_e][size_e], dc_base + UMC_MEMCONFCH);
584         writel(0x00000008, dc_base + UMC_MEMMAPSET);
585
586         writel(umc_cmdctla[freq_e], dc_base + UMC_CMDCTLA);
587         writel(umc_cmdctlb[freq_e], dc_base + UMC_CMDCTLB);
588         writel(umc_cmdctlc[freq_e], dc_base + UMC_CMDCTLC);
589         writel(umc_cmdctle[freq_e][size_e], dc_base + UMC_CMDCTLE);
590
591         writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
592         writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D1);
593
594         writel(umc_wdatactl[freq_e], dc_base + UMC_WDATACTL_D0);
595         writel(umc_wdatactl[freq_e], dc_base + UMC_WDATACTL_D1);
596         writel(umc_odtctl[freq_e], dc_base + UMC_ODTCTL_D0);
597         writel(umc_odtctl[freq_e], dc_base + UMC_ODTCTL_D1);
598         writel(umc_dataset[freq_e], dc_base + UMC_DATASET);
599
600         writel(0x00400020, dc_base + UMC_DCCGCTL);
601         writel(0x00000003, dc_base + UMC_ACSSETA);
602         writel(0x00000103, dc_base + UMC_FLOWCTLG);
603         writel(0x00010200, dc_base + UMC_ACSSETB);
604
605         writel(umc_flowctla[freq_e], dc_base + UMC_FLOWCTLA);
606         writel(0x00004444, dc_base + UMC_FLOWCTLC);
607         writel(0x00000000, dc_base + UMC_DFICUPDCTLA);
608
609         writel(0x00202000, dc_base + UMC_FLOWCTLB);
610         writel(0x00000000, dc_base + UMC_BSICMAPSET);
611         writel(0x00000000, dc_base + UMC_ERRMASKA);
612         writel(0x00000000, dc_base + UMC_ERRMASKB);
613
614         writel(umc_directbusctrla[ch], dc_base + UMC_DIRECTBUSCTRLA);
615
616         writel(0x00000001, dc_base + UMC_INITSET);
617         /* Wait for PHY Init Complete */
618         while (readl(dc_base + UMC_INITSTAT) & BIT(0))
619                 cpu_relax();
620
621         writel(0x2A0A0A00, dc_base + UMC_SPCSETB);
622         writel(0x00000000, dc_base + UMC_DFICSOVRRD);
623
624         return 0;
625 }
626
627 static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base,
628                        enum dram_board board, unsigned int freq,
629                        unsigned long size, int ch)
630 {
631         void __iomem *dc_base = umc_ch_base + 0x00011000;
632         void __iomem *phy_base = phy_ch_base;
633         int ret;
634
635         /* PHY Update Mode (ON) */
636         writel(0x8000003f, dc_base + UMC_DFIPUPDCTLA);
637
638         /* deassert PHY reset signals */
639         writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST,
640                dc_base + UMC_DIOCTLA);
641
642         ddrphy_init(phy_base, board, ch);
643
644         umc_poll_phy_init_complete(dc_base);
645
646         ddrphy_init_tail(phy_base, board, freq, ch);
647
648         ret = umc_dc_init(dc_base, freq, size, ch);
649         if (ret)
650                 return ret;
651
652         ret = ddrphy_training(phy_base, board, ch);
653         if (ret)
654                 return ret;
655
656         return 0;
657 }
658
659 static void um_init(void __iomem *um_base)
660 {
661         writel(0x000000ff, um_base + UMC_MBUS0);
662         writel(0x000000ff, um_base + UMC_MBUS1);
663         writel(0x000000ff, um_base + UMC_MBUS2);
664         writel(0x00000001, um_base + UMC_MBUS3);
665         writel(0x00000001, um_base + UMC_MBUS4);
666         writel(0x00000001, um_base + UMC_MBUS5);
667         writel(0x00000001, um_base + UMC_MBUS6);
668         writel(0x00000001, um_base + UMC_MBUS7);
669         writel(0x00000001, um_base + UMC_MBUS8);
670         writel(0x00000001, um_base + UMC_MBUS9);
671         writel(0x00000001, um_base + UMC_MBUS10);
672 }
673
674 int uniphier_ld20_umc_init(const struct uniphier_board_data *bd)
675 {
676         void __iomem *um_base = (void __iomem *)0x5b600000;
677         void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
678         void __iomem *phy_ch_base = (void __iomem *)0x6e200000;
679         enum dram_board board;
680         int ch, ret;
681
682         switch (UNIPHIER_BD_BOARD_GET_TYPE(bd->flags)) {
683         case UNIPHIER_BD_BOARD_LD20_REF:
684                 board = DRAM_BOARD_LD20_REF;
685                 break;
686         case UNIPHIER_BD_BOARD_LD20_GLOBAL:
687                 board = DRAM_BOARD_LD20_GLOBAL;
688                 break;
689         case UNIPHIER_BD_BOARD_LD20_C1:
690                 board = DRAM_BOARD_LD20_C1;
691                 break;
692         case UNIPHIER_BD_BOARD_LD21_REF:
693                 board = DRAM_BOARD_LD21_REF;
694                 break;
695         case UNIPHIER_BD_BOARD_LD21_GLOBAL:
696                 board = DRAM_BOARD_LD21_GLOBAL;
697                 break;
698         default:
699                 pr_err("unsupported board type %d\n",
700                        UNIPHIER_BD_BOARD_GET_TYPE(bd->flags));
701                 return -EINVAL;
702         }
703
704         for (ch = 0; ch < bd->dram_nr_ch; ch++) {
705                 unsigned long size = bd->dram_ch[ch].size;
706                 unsigned int width = bd->dram_ch[ch].width;
707
708                 ret = umc_ch_init(umc_ch_base, phy_ch_base, board,
709                                   bd->dram_freq, size / (width / 16), ch);
710                 if (ret) {
711                         pr_err("failed to initialize UMC ch%d\n", ch);
712                         return ret;
713                 }
714
715                 umc_ch_base += 0x00200000;
716                 phy_ch_base += 0x00004000;
717         }
718
719         um_init(um_base);
720
721         return 0;
722 }