blob: 1fdd119a3fef16ae76191d8b053e5286cc992d93 [file] [log] [blame]
Masahiro Yamada063eb1e2016-04-21 14:43:18 +09001/*
2 * Copyright (C) 2016 Socionext Inc.
3 *
Masahiro Yamada40ee94e2016-09-17 03:33:12 +09004 * based on commit a3c28918e86ad57127cf07bf8b32950cab20c03c of Diag
Masahiro Yamada063eb1e2016-04-21 14:43:18 +09005 *
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"
Masahiro Yamada900117b2016-05-24 21:13:59 +090018#include "umc64-regs.h"
Masahiro Yamada063eb1e2016-04-21 14:43:18 +090019
20#define DRAM_CH_NR 3
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090021#define CONFIG_DDR_FREQ 1866
Masahiro Yamada063eb1e2016-04-21 14:43:18 +090022
23enum dram_freq {
24 DRAM_FREQ_1866M,
25 DRAM_FREQ_NR,
26};
27
28enum dram_size {
29 DRAM_SZ_256M,
30 DRAM_SZ_512M,
31 DRAM_SZ_NR,
32};
33
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090034enum dram_board { /* board type */
35 DRAM_BOARD_LD20_REF, /* LD20 reference */
36 DRAM_BOARD_LD20_GLOBAL, /* LD20 TV */
37 DRAM_BOARD_LD21_REF, /* LD21 reference */
38 DRAM_BOARD_LD21_GLOBAL, /* LD21 TV */
39 DRAM_BOARD_NR,
40};
41
42#define MSK_PHY_LANE_SEL 0x000000FF
43#define MSK_BIT_SEL 0x00000F00
44#define MSK_DLL_MAS_DLY 0xFF000000
45#define MSK_MAS_DLY 0x7F000000
46#define MSK_DLLS_TRIM_CLK 0x000000FF
47
48#define PHY_DLL_MAS_DLY_WIDTH 8
49#define PHY_SLV_DLY_WIDTH 6
50
51static void ddrphy_maskwritel(u32 data, u32 mask, void *addr)
52{
53 u32 value;
54
55 value = (readl(addr) & ~mask) | (data & mask);
56 writel(value, addr);
57}
58
59static u32 ddrphy_maskreadl(u32 mask, void *addr)
60{
61 return readl(addr) & mask;
62}
63
64/* set phy_lane_sel.phy_lane_sel */
65static void ddrphy_set_phy_lane_sel(int val, void __iomem *phy_base)
66{
67 ddrphy_maskwritel(val, MSK_PHY_LANE_SEL, phy_base + PHY_LANE_SEL);
68}
69
70/* set phy_lane_sel.bit_sel */
71static void ddrphy_set_bit_sel(int bit, void __iomem *phy_base)
72{
73 ddrphy_maskwritel(bit << 8, MSK_BIT_SEL, phy_base + PHY_LANE_SEL);
74}
75
76/* Calculating step for PUB-byte */
77static int ddrphy_hpstep(int delay, void __iomem *phy_base)
78{
79 int mdl, freq;
80
81 freq = CONFIG_DDR_FREQ; /* FIXME */
82 mdl = ddrphy_maskreadl(MSK_DLL_MAS_DLY, phy_base + PHY_DLL_ADRCTRL) >> 24;
83
84 return DIV_ROUND_CLOSEST(freq * delay * mdl, 2 * 1000000);
85}
86
87static void ddrphy_set_dll_trim_clk(int delay_ckoffset, void __iomem *phy_base)
88{
89 u8 ck_step; /* ckoffset_step for clock */
90 u32 ck_step_all;
91
92 /* CK-Offset */
93 if (delay_ckoffset >= 0) {
94 /* shift + direction */
95 ck_step = min(ddrphy_hpstep(delay_ckoffset, phy_base), 127);
96 ck_step_all = ((0x1<<(PHY_SLV_DLY_WIDTH + 1))|ck_step);
97 } else{
98 /* shift - direction */
99 ck_step = min(ddrphy_hpstep(-1*delay_ckoffset, phy_base), 127);
100 ck_step_all = ck_step;
101 }
102
103 ddrphy_set_phy_lane_sel(0, phy_base);
104 ddrphy_maskwritel(ck_step_all, MSK_DLLS_TRIM_CLK, phy_base + PHY_DLL_TRIM_CLK);
105}
106
107static void ddrphy_set_dll_recalib(int delay_qoffset, u32 recalib_cnt,
108 u8 disable_recalib, u8 ctr_start_val,
109 void __iomem *phy_base)
110{
111 u8 dlls_trim_adrctrl_ma, incr_dly_adrctrl_ma; /* qoffset_step and flag for inc/dec */
112 u32 recalib_all; /* all fields of register dll_recalib */
113
114 /* Q-Offset */
115 if (delay_qoffset >= 0) {
116 dlls_trim_adrctrl_ma = min(ddrphy_hpstep(delay_qoffset, phy_base), 63);
117 incr_dly_adrctrl_ma = 0x1;
118 } else {
119 dlls_trim_adrctrl_ma = min(ddrphy_hpstep(-1*delay_qoffset, phy_base), 63);
120 incr_dly_adrctrl_ma = 0x0;
121 }
122
123 recalib_all = ((ctr_start_val & 0xf) << 28) |
124 (incr_dly_adrctrl_ma << 27) |
125 ((disable_recalib & 0x1) << 26) |
126 ((recalib_cnt & 0x3ffff) << 8) |
127 (dlls_trim_adrctrl_ma & 0x3f);
128
129 /* write value for all bits other than bit[7:6] */
130 ddrphy_maskwritel(recalib_all, ~0xc0, phy_base + PHY_DLL_RECALIB);
131}
132
133static void ddrphy_set_dll_adrctrl(int delay_qoffset, u8 override_adrctrl,
134 void __iomem *phy_base)
135{
136 u8 dlls_trim_adrctrl, incr_dly_adrctrl; /* qoffset_step for clock */
137 u32 adrctrl_all;
138
139 if (delay_qoffset >= 0) {
140 dlls_trim_adrctrl = min(ddrphy_hpstep(delay_qoffset, phy_base), 63);
141 incr_dly_adrctrl = 0x1;
142 } else {
143 dlls_trim_adrctrl = min(ddrphy_hpstep(-delay_qoffset, phy_base), 63);
144 incr_dly_adrctrl = 0x0;
145 }
146
147 adrctrl_all = (incr_dly_adrctrl << 9) |
148 ((override_adrctrl & 0x1) << 8) |
149 dlls_trim_adrctrl;
150
151 ddrphy_maskwritel(adrctrl_all, 0x33f, phy_base + PHY_DLL_ADRCTRL);
152}
153
154/* dio */
155static int dio_adrctrl_0[DRAM_BOARD_NR][DRAM_CH_NR] = {
156 {268-262, 268-263, 268-378}, /* LD20 reference */
157 {268-262, 268-263, 268-378}, /* LD20 TV */
158 {268-212, 268-268, 0}, /* LD21 reference */
159 {268-212, 268-268, 0}, /* LD21 TV */
160};
161static int dio_dlltrimclk_0[DRAM_BOARD_NR][DRAM_CH_NR] = {
162 {268, 268, 268}, /* LD20 reference */
163 {268, 268, 268}, /* LD20 TV */
164 {268, 268+252, 0}, /* LD21 reference */
165 {268, 268+202, 0}, /* LD21 TV */
166};
167static int dio_dllrecalib_0[DRAM_BOARD_NR][DRAM_CH_NR] = {
168 {268-378, 268-263, 268-378}, /* LD20 reference */
169 {268-378, 268-263, 268-378}, /* LD20 TV */
170 {268-212, 268-536, 0}, /* LD21 reference */
171 {268-212, 268-536, 0}, /* LD21 TV */
172};
173
174static u32 dio_phy_pad_ctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
175 {0x50B840B1, 0x50B840B1, 0x50B840B1}, /* LD20 reference */
176 {0x50BB40B1, 0x50BB40B1, 0x50BB40B1}, /* LD20 TV */
177 {0x50BB40B4, 0x50B840B1, 0x50BB40B1}, /* LD21 reference */
178 {0x50BB40B4, 0x50B840B1, 0x50BB40B1}, /* LD21 TV */
179};
180
181static u32 dio_scl_gate_timing[DRAM_CH_NR] = {0x00000140, 0x00000180, 0x00000140};
182
183static int dio_op_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
184 { /* LD20 reference */
185 {
186 2, 1, 0, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1,
187 1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 0, 1, 1, 2, 2, 1,
188 },
189 {
190 1, 1, 0, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
191 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 2, 1, 2, 1,
192 },
193 {
194 2, 2, 0, 2, 1, 1, 2, 1, 1, 1, 0, 1, 1, -1, 1, 1,
195 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 1, 2,
196 },
197 },
198 { /* LD20 TV */
199 {
200 2, 1, 0, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1,
201 1, 2, 1, 1, 1, 2, 1, 1, 2, 2, 0, 1, 1, 2, 2, 1,
202 },
203 {
204 1, 1, 0, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
205 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 2, 1, 2, 1,
206 },
207 {
208 2, 2, 0, 2, 1, 1, 2, 1, 1, 1, 0, 1, 1, -1, 1, 1,
209 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 1, 2,
210 },
211 },
212 { /* LD21 reference */
213 {
214 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 2,
215 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1,
216 },
217 { 1, 0, 2, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0,
218 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0,
219 },
220 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
222 },
223 },
224 { /* LD21 TV */
225 {
226 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 2,
227 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1,
228 },
229 { 1, 0, 2, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0,
230 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0,
231 },
232 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
234 },
235 },
236};
237static int dio_ip_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
238 { /* LD20 reference */
239 {
240 3, 3, 3, 2, 3, 2, 0, 2, 2, 3, 3, 1, 2, 2, 2, 2,
241 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 3, 0, 2, 2,
242 },
243 {
244 2, 2, 1, 1, -1, 1, 1, 1, 2, 0, 2, 2, 2, 1, 0, 2,
245 2, 1, 2, 1, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
246 },
247 {
248 2, 2, 3, 2, 1, 2, 2, 2, 2, 3, 4, 2, 3, 4, 3, 3,
249 2, 2, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1,
250 },
251 },
252 { /* LD20 TV */
253 {
254 3, 3, 3, 2, 3, 2, 0, 2, 2, 3, 3, 1, 2, 2, 2, 2,
255 2, 2, 2, 2, 0, 1, 1, 1, 2, 2, 2, 2, 3, 0, 2, 2,
256 },
257 {
258 2, 2, 1, 1, -1, 1, 1, 1, 2, 0, 2, 2, 2, 1, 0, 2,
259 2, 1, 2, 1, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
260 },
261 {
262 2, 2, 3, 2, 1, 2, 2, 2, 2, 3, 4, 2, 3, 4, 3, 3,
263 2, 2, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1,
264 },
265 },
266 { /* LD21 reference */
267 {
268 2, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2,
269 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 3, 1, 2, 2, 2,
270 },
271 {
272 3, 4, 4, 1, 0, 1, 1, 1, 1, 2, 1, 2, 2, 3, 3, 2,
273 1, 0, 2, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1,
274 },
275 {
276 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
277 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
278 },
279 },
280 { /* LD21 TV */
281 {
282 2, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2,
283 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 3, 1, 2, 2, 2,
284 },
285 {
286 3, 4, 4, 1, 0, 1, 1, 1, 1, 2, 1, 2, 2, 3, 3, 2,
287 1, 0, 2, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1,
288 },
289 {
290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
292 },
293 },
294};
295
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900296/* umc */
297static u32 umc_initctla[DRAM_FREQ_NR] = {0x71016D11};
298static u32 umc_initctlb[DRAM_FREQ_NR] = {0x07E390AC};
299static u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF};
300static u32 umc_drmmr0[DRAM_FREQ_NR] = {0x00000114};
301static u32 umc_drmmr2[DRAM_FREQ_NR] = {0x000002a0};
302
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900303static u32 umc_memconf0a[DRAM_FREQ_NR][DRAM_SZ_NR] = {
304 /* 256MB 512MB */
305 {0x00000601, 0x00000801}, /* 1866 MHz */
306};
307static u32 umc_memconf0b[DRAM_FREQ_NR][DRAM_SZ_NR] = {
308 /* 256MB 512MB */
309 {0x00000120, 0x00000130}, /* 1866 MHz */
310};
311static u32 umc_memconfch[DRAM_FREQ_NR][DRAM_SZ_NR] = {
312 /* 256MB 512MB */
313 {0x00033603, 0x00033803}, /* 1866 MHz */
314};
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900315static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x060D0D20};
316static u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x2D211C08};
317static u32 umc_cmdctlc[DRAM_FREQ_NR] = {0x00150C04};
318static u32 umc_cmdctle[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900319 /* 256MB 512MB */
320 {0x0049071D, 0x0078071D}, /* 1866 MHz */
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900321};
322
323static u32 umc_rdatactl_d0[DRAM_FREQ_NR] = {0x00000610};
324static u32 umc_rdatactl_d1[DRAM_FREQ_NR] = {0x00000610};
325static u32 umc_wdatactl_d0[DRAM_FREQ_NR] = {0x00000204};
326static u32 umc_wdatactl_d1[DRAM_FREQ_NR] = {0x00000204};
327static u32 umc_odtctl_d0[DRAM_FREQ_NR] = {0x02000002};
328static u32 umc_odtctl_d1[DRAM_FREQ_NR] = {0x02000002};
329static u32 umc_dataset[DRAM_FREQ_NR] = {0x04000000};
330
331static u32 umc_flowctla[DRAM_FREQ_NR] = {0x0081E01E};
332static u32 umc_directbusctrla[DRAM_CH_NR] = {
333 0x00000000, 0x00000001, 0x00000001
334};
335
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900336/* polling function for PHY Init Complete */
337static void ddrphy_init_complete(void __iomem *dc_base)
338{
339 /* Wait for PHY Init Complete */
340 while (!(readl(dc_base + UMC_DFISTCTLC) & BIT(0)))
341 cpu_relax();
342}
343
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900344/* DDR PHY */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900345static void ddrphy_init(void __iomem *phy_base, void __iomem *dc_base,
346 enum dram_freq freq, enum dram_board board, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900347{
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900348 writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
349 while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1)))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900350 cpu_relax();
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900351 writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900352
353 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3);
354 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1);
355 writel(0x00000000, phy_base + PHY_LANE_SEL);
356 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
357 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
358 writel(0x00000006, phy_base + PHY_LANE_SEL);
359 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
360 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
361 writel(0x0000000c, phy_base + PHY_LANE_SEL);
362 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
363 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
364 writel(0x00000012, phy_base + PHY_LANE_SEL);
365 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
366 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
367 writel(0x00000001, phy_base + PHY_SCL_WINDOW_TRIM);
368 writel(0x00000000, phy_base + PHY_UNQ_ANALOG_DLL_1);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900369 writel(dio_phy_pad_ctrl[board][ch], phy_base + PHY_PAD_CTRL);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900370 writel(0x00000070, phy_base + PHY_VREF_TRAINING);
371 writel(0x01000075, phy_base + PHY_SCL_CONFIG_1);
372 writel(0x00000501, phy_base + PHY_SCL_CONFIG_2);
373 writel(0x00000000, phy_base + PHY_SCL_CONFIG_3);
374 writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
375 writel(0x00000000, phy_base + PHY_SCL_CONFIG_4);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900376 writel(dio_scl_gate_timing[ch], phy_base + PHY_SCL_GATE_TIMING);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900377 writel(0x02a000a0, phy_base + PHY_WRLVL_DYN_ODT);
378 writel(0x00840004, phy_base + PHY_WRLVL_ON_OFF);
379 writel(0x0000020d, phy_base + PHY_DLL_ADRCTRL);
380 writel(0x00000000, phy_base + PHY_LANE_SEL);
381 writel(0x0000008d, phy_base + PHY_DLL_TRIM_CLK);
382 writel(0xa800100d, phy_base + PHY_DLL_RECALIB);
383 writel(0x00005076, phy_base + PHY_SCL_LATENCY);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900384
385 ddrphy_init_complete(dc_base);
386
387 ddrphy_set_dll_adrctrl(dio_adrctrl_0[board][ch], 0, phy_base);
388 ddrphy_set_dll_trim_clk(dio_dlltrimclk_0[board][ch], phy_base);
389 ddrphy_set_dll_recalib(dio_dllrecalib_0[board][ch], 0x10, 0, 0xa,
390 phy_base);
391}
392
393static void ddrphy_shift_dq(u32 reg_mask, u32 reg_addr, int shift_val,
394 void __iomem *phy_base)
395{
396 u32 reg_val;
397 int dq_val;
398
399 reg_val = ddrphy_maskreadl(reg_mask, phy_base + reg_addr) & 0x7f;
400 dq_val = reg_val & 0x3f;
401
402 if ((reg_val & 0x40) == 0x00)
403 dq_val = -1 * dq_val;
404
405 /* value shift*/
406 dq_val = dq_val + shift_val;
407
408 if (dq_val >= 0)
409 reg_val = 0x40 + (dq_val & 0x3f);
410 else
411 reg_val = ((-1 * dq_val) & 0x3f);
412
413 ddrphy_maskwritel(reg_val, reg_mask, phy_base + reg_addr);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900414}
415
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900416static void ddrphy_shift(void __iomem *phy_base, enum dram_board board, int ch)
417{
418 u32 dx, bit;
419
420 /* set override = 1 */
421 ddrphy_maskwritel(MSK_OVERRIDE, MSK_OVERRIDE,
422 phy_base + PHY_OP_DQ_DM_DQS_BITWISE_TRIM);
423 ddrphy_maskwritel(MSK_OVERRIDE, MSK_OVERRIDE,
424 phy_base + PHY_IP_DQ_DQS_BITWISE_TRIM);
425
426 for (dx = 0; dx < 4; dx++) {
427 /* set byte to PHY_LANE_SEL.phy_lane_sel= dx * (PHY_BITLVL_DLY_WIDTH+1) */
428 ddrphy_set_phy_lane_sel(dx * (PHY_BITLVL_DLY_WIDTH + 1),
429 phy_base);
430
431 for (bit = 0; bit < 8; bit++) {
432 ddrphy_set_bit_sel(bit, phy_base);
433
434 /* shift write reg value*/
435 ddrphy_shift_dq(MSK_OP_DQ_DM_DQS_BITWISE_TRIM,
436 PHY_OP_DQ_DM_DQS_BITWISE_TRIM,
437 dio_op_dq_shift_val[board][ch][dx * 8 + bit],
438 phy_base);
439 /* shift read reg value */
440 ddrphy_shift_dq(MSK_IP_DQ_DQS_BITWISE_TRIM,
441 PHY_IP_DQ_DQS_BITWISE_TRIM,
442 dio_ip_dq_shift_val[board][ch][dx * 8 + bit],
443 phy_base);
444 }
445
446 }
447 ddrphy_set_phy_lane_sel(0, phy_base);
448 ddrphy_set_bit_sel(0, phy_base);
449}
450
451static int ddrphy_training(void __iomem *phy_base, enum dram_board board,
452 int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900453{
454 writel(0x0000000f, phy_base + PHY_WRLVL_AUTOINC_TRIM);
455 writel(0x00010000, phy_base + PHY_DLL_TRIM_2);
456 writel(0x50000000, phy_base + PHY_SCL_START);
457
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900458 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900459 cpu_relax();
460
461 writel(0x00000000, phy_base + PHY_DISABLE_GATING_FOR_SCL);
462 writel(0xff00ff00, phy_base + PHY_SCL_DATA_0);
463 writel(0xff00ff00, phy_base + PHY_SCL_DATA_1);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900464 writel(0xFBF8FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900465 writel(0x11000000, phy_base + PHY_SCL_START);
466
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900467 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900468 cpu_relax();
469
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900470 writel(0xFBF0FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900471 writel(0x30500000, phy_base + PHY_SCL_START);
472
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900473 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900474 cpu_relax();
475
476 writel(0x00000001, phy_base + PHY_DISABLE_GATING_FOR_SCL);
477 writel(0x00000010, phy_base + PHY_SCL_MAIN_CLK_DELTA);
478 writel(0x789b3de0, phy_base + PHY_SCL_DATA_0);
479 writel(0xf10e4a56, phy_base + PHY_SCL_DATA_1);
480 writel(0x11000000, phy_base + PHY_SCL_START);
481
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900482 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900483 cpu_relax();
484
485 writel(0x34000000, phy_base + PHY_SCL_START);
486
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900487 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900488 cpu_relax();
489
490 writel(0x00000003, phy_base + PHY_DISABLE_GATING_FOR_SCL);
491
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900492 writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
493 writel(0x00003270, phy_base + PHY_DYNAMIC_BIT_LVL);
494 writel(0x011BD0C4, phy_base + PHY_DSCL_CNT);
495
496 /* shift ip_dq, op_dq trim */
497 ddrphy_shift(phy_base, board, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900498 return 0;
499}
500
501static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq,
502 unsigned long size, int ch)
503{
504 enum dram_size size_e;
505
506 switch (size) {
507 case 0:
508 return 0;
509 case SZ_256M:
510 size_e = DRAM_SZ_256M;
511 break;
512 case SZ_512M:
513 size_e = DRAM_SZ_512M;
514 break;
515 default:
516 pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
517 size, ch);
518 return -EINVAL;
519 }
520
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900521 writel(0x00000001, dc_base + UMC_DFICSOVRRD);
522 writel(0x00000000, dc_base + UMC_DFITURNOFF);
523
524 writel(umc_initctla[freq], dc_base + UMC_INITCTLA);
525 writel(umc_initctlb[freq], dc_base + UMC_INITCTLB);
526 writel(umc_initctlc[freq], dc_base + UMC_INITCTLC);
527
528 writel(umc_drmmr0[freq], dc_base + UMC_DRMMR0);
529 writel(0x00000004, dc_base + UMC_DRMMR1);
530 writel(umc_drmmr2[freq], dc_base + UMC_DRMMR2);
531 writel(0x00000000, dc_base + UMC_DRMMR3);
532
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900533 writel(umc_memconf0a[freq][size_e], dc_base + UMC_MEMCONF0A);
534 writel(umc_memconf0b[freq][size_e], dc_base + UMC_MEMCONF0B);
535 writel(umc_memconfch[freq][size_e], dc_base + UMC_MEMCONFCH);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900536 writel(0x00000008, dc_base + UMC_MEMMAPSET);
537
538 writel(umc_cmdctla[freq], dc_base + UMC_CMDCTLA);
539 writel(umc_cmdctlb[freq], dc_base + UMC_CMDCTLB);
540 writel(umc_cmdctlc[freq], dc_base + UMC_CMDCTLC);
541 writel(umc_cmdctle[freq][size_e], dc_base + UMC_CMDCTLE);
542
543 writel(umc_rdatactl_d0[freq], dc_base + UMC_RDATACTL_D0);
544 writel(umc_rdatactl_d1[freq], dc_base + UMC_RDATACTL_D1);
545
546 writel(umc_wdatactl_d0[freq], dc_base + UMC_WDATACTL_D0);
547 writel(umc_wdatactl_d1[freq], dc_base + UMC_WDATACTL_D1);
548 writel(umc_odtctl_d0[freq], dc_base + UMC_ODTCTL_D0);
549 writel(umc_odtctl_d1[freq], dc_base + UMC_ODTCTL_D1);
550 writel(umc_dataset[freq], dc_base + UMC_DATASET);
551
552 writel(0x00400020, dc_base + UMC_DCCGCTL);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900553 writel(0x00000003, dc_base + UMC_ACSSETA);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900554 writel(0x00000103, dc_base + UMC_FLOWCTLG);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900555 writel(0x00010200, dc_base + UMC_ACSSETB);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900556
557 writel(umc_flowctla[freq], dc_base + UMC_FLOWCTLA);
558 writel(0x00004444, dc_base + UMC_FLOWCTLC);
559 writel(0x00000000, dc_base + UMC_DFICUPDCTLA);
560
561 writel(0x00202000, dc_base + UMC_FLOWCTLB);
562 writel(0x00000000, dc_base + UMC_BSICMAPSET);
563 writel(0x00000000, dc_base + UMC_ERRMASKA);
564 writel(0x00000000, dc_base + UMC_ERRMASKB);
565
566 writel(umc_directbusctrla[ch], dc_base + UMC_DIRECTBUSCTRLA);
567
568 writel(0x00000001, dc_base + UMC_INITSET);
569 /* Wait for PHY Init Complete */
570 while (readl(dc_base + UMC_INITSTAT) & BIT(0))
571 cpu_relax();
572
573 writel(0x2A0A0A00, dc_base + UMC_SPCSETB);
574 writel(0x00000000, dc_base + UMC_DFICSOVRRD);
575
576 return 0;
577}
578
579static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900580 enum dram_freq freq, enum dram_board board,
581 unsigned long size, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900582{
583 void __iomem *dc_base = umc_ch_base + 0x00011000;
584 void __iomem *phy_base = phy_ch_base;
585 int ret;
586
587 /* PHY Update Mode (ON) */
588 writel(0x8000003f, dc_base + UMC_DFIPUPDCTLA);
589
590 /* deassert PHY reset signals */
591 writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST,
592 dc_base + UMC_DIOCTLA);
593
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900594 ddrphy_init(phy_base, dc_base, freq, board, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900595
596 ret = umc_dc_init(dc_base, freq, size, ch);
597 if (ret)
598 return ret;
599
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900600 ret = ddrphy_training(phy_base, board, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900601 if (ret)
602 return ret;
603
604 return 0;
605}
606
607static void um_init(void __iomem *um_base)
608{
609 writel(0x000000ff, um_base + UMC_MBUS0);
610 writel(0x000000ff, um_base + UMC_MBUS1);
611 writel(0x000000ff, um_base + UMC_MBUS2);
612 writel(0x00000001, um_base + UMC_MBUS3);
613 writel(0x00000001, um_base + UMC_MBUS4);
614 writel(0x00000001, um_base + UMC_MBUS5);
615 writel(0x00000001, um_base + UMC_MBUS6);
616 writel(0x00000001, um_base + UMC_MBUS7);
617 writel(0x00000001, um_base + UMC_MBUS8);
618 writel(0x00000001, um_base + UMC_MBUS9);
619 writel(0x00000001, um_base + UMC_MBUS10);
620}
621
622int uniphier_ld20_umc_init(const struct uniphier_board_data *bd)
623{
624 void __iomem *um_base = (void __iomem *)0x5b600000;
625 void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
626 void __iomem *phy_ch_base = (void __iomem *)0x6e200000;
627 enum dram_freq freq;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900628 enum dram_board board;
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900629 int ch, ret;
630
631 switch (bd->dram_freq) {
632 case 1866:
633 freq = DRAM_FREQ_1866M;
634 break;
635 default:
636 pr_err("unsupported DRAM frequency %d MHz\n", bd->dram_freq);
637 return -EINVAL;
638 }
639
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900640 switch (UNIPHIER_BD_BOARD_GET_TYPE(bd->flags)) {
641 case UNIPHIER_BD_BOARD_LD20_REF:
642 board = DRAM_BOARD_LD20_REF;
643 break;
644 case UNIPHIER_BD_BOARD_LD20_GLOBAL:
645 board = DRAM_BOARD_LD20_GLOBAL;
646 break;
647 case UNIPHIER_BD_BOARD_LD21_REF:
648 board = DRAM_BOARD_LD21_REF;
649 break;
650 case UNIPHIER_BD_BOARD_LD21_GLOBAL:
651 board = DRAM_BOARD_LD21_GLOBAL;
652 break;
653 default:
654 pr_err("unsupported board type %d\n",
655 UNIPHIER_BD_BOARD_GET_TYPE(bd->flags));
656 return -EINVAL;
657 }
658
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900659 for (ch = 0; ch < bd->dram_nr_ch; ch++) {
660 unsigned long size = bd->dram_ch[ch].size;
661 unsigned int width = bd->dram_ch[ch].width;
662
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900663 ret = umc_ch_init(umc_ch_base, phy_ch_base, freq, board,
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900664 size / (width / 16), ch);
665 if (ret) {
666 pr_err("failed to initialize UMC ch%d\n", ch);
667 return ret;
668 }
669
670 umc_ch_base += 0x00200000;
671 phy_ch_base += 0x00004000;
672 }
673
674 um_init(um_base);
675
676 return 0;
677}