blob: 61f62ae6d753876d7c167f1a48c31d2c186a07b9 [file] [log] [blame]
Masahiro Yamada063eb1e2016-04-21 14:43:18 +09001/*
2 * Copyright (C) 2016 Socionext Inc.
3 *
Wataru Okoshi50fda9d2017-01-18 16:24:38 +09004 * based on commit 1f6feb76e7f9753f51955444e422486521f9b3a3 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>
Masahiro Yamadae4e789d2017-01-21 18:05:24 +090011#include <linux/compat.h>
12#include <linux/errno.h>
Masahiro Yamada063eb1e2016-04-21 14:43:18 +090013#include <linux/io.h>
14#include <linux/sizes.h>
15#include <asm/processor.h>
16
17#include "../init.h"
Masahiro Yamada5ffc49b2016-10-27 23:47:03 +090018#include "ddruqphy-regs.h"
Masahiro Yamada900117b2016-05-24 21:13:59 +090019#include "umc64-regs.h"
Masahiro Yamada063eb1e2016-04-21 14:43:18 +090020
21#define DRAM_CH_NR 3
22
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 */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090037 DRAM_BOARD_LD20_C1, /* LD20 TV C1 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090038 DRAM_BOARD_LD21_REF, /* LD21 reference */
39 DRAM_BOARD_LD21_GLOBAL, /* LD21 TV */
40 DRAM_BOARD_NR,
41};
42
Masahiro Yamadab1224f32016-10-08 13:25:24 +090043/* PHY */
44static const int ddrphy_adrctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
45 {268 - 262, 268 - 263, 268 - 378}, /* LD20 reference */
46 {268 - 262, 268 - 263, 268 - 378}, /* LD20 TV */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090047 {268 - 262, 268 - 263, 268 - 378}, /* LD20 TV C1 */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090048 {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 reference */
49 {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090050};
Masahiro Yamadab1224f32016-10-08 13:25:24 +090051
52static const int ddrphy_dlltrimclk[DRAM_BOARD_NR][DRAM_CH_NR] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090053 {268, 268, 268}, /* LD20 reference */
54 {268, 268, 268}, /* LD20 TV */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090055 {189, 189, 189}, /* LD20 TV C1 */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090056 {268, 268 + 252, /* No CH2 */}, /* LD21 reference */
57 {268, 268 + 202, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090058};
Masahiro Yamadab1224f32016-10-08 13:25:24 +090059
60static const int ddrphy_dllrecalib[DRAM_BOARD_NR][DRAM_CH_NR] = {
61 {268 - 378, 268 - 263, 268 - 378}, /* LD20 reference */
62 {268 - 378, 268 - 263, 268 - 378}, /* LD20 TV */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090063 {268 - 378, 268 - 263, 268 - 378}, /* LD20 TV C1 */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090064 {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 reference */
65 {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090066};
67
Masahiro Yamadab1224f32016-10-08 13:25:24 +090068static const u32 ddrphy_phy_pad_ctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090069 {0x50B840B1, 0x50B840B1, 0x50B840B1}, /* LD20 reference */
70 {0x50BB40B1, 0x50BB40B1, 0x50BB40B1}, /* LD20 TV */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090071 {0x50BB40B1, 0x50BB40B1, 0x50BB40B1}, /* LD20 TV C1 */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090072 {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 reference */
73 {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090074};
75
Masahiro Yamadab1224f32016-10-08 13:25:24 +090076static const u32 ddrphy_scl_gate_timing[DRAM_CH_NR] = {
77 0x00000140, 0x00000180, 0x00000140
78};
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090079
Masahiro Yamadab1224f32016-10-08 13:25:24 +090080static const int ddrphy_op_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090081 { /* LD20 reference */
82 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090083 2, 1, 0, 1, 2, 1, 1, 1,
84 2, 1, 1, 2, 1, 1, 1, 1,
85 1, 2, 1, 1, 1, 2, 1, 1,
86 2, 2, 0, 1, 1, 2, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090087 },
88 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090089 1, 1, 0, 1, 2, 2, 1, 1,
90 1, 1, 1, 1, 1, 1, 1, 1,
91 1, 1, 0, 0, 1, 1, 0, 0,
92 0, 1, 1, 1, 2, 1, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090093 },
94 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090095 2, 2, 0, 2, 1, 1, 2, 1,
96 1, 1, 0, 1, 1, -1, 1, 1,
97 2, 2, 2, 2, 1, 1, 1, 1,
98 1, 1, 1, 0, 2, 2, 1, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090099 },
100 },
101 { /* LD20 TV */
102 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900103 2, 1, 0, 1, 2, 1, 1, 1,
104 2, 1, 1, 2, 1, 1, 1, 1,
105 1, 2, 1, 1, 1, 2, 1, 1,
106 2, 2, 0, 1, 1, 2, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900107 },
108 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900109 1, 1, 0, 1, 2, 2, 1, 1,
110 1, 1, 1, 1, 1, 1, 1, 1,
111 1, 1, 0, 0, 1, 1, 0, 0,
112 0, 1, 1, 1, 2, 1, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900113 },
114 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900115 2, 2, 0, 2, 1, 1, 2, 1,
116 1, 1, 0, 1, 1, -1, 1, 1,
117 2, 2, 2, 2, 1, 1, 1, 1,
118 1, 1, 1, 0, 2, 2, 1, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900119 },
120 },
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900121 { /* LD20 TV C1 */
122 {
123 2, 1, 0, 1, 2, 1, 1, 1,
124 2, 1, 1, 2, 1, 1, 1, 1,
125 1, 2, 1, 1, 1, 2, 1, 1,
126 2, 2, 0, 1, 1, 2, 2, 1,
127 },
128 {
129 1, 1, 0, 1, 2, 2, 1, 1,
130 1, 1, 1, 1, 1, 1, 1, 1,
131 1, 1, 0, 0, 1, 1, 0, 0,
132 0, 1, 1, 1, 2, 1, 2, 1,
133 },
134 {
135 2, 2, 0, 2, 1, 1, 2, 1,
136 1, 1, 0, 1, 1, -1, 1, 1,
137 2, 2, 2, 2, 1, 1, 1, 1,
138 1, 1, 1, 0, 2, 2, 1, 2,
139 },
140 },
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900141 { /* LD21 reference */
142 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900143 1, 1, 0, 1, 1, 1, 1, 1,
144 1, 0, 0, 0, 1, 1, 0, 2,
145 1, 1, 0, 0, 1, 1, 1, 1,
146 1, 0, 0, 0, 1, 0, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900147 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900148 { 1, 0, 2, 1, 1, 1, 1, 0,
149 1, 0, 0, 1, 0, 1, 0, 0,
150 1, 0, 1, 0, 1, 1, 1, 0,
151 1, 1, 1, 1, 0, 1, 0, 0,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900152 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900153 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900154 },
155 { /* LD21 TV */
156 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900157 1, 1, 0, 1, 1, 1, 1, 1,
158 1, 0, 0, 0, 1, 1, 0, 2,
159 1, 1, 0, 0, 1, 1, 1, 1,
160 1, 0, 0, 0, 1, 0, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900161 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900162 { 1, 0, 2, 1, 1, 1, 1, 0,
163 1, 0, 0, 1, 0, 1, 0, 0,
164 1, 0, 1, 0, 1, 1, 1, 0,
165 1, 1, 1, 1, 0, 1, 0, 0,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900166 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900167 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900168 },
169};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900170
171static int ddrphy_ip_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900172 { /* LD20 reference */
173 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900174 3, 3, 3, 2, 3, 2, 0, 2,
175 2, 3, 3, 1, 2, 2, 2, 2,
176 2, 2, 2, 2, 0, 1, 1, 1,
177 2, 2, 2, 2, 3, 0, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900178 },
179 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900180 2, 2, 1, 1, -1, 1, 1, 1,
181 2, 0, 2, 2, 2, 1, 0, 2,
182 2, 1, 2, 1, 0, 1, 1, 1,
183 2, 2, 2, 2, 2, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900184 },
185 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900186 2, 2, 3, 2, 1, 2, 2, 2,
187 2, 3, 4, 2, 3, 4, 3, 3,
188 2, 2, 1, 2, 1, 1, 1, 1,
189 2, 2, 2, 2, 1, 2, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900190 },
191 },
192 { /* LD20 TV */
193 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900194 3, 3, 3, 2, 3, 2, 0, 2,
195 2, 3, 3, 1, 2, 2, 2, 2,
196 2, 2, 2, 2, 0, 1, 1, 1,
197 2, 2, 2, 2, 3, 0, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900198 },
199 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900200 2, 2, 1, 1, -1, 1, 1, 1,
201 2, 0, 2, 2, 2, 1, 0, 2,
202 2, 1, 2, 1, 0, 1, 1, 1,
203 2, 2, 2, 2, 2, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900204 },
205 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900206 2, 2, 3, 2, 1, 2, 2, 2,
207 2, 3, 4, 2, 3, 4, 3, 3,
208 2, 2, 1, 2, 1, 1, 1, 1,
209 2, 2, 2, 2, 1, 2, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900210 },
211 },
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900212 { /* LD20 TV C1 */
213 {
214 3, 3, 3, 2, 3, 2, 0, 2,
215 2, 3, 3, 1, 2, 2, 2, 2,
216 2, 2, 2, 2, 0, 1, 1, 1,
217 2, 2, 2, 2, 3, 0, 2, 2,
218 },
219 {
220 2, 2, 1, 1, -1, 1, 1, 1,
221 2, 0, 2, 2, 2, 1, 0, 2,
222 2, 1, 2, 1, 0, 1, 1, 1,
223 2, 2, 2, 2, 2, 2, 2, 2,
224 },
225 {
226 2, 2, 3, 2, 1, 2, 2, 2,
227 2, 3, 4, 2, 3, 4, 3, 3,
228 2, 2, 1, 2, 1, 1, 1, 1,
229 2, 2, 2, 2, 1, 2, 2, 1,
230 },
231 },
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900232 { /* LD21 reference */
233 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900234 2, 2, 2, 2, 1, 2, 2, 2,
235 2, 3, 3, 2, 2, 2, 2, 2,
236 2, 1, 2, 2, 1, 1, 1, 1,
237 2, 2, 2, 3, 1, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900238 },
239 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900240 3, 4, 4, 1, 0, 1, 1, 1,
241 1, 2, 1, 2, 2, 3, 3, 2,
242 1, 0, 2, 1, 1, 0, 1, 0,
243 0, 1, 0, 0, 1, 1, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900244 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900245 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900246 },
247 { /* LD21 TV */
248 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900249 2, 2, 2, 2, 1, 2, 2, 2,
250 2, 3, 3, 2, 2, 2, 2, 2,
251 2, 1, 2, 2, 1, 1, 1, 1,
252 2, 2, 2, 3, 1, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900253 },
254 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900255 3, 4, 4, 1, 0, 1, 1, 1,
256 1, 2, 1, 2, 2, 3, 3, 2,
257 1, 0, 2, 1, 1, 0, 1, 0,
258 0, 1, 0, 0, 1, 1, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900259 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900260 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900261 },
262};
263
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900264/* DDR PHY */
265static void ddrphy_select_lane(void __iomem *phy_base, unsigned int lane,
266 unsigned int bit)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900267{
Masahiro Yamada5864e162016-12-05 18:31:37 +0900268 WARN_ON(lane >= 1 << PHY_LANE_SEL_LANE_WIDTH);
269 WARN_ON(bit >= 1 << PHY_LANE_SEL_BIT_WIDTH);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900270
271 writel((bit << PHY_LANE_SEL_BIT_SHIFT) |
272 (lane << PHY_LANE_SEL_LANE_SHIFT),
273 phy_base + PHY_LANE_SEL);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900274}
275
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900276static void ddrphy_init(void __iomem *phy_base, enum dram_board board, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900277{
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900278 writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
279 while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1)))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900280 cpu_relax();
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900281 writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900282
283 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3);
284 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900285 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900286 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
287 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900288 ddrphy_select_lane(phy_base, 6, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900289 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
290 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900291 ddrphy_select_lane(phy_base, 12, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900292 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
293 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900294 ddrphy_select_lane(phy_base, 18, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900295 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
296 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
297 writel(0x00000001, phy_base + PHY_SCL_WINDOW_TRIM);
298 writel(0x00000000, phy_base + PHY_UNQ_ANALOG_DLL_1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900299 writel(ddrphy_phy_pad_ctrl[board][ch], phy_base + PHY_PAD_CTRL);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900300 writel(0x00000070, phy_base + PHY_VREF_TRAINING);
301 writel(0x01000075, phy_base + PHY_SCL_CONFIG_1);
302 writel(0x00000501, phy_base + PHY_SCL_CONFIG_2);
303 writel(0x00000000, phy_base + PHY_SCL_CONFIG_3);
304 writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
305 writel(0x00000000, phy_base + PHY_SCL_CONFIG_4);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900306 writel(ddrphy_scl_gate_timing[ch], phy_base + PHY_SCL_GATE_TIMING);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900307 writel(0x02a000a0, phy_base + PHY_WRLVL_DYN_ODT);
308 writel(0x00840004, phy_base + PHY_WRLVL_ON_OFF);
309 writel(0x0000020d, phy_base + PHY_DLL_ADRCTRL);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900310 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900311 writel(0x0000008d, phy_base + PHY_DLL_TRIM_CLK);
312 writel(0xa800100d, phy_base + PHY_DLL_RECALIB);
313 writel(0x00005076, phy_base + PHY_SCL_LATENCY);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900314}
315
316static int ddrphy_to_dly_step(void __iomem *phy_base, unsigned int freq,
317 int delay)
318{
319 int mdl;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900320
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900321 mdl = (readl(phy_base + PHY_DLL_ADRCTRL) & PHY_DLL_ADRCTRL_MDL_MASK) >>
322 PHY_DLL_ADRCTRL_MDL_SHIFT;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900323
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900324 return DIV_ROUND_CLOSEST((long)freq * delay * mdl, 2 * 1000000L);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900325}
326
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900327static void ddrphy_set_delay(void __iomem *phy_base, unsigned int reg,
328 u32 mask, u32 incr, int dly_step)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900329{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900330 u32 tmp;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900331
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900332 tmp = readl(phy_base + reg);
333 tmp &= ~mask;
334 tmp |= min_t(u32, abs(dly_step), mask);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900335
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900336 if (dly_step >= 0)
337 tmp |= incr;
338 else
339 tmp &= ~incr;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900340
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900341 writel(tmp, phy_base + reg);
342}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900343
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900344static void ddrphy_set_dll_recalib(void __iomem *phy_base, int dly_step)
345{
346 ddrphy_set_delay(phy_base, PHY_DLL_RECALIB,
347 PHY_DLL_RECALIB_TRIM_MASK, PHY_DLL_RECALIB_INCR,
348 dly_step);
349}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900350
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900351static void ddrphy_set_dll_adrctrl(void __iomem *phy_base, int dly_step)
352{
353 ddrphy_set_delay(phy_base, PHY_DLL_ADRCTRL,
354 PHY_DLL_ADRCTRL_TRIM_MASK, PHY_DLL_ADRCTRL_INCR,
355 dly_step);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900356}
357
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900358static void ddrphy_set_dll_trim_clk(void __iomem *phy_base, int dly_step)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900359{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900360 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900361
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900362 ddrphy_set_delay(phy_base, PHY_DLL_TRIM_CLK,
363 PHY_DLL_TRIM_CLK_MASK, PHY_DLL_TRIM_CLK_INCR,
364 dly_step);
365}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900366
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900367static void ddrphy_init_tail(void __iomem *phy_base, enum dram_board board,
368 unsigned int freq, int ch)
369{
370 int step;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900371
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900372 step = ddrphy_to_dly_step(phy_base, freq, ddrphy_adrctrl[board][ch]);
373 ddrphy_set_dll_adrctrl(phy_base, step);
374
375 step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dlltrimclk[board][ch]);
376 ddrphy_set_dll_trim_clk(phy_base, step);
377
378 step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dllrecalib[board][ch]);
379 ddrphy_set_dll_recalib(phy_base, step);
380}
381
382static void ddrphy_shift_one_dq(void __iomem *phy_base, unsigned int reg,
383 u32 mask, u32 incr, int shift_val)
384{
385 u32 tmp;
386 int val;
387
388 tmp = readl(phy_base + reg);
389
390 val = tmp & mask;
391 if (!(tmp & incr))
392 val = -val;
393
394 val += shift_val;
395
396 tmp &= ~(incr | mask);
397 tmp |= min_t(u32, abs(val), mask);
398 if (val >= 0)
399 tmp |= incr;
400
401 writel(tmp, phy_base + reg);
402}
403
404static void ddrphy_shift_dq(void __iomem *phy_base, unsigned int reg,
405 u32 mask, u32 incr, u32 override,
406 const int *shift_val_array)
407{
408 u32 tmp;
409 int dx, bit;
410
411 tmp = readl(phy_base + reg);
412 tmp |= override;
413 writel(tmp, phy_base + reg);
414
415 for (dx = 0; dx < 4; dx++) {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900416 for (bit = 0; bit < 8; bit++) {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900417 ddrphy_select_lane(phy_base,
418 (PHY_BITLVL_DLY_WIDTH + 1) * dx,
419 bit);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900420
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900421 ddrphy_shift_one_dq(phy_base, reg, mask, incr,
422 shift_val_array[dx * 8 + bit]);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900423 }
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900424 }
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900425
426 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900427}
428
429static int ddrphy_training(void __iomem *phy_base, enum dram_board board,
430 int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900431{
432 writel(0x0000000f, phy_base + PHY_WRLVL_AUTOINC_TRIM);
433 writel(0x00010000, phy_base + PHY_DLL_TRIM_2);
434 writel(0x50000000, phy_base + PHY_SCL_START);
435
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900436 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900437 cpu_relax();
438
439 writel(0x00000000, phy_base + PHY_DISABLE_GATING_FOR_SCL);
440 writel(0xff00ff00, phy_base + PHY_SCL_DATA_0);
441 writel(0xff00ff00, phy_base + PHY_SCL_DATA_1);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900442 writel(0xFBF8FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900443 writel(0x11000000, phy_base + PHY_SCL_START);
444
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900445 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900446 cpu_relax();
447
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900448 writel(0xFBF0FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900449 writel(0x30500000, phy_base + PHY_SCL_START);
450
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900451 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900452 cpu_relax();
453
454 writel(0x00000001, phy_base + PHY_DISABLE_GATING_FOR_SCL);
455 writel(0x00000010, phy_base + PHY_SCL_MAIN_CLK_DELTA);
456 writel(0x789b3de0, phy_base + PHY_SCL_DATA_0);
457 writel(0xf10e4a56, phy_base + PHY_SCL_DATA_1);
458 writel(0x11000000, phy_base + PHY_SCL_START);
459
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900460 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900461 cpu_relax();
462
463 writel(0x34000000, phy_base + PHY_SCL_START);
464
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900465 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900466 cpu_relax();
467
468 writel(0x00000003, phy_base + PHY_DISABLE_GATING_FOR_SCL);
469
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900470 writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
471 writel(0x00003270, phy_base + PHY_DYNAMIC_BIT_LVL);
472 writel(0x011BD0C4, phy_base + PHY_DSCL_CNT);
473
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900474 /* shift ip_dq trim */
475 ddrphy_shift_dq(phy_base,
476 PHY_IP_DQ_DQS_BITWISE_TRIM,
477 PHY_IP_DQ_DQS_BITWISE_TRIM_MASK,
478 PHY_IP_DQ_DQS_BITWISE_TRIM_INC,
479 PHY_IP_DQ_DQS_BITWISE_TRIM_OVERRIDE,
480 ddrphy_ip_dq_shift_val[board][ch]);
481
482 /* shift op_dq trim */
483 ddrphy_shift_dq(phy_base,
484 PHY_OP_DQ_DM_DQS_BITWISE_TRIM,
485 PHY_OP_DQ_DM_DQS_BITWISE_TRIM_MASK,
486 PHY_OP_DQ_DM_DQS_BITWISE_TRIM_INC,
487 PHY_OP_DQ_DM_DQS_BITWISE_TRIM_OVERRIDE,
488 ddrphy_op_dq_shift_val[board][ch]);
489
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900490 return 0;
491}
492
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900493/* UMC */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900494static const u32 umc_initctla[DRAM_FREQ_NR] = {0x71016D11};
495static const u32 umc_initctlb[DRAM_FREQ_NR] = {0x07E390AC};
496static const u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF};
497static const u32 umc_drmmr0[DRAM_FREQ_NR] = {0x00000114};
498static const u32 umc_drmmr2[DRAM_FREQ_NR] = {0x000002a0};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900499
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900500static const u32 umc_memconf0a[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900501 /* 256MB 512MB */
502 {0x00000601, 0x00000801}, /* 1866 MHz */
503};
504
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900505static const u32 umc_memconf0b[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900506 /* 256MB 512MB */
507 {0x00000120, 0x00000130}, /* 1866 MHz */
508};
509
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900510static const u32 umc_memconfch[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900511 /* 256MB 512MB */
512 {0x00033603, 0x00033803}, /* 1866 MHz */
513};
514
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900515static const u32 umc_cmdctla[DRAM_FREQ_NR] = {0x060D0D20};
516static const u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x2D211C08};
517static const u32 umc_cmdctlc[DRAM_FREQ_NR] = {0x00150C04};
518static const u32 umc_cmdctle[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900519 /* 256MB 512MB */
520 {0x0049071D, 0x0078071D}, /* 1866 MHz */
521};
522
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900523static const u32 umc_rdatactl[DRAM_FREQ_NR] = {0x00000610};
524static const u32 umc_wdatactl[DRAM_FREQ_NR] = {0x00000204};
525static const u32 umc_odtctl[DRAM_FREQ_NR] = {0x02000002};
526static const u32 umc_dataset[DRAM_FREQ_NR] = {0x04000000};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900527
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900528static const u32 umc_flowctla[DRAM_FREQ_NR] = {0x0081E01E};
529static const u32 umc_directbusctrla[DRAM_CH_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900530 0x00000000, 0x00000001, 0x00000001
531};
532
533static void umc_poll_phy_init_complete(void __iomem *dc_base)
534{
535 /* Wait for PHY Init Complete */
536 while (!(readl(dc_base + UMC_DFISTCTLC) & BIT(0)))
537 cpu_relax();
538}
539
540static int umc_dc_init(void __iomem *dc_base, unsigned int freq,
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900541 unsigned long size, int ch)
542{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900543 enum dram_freq freq_e;
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900544 enum dram_size size_e;
545
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900546 switch (freq) {
547 case 1866:
548 freq_e = DRAM_FREQ_1866M;
549 break;
550 default:
551 pr_err("unsupported DRAM frequency %ud MHz\n", freq);
552 return -EINVAL;
553 }
554
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900555 switch (size) {
556 case 0:
557 return 0;
558 case SZ_256M:
559 size_e = DRAM_SZ_256M;
560 break;
561 case SZ_512M:
562 size_e = DRAM_SZ_512M;
563 break;
564 default:
565 pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
566 size, ch);
567 return -EINVAL;
568 }
569
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900570 writel(0x00000001, dc_base + UMC_DFICSOVRRD);
571 writel(0x00000000, dc_base + UMC_DFITURNOFF);
572
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900573 writel(umc_initctla[freq_e], dc_base + UMC_INITCTLA);
574 writel(umc_initctlb[freq_e], dc_base + UMC_INITCTLB);
575 writel(umc_initctlc[freq_e], dc_base + UMC_INITCTLC);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900576
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900577 writel(umc_drmmr0[freq_e], dc_base + UMC_DRMMR0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900578 writel(0x00000004, dc_base + UMC_DRMMR1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900579 writel(umc_drmmr2[freq_e], dc_base + UMC_DRMMR2);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900580 writel(0x00000000, dc_base + UMC_DRMMR3);
581
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900582 writel(umc_memconf0a[freq_e][size_e], dc_base + UMC_MEMCONF0A);
583 writel(umc_memconf0b[freq_e][size_e], dc_base + UMC_MEMCONF0B);
584 writel(umc_memconfch[freq_e][size_e], dc_base + UMC_MEMCONFCH);
Wataru Okoshi50fda9d2017-01-18 16:24:38 +0900585 writel(0x00000000, dc_base + UMC_MEMMAPSET);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900586
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900587 writel(umc_cmdctla[freq_e], dc_base + UMC_CMDCTLA);
588 writel(umc_cmdctlb[freq_e], dc_base + UMC_CMDCTLB);
589 writel(umc_cmdctlc[freq_e], dc_base + UMC_CMDCTLC);
590 writel(umc_cmdctle[freq_e][size_e], dc_base + UMC_CMDCTLE);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900591
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900592 writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
593 writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D1);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900594
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900595 writel(umc_wdatactl[freq_e], dc_base + UMC_WDATACTL_D0);
596 writel(umc_wdatactl[freq_e], dc_base + UMC_WDATACTL_D1);
597 writel(umc_odtctl[freq_e], dc_base + UMC_ODTCTL_D0);
598 writel(umc_odtctl[freq_e], dc_base + UMC_ODTCTL_D1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900599 writel(umc_dataset[freq_e], dc_base + UMC_DATASET);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900600
601 writel(0x00400020, dc_base + UMC_DCCGCTL);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900602 writel(0x00000003, dc_base + UMC_ACSSETA);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900603 writel(0x00000103, dc_base + UMC_FLOWCTLG);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900604 writel(0x00010200, dc_base + UMC_ACSSETB);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900605
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900606 writel(umc_flowctla[freq_e], dc_base + UMC_FLOWCTLA);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900607 writel(0x00004444, dc_base + UMC_FLOWCTLC);
608 writel(0x00000000, dc_base + UMC_DFICUPDCTLA);
609
610 writel(0x00202000, dc_base + UMC_FLOWCTLB);
611 writel(0x00000000, dc_base + UMC_BSICMAPSET);
612 writel(0x00000000, dc_base + UMC_ERRMASKA);
613 writel(0x00000000, dc_base + UMC_ERRMASKB);
614
615 writel(umc_directbusctrla[ch], dc_base + UMC_DIRECTBUSCTRLA);
616
617 writel(0x00000001, dc_base + UMC_INITSET);
618 /* Wait for PHY Init Complete */
619 while (readl(dc_base + UMC_INITSTAT) & BIT(0))
620 cpu_relax();
621
622 writel(0x2A0A0A00, dc_base + UMC_SPCSETB);
623 writel(0x00000000, dc_base + UMC_DFICSOVRRD);
624
625 return 0;
626}
627
628static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base,
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900629 enum dram_board board, unsigned int freq,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900630 unsigned long size, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900631{
632 void __iomem *dc_base = umc_ch_base + 0x00011000;
633 void __iomem *phy_base = phy_ch_base;
634 int ret;
635
636 /* PHY Update Mode (ON) */
637 writel(0x8000003f, dc_base + UMC_DFIPUPDCTLA);
638
639 /* deassert PHY reset signals */
640 writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST,
641 dc_base + UMC_DIOCTLA);
642
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900643 ddrphy_init(phy_base, board, ch);
644
645 umc_poll_phy_init_complete(dc_base);
646
647 ddrphy_init_tail(phy_base, board, freq, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900648
649 ret = umc_dc_init(dc_base, freq, size, ch);
650 if (ret)
651 return ret;
652
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900653 ret = ddrphy_training(phy_base, board, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900654 if (ret)
655 return ret;
656
657 return 0;
658}
659
660static void um_init(void __iomem *um_base)
661{
662 writel(0x000000ff, um_base + UMC_MBUS0);
663 writel(0x000000ff, um_base + UMC_MBUS1);
664 writel(0x000000ff, um_base + UMC_MBUS2);
665 writel(0x00000001, um_base + UMC_MBUS3);
666 writel(0x00000001, um_base + UMC_MBUS4);
667 writel(0x00000001, um_base + UMC_MBUS5);
668 writel(0x00000001, um_base + UMC_MBUS6);
669 writel(0x00000001, um_base + UMC_MBUS7);
670 writel(0x00000001, um_base + UMC_MBUS8);
671 writel(0x00000001, um_base + UMC_MBUS9);
672 writel(0x00000001, um_base + UMC_MBUS10);
673}
674
675int uniphier_ld20_umc_init(const struct uniphier_board_data *bd)
676{
677 void __iomem *um_base = (void __iomem *)0x5b600000;
678 void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
679 void __iomem *phy_ch_base = (void __iomem *)0x6e200000;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900680 enum dram_board board;
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900681 int ch, ret;
682
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900683 switch (UNIPHIER_BD_BOARD_GET_TYPE(bd->flags)) {
684 case UNIPHIER_BD_BOARD_LD20_REF:
685 board = DRAM_BOARD_LD20_REF;
686 break;
687 case UNIPHIER_BD_BOARD_LD20_GLOBAL:
688 board = DRAM_BOARD_LD20_GLOBAL;
689 break;
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900690 case UNIPHIER_BD_BOARD_LD20_C1:
691 board = DRAM_BOARD_LD20_C1;
692 break;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900693 case UNIPHIER_BD_BOARD_LD21_REF:
694 board = DRAM_BOARD_LD21_REF;
695 break;
696 case UNIPHIER_BD_BOARD_LD21_GLOBAL:
697 board = DRAM_BOARD_LD21_GLOBAL;
698 break;
699 default:
700 pr_err("unsupported board type %d\n",
701 UNIPHIER_BD_BOARD_GET_TYPE(bd->flags));
702 return -EINVAL;
703 }
704
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900705 for (ch = 0; ch < bd->dram_nr_ch; ch++) {
706 unsigned long size = bd->dram_ch[ch].size;
707 unsigned int width = bd->dram_ch[ch].width;
708
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900709 ret = umc_ch_init(umc_ch_base, phy_ch_base, board,
710 bd->dram_freq, size / (width / 16), ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900711 if (ret) {
712 pr_err("failed to initialize UMC ch%d\n", ch);
713 return ret;
714 }
715
716 umc_ch_base += 0x00200000;
717 phy_ch_base += 0x00004000;
718 }
719
720 um_init(um_base);
721
722 return 0;
723}