blob: b8c0f59e171368ae40abb0269713063158172729 [file] [log] [blame]
Masahiro Yamada063eb1e2016-04-21 14:43:18 +09001/*
2 * Copyright (C) 2016 Socionext Inc.
3 *
Masahiro Yamadabf4266e2016-10-27 23:47:02 +09004 * based on commit a7a36122aa072fe1bb06e02b73b3634b7a6c555a 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"
Masahiro Yamada5ffc49b2016-10-27 23:47:03 +090017#include "ddruqphy-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
21
22enum dram_freq {
23 DRAM_FREQ_1866M,
24 DRAM_FREQ_NR,
25};
26
27enum dram_size {
28 DRAM_SZ_256M,
29 DRAM_SZ_512M,
30 DRAM_SZ_NR,
31};
32
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090033enum dram_board { /* board type */
34 DRAM_BOARD_LD20_REF, /* LD20 reference */
35 DRAM_BOARD_LD20_GLOBAL, /* LD20 TV */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090036 DRAM_BOARD_LD20_C1, /* LD20 TV C1 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090037 DRAM_BOARD_LD21_REF, /* LD21 reference */
38 DRAM_BOARD_LD21_GLOBAL, /* LD21 TV */
39 DRAM_BOARD_NR,
40};
41
Masahiro Yamadab1224f32016-10-08 13:25:24 +090042/* PHY */
43static 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 */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090046 {268 - 262, 268 - 263, 268 - 378}, /* LD20 TV C1 */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090047 {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 reference */
48 {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090049};
Masahiro Yamadab1224f32016-10-08 13:25:24 +090050
51static const int ddrphy_dlltrimclk[DRAM_BOARD_NR][DRAM_CH_NR] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090052 {268, 268, 268}, /* LD20 reference */
53 {268, 268, 268}, /* LD20 TV */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090054 {189, 189, 189}, /* LD20 TV C1 */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090055 {268, 268 + 252, /* No CH2 */}, /* LD21 reference */
56 {268, 268 + 202, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090057};
Masahiro Yamadab1224f32016-10-08 13:25:24 +090058
59static 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 */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090062 {268 - 378, 268 - 263, 268 - 378}, /* LD20 TV C1 */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090063 {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 reference */
64 {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090065};
66
Masahiro Yamadab1224f32016-10-08 13:25:24 +090067static const u32 ddrphy_phy_pad_ctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090068 {0x50B840B1, 0x50B840B1, 0x50B840B1}, /* LD20 reference */
69 {0x50BB40B1, 0x50BB40B1, 0x50BB40B1}, /* LD20 TV */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090070 {0x50BB40B1, 0x50BB40B1, 0x50BB40B1}, /* LD20 TV C1 */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090071 {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 reference */
72 {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090073};
74
Masahiro Yamadab1224f32016-10-08 13:25:24 +090075static const u32 ddrphy_scl_gate_timing[DRAM_CH_NR] = {
76 0x00000140, 0x00000180, 0x00000140
77};
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090078
Masahiro Yamadab1224f32016-10-08 13:25:24 +090079static const int ddrphy_op_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090080 { /* LD20 reference */
81 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090082 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090086 },
87 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090088 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090092 },
93 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090094 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090098 },
99 },
100 { /* LD20 TV */
101 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900102 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900106 },
107 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900108 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900112 },
113 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900114 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900118 },
119 },
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900120 { /* 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 },
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900140 { /* LD21 reference */
141 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900142 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900146 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900147 { 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900151 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900152 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900153 },
154 { /* LD21 TV */
155 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900156 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900160 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900161 { 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900165 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900166 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900167 },
168};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900169
170static int ddrphy_ip_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900171 { /* LD20 reference */
172 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900173 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900177 },
178 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900179 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900183 },
184 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900185 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900189 },
190 },
191 { /* LD20 TV */
192 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900193 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900197 },
198 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900199 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900203 },
204 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900205 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900209 },
210 },
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900211 { /* 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 },
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900231 { /* LD21 reference */
232 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900233 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900237 },
238 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900239 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900243 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900244 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900245 },
246 { /* LD21 TV */
247 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900248 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900252 },
253 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900254 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,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900258 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900259 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900260 },
261};
262
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900263/* DDR PHY */
264static void ddrphy_select_lane(void __iomem *phy_base, unsigned int lane,
265 unsigned int bit)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900266{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900267 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);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900273}
274
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900275static void ddrphy_init(void __iomem *phy_base, enum dram_board board, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900276{
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900277 writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
278 while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1)))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900279 cpu_relax();
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900280 writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900281
282 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3);
283 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900284 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900285 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
286 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900287 ddrphy_select_lane(phy_base, 6, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900288 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
289 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900290 ddrphy_select_lane(phy_base, 12, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900291 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
292 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900293 ddrphy_select_lane(phy_base, 18, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900294 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);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900298 writel(ddrphy_phy_pad_ctrl[board][ch], phy_base + PHY_PAD_CTRL);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900299 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);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900305 writel(ddrphy_scl_gate_timing[ch], phy_base + PHY_SCL_GATE_TIMING);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900306 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);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900309 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900310 writel(0x0000008d, phy_base + PHY_DLL_TRIM_CLK);
311 writel(0xa800100d, phy_base + PHY_DLL_RECALIB);
312 writel(0x00005076, phy_base + PHY_SCL_LATENCY);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900313}
314
315static int ddrphy_to_dly_step(void __iomem *phy_base, unsigned int freq,
316 int delay)
317{
318 int mdl;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900319
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900320 mdl = (readl(phy_base + PHY_DLL_ADRCTRL) & PHY_DLL_ADRCTRL_MDL_MASK) >>
321 PHY_DLL_ADRCTRL_MDL_SHIFT;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900322
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900323 return DIV_ROUND_CLOSEST((long)freq * delay * mdl, 2 * 1000000L);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900324}
325
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900326static void ddrphy_set_delay(void __iomem *phy_base, unsigned int reg,
327 u32 mask, u32 incr, int dly_step)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900328{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900329 u32 tmp;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900330
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900331 tmp = readl(phy_base + reg);
332 tmp &= ~mask;
333 tmp |= min_t(u32, abs(dly_step), mask);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900334
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900335 if (dly_step >= 0)
336 tmp |= incr;
337 else
338 tmp &= ~incr;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900339
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900340 writel(tmp, phy_base + reg);
341}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900342
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900343static 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}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900349
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900350static 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);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900355}
356
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900357static void ddrphy_set_dll_trim_clk(void __iomem *phy_base, int dly_step)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900358{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900359 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900360
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900361 ddrphy_set_delay(phy_base, PHY_DLL_TRIM_CLK,
362 PHY_DLL_TRIM_CLK_MASK, PHY_DLL_TRIM_CLK_INCR,
363 dly_step);
364}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900365
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900366static void ddrphy_init_tail(void __iomem *phy_base, enum dram_board board,
367 unsigned int freq, int ch)
368{
369 int step;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900370
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900371 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
381static 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
403static 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++) {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900415 for (bit = 0; bit < 8; bit++) {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900416 ddrphy_select_lane(phy_base,
417 (PHY_BITLVL_DLY_WIDTH + 1) * dx,
418 bit);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900419
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900420 ddrphy_shift_one_dq(phy_base, reg, mask, incr,
421 shift_val_array[dx * 8 + bit]);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900422 }
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900423 }
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900424
425 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900426}
427
428static int ddrphy_training(void __iomem *phy_base, enum dram_board board,
429 int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900430{
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
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900435 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900436 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);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900441 writel(0xFBF8FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900442 writel(0x11000000, phy_base + PHY_SCL_START);
443
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900444 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900445 cpu_relax();
446
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900447 writel(0xFBF0FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900448 writel(0x30500000, phy_base + PHY_SCL_START);
449
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900450 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900451 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
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900459 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900460 cpu_relax();
461
462 writel(0x34000000, phy_base + PHY_SCL_START);
463
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900464 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900465 cpu_relax();
466
467 writel(0x00000003, phy_base + PHY_DISABLE_GATING_FOR_SCL);
468
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900469 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
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900473 /* 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
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900489 return 0;
490}
491
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900492/* UMC */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900493static const u32 umc_initctla[DRAM_FREQ_NR] = {0x71016D11};
494static const u32 umc_initctlb[DRAM_FREQ_NR] = {0x07E390AC};
495static const u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF};
496static const u32 umc_drmmr0[DRAM_FREQ_NR] = {0x00000114};
497static const u32 umc_drmmr2[DRAM_FREQ_NR] = {0x000002a0};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900498
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900499static const u32 umc_memconf0a[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900500 /* 256MB 512MB */
501 {0x00000601, 0x00000801}, /* 1866 MHz */
502};
503
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900504static const u32 umc_memconf0b[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900505 /* 256MB 512MB */
506 {0x00000120, 0x00000130}, /* 1866 MHz */
507};
508
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900509static const u32 umc_memconfch[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900510 /* 256MB 512MB */
511 {0x00033603, 0x00033803}, /* 1866 MHz */
512};
513
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900514static const u32 umc_cmdctla[DRAM_FREQ_NR] = {0x060D0D20};
515static const u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x2D211C08};
516static const u32 umc_cmdctlc[DRAM_FREQ_NR] = {0x00150C04};
517static const u32 umc_cmdctle[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900518 /* 256MB 512MB */
519 {0x0049071D, 0x0078071D}, /* 1866 MHz */
520};
521
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900522static const u32 umc_rdatactl[DRAM_FREQ_NR] = {0x00000610};
523static const u32 umc_wdatactl[DRAM_FREQ_NR] = {0x00000204};
524static const u32 umc_odtctl[DRAM_FREQ_NR] = {0x02000002};
525static const u32 umc_dataset[DRAM_FREQ_NR] = {0x04000000};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900526
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900527static const u32 umc_flowctla[DRAM_FREQ_NR] = {0x0081E01E};
528static const u32 umc_directbusctrla[DRAM_CH_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900529 0x00000000, 0x00000001, 0x00000001
530};
531
532static 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
539static int umc_dc_init(void __iomem *dc_base, unsigned int freq,
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900540 unsigned long size, int ch)
541{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900542 enum dram_freq freq_e;
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900543 enum dram_size size_e;
544
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900545 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
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900554 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
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900569 writel(0x00000001, dc_base + UMC_DFICSOVRRD);
570 writel(0x00000000, dc_base + UMC_DFITURNOFF);
571
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900572 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);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900575
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900576 writel(umc_drmmr0[freq_e], dc_base + UMC_DRMMR0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900577 writel(0x00000004, dc_base + UMC_DRMMR1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900578 writel(umc_drmmr2[freq_e], dc_base + UMC_DRMMR2);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900579 writel(0x00000000, dc_base + UMC_DRMMR3);
580
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900581 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);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900584 writel(0x00000008, dc_base + UMC_MEMMAPSET);
585
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900586 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);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900590
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900591 writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
592 writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D1);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900593
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900594 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);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900598 writel(umc_dataset[freq_e], dc_base + UMC_DATASET);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900599
600 writel(0x00400020, dc_base + UMC_DCCGCTL);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900601 writel(0x00000003, dc_base + UMC_ACSSETA);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900602 writel(0x00000103, dc_base + UMC_FLOWCTLG);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900603 writel(0x00010200, dc_base + UMC_ACSSETB);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900604
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900605 writel(umc_flowctla[freq_e], dc_base + UMC_FLOWCTLA);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900606 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
627static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base,
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900628 enum dram_board board, unsigned int freq,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900629 unsigned long size, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900630{
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
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900642 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);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900647
648 ret = umc_dc_init(dc_base, freq, size, ch);
649 if (ret)
650 return ret;
651
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900652 ret = ddrphy_training(phy_base, board, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900653 if (ret)
654 return ret;
655
656 return 0;
657}
658
659static 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
674int 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;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900679 enum dram_board board;
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900680 int ch, ret;
681
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900682 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;
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900689 case UNIPHIER_BD_BOARD_LD20_C1:
690 board = DRAM_BOARD_LD20_C1;
691 break;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900692 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
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900704 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
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900708 ret = umc_ch_init(umc_ch_base, phy_ch_base, board,
709 bd->dram_freq, size / (width / 16), ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900710 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}