]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/arm/mach-uniphier/dram/umc-ld20.c
ARM: uniphier: remove unneeded parentheses
[people/ms/u-boot.git] / arch / arm / mach-uniphier / dram / umc-ld20.c
1 /*
2 * Copyright (C) 2016 Socionext Inc.
3 *
4 * based on commit 5e1cb0f1caeabc6c99469dd997cb6b4f46834443 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 "ddruqphy-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 }