blob: 4e1fbde7a67d256698724f0581136383d08178fa [file] [log] [blame]
Masahiro Yamada063eb1e2016-04-21 14:43:18 +09001/*
2 * Copyright (C) 2016 Socionext Inc.
3 *
Masahiro Yamadab1224f32016-10-08 13:25:24 +09004 * based on commit 9073035a9860f892f8d1345dfb0ea862b5021145 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
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 */
36 DRAM_BOARD_LD21_REF, /* LD21 reference */
37 DRAM_BOARD_LD21_GLOBAL, /* LD21 TV */
38 DRAM_BOARD_NR,
39};
40
Masahiro Yamadab1224f32016-10-08 13:25:24 +090041/* PHY */
42static const int ddrphy_adrctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
43 {268 - 262, 268 - 263, 268 - 378}, /* LD20 reference */
44 {268 - 262, 268 - 263, 268 - 378}, /* LD20 TV */
45 {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 reference */
46 {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090047};
Masahiro Yamadab1224f32016-10-08 13:25:24 +090048
49static const int ddrphy_dlltrimclk[DRAM_BOARD_NR][DRAM_CH_NR] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090050 {268, 268, 268}, /* LD20 reference */
51 {268, 268, 268}, /* LD20 TV */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090052 {268, 268 + 252, /* No CH2 */}, /* LD21 reference */
53 {268, 268 + 202, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090054};
Masahiro Yamadab1224f32016-10-08 13:25:24 +090055
56static const int ddrphy_dllrecalib[DRAM_BOARD_NR][DRAM_CH_NR] = {
57 {268 - 378, 268 - 263, 268 - 378}, /* LD20 reference */
58 {268 - 378, 268 - 263, 268 - 378}, /* LD20 TV */
59 {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 reference */
60 {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090061};
62
Masahiro Yamadab1224f32016-10-08 13:25:24 +090063static const u32 ddrphy_phy_pad_ctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090064 {0x50B840B1, 0x50B840B1, 0x50B840B1}, /* LD20 reference */
65 {0x50BB40B1, 0x50BB40B1, 0x50BB40B1}, /* LD20 TV */
Masahiro Yamadab1224f32016-10-08 13:25:24 +090066 {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 reference */
67 {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090068};
69
Masahiro Yamadab1224f32016-10-08 13:25:24 +090070static const u32 ddrphy_scl_gate_timing[DRAM_CH_NR] = {
71 0x00000140, 0x00000180, 0x00000140
72};
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090073
Masahiro Yamadab1224f32016-10-08 13:25:24 +090074static const int ddrphy_op_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090075 { /* LD20 reference */
76 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090077 2, 1, 0, 1, 2, 1, 1, 1,
78 2, 1, 1, 2, 1, 1, 1, 1,
79 1, 2, 1, 1, 1, 2, 1, 1,
80 2, 2, 0, 1, 1, 2, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090081 },
82 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090083 1, 1, 0, 1, 2, 2, 1, 1,
84 1, 1, 1, 1, 1, 1, 1, 1,
85 1, 1, 0, 0, 1, 1, 0, 0,
86 0, 1, 1, 1, 2, 1, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090087 },
88 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090089 2, 2, 0, 2, 1, 1, 2, 1,
90 1, 1, 0, 1, 1, -1, 1, 1,
91 2, 2, 2, 2, 1, 1, 1, 1,
92 1, 1, 1, 0, 2, 2, 1, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090093 },
94 },
95 { /* LD20 TV */
96 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +090097 2, 1, 0, 1, 2, 1, 1, 1,
98 2, 1, 1, 2, 1, 1, 1, 1,
99 1, 2, 1, 1, 1, 2, 1, 1,
100 2, 2, 0, 1, 1, 2, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900101 },
102 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900103 1, 1, 0, 1, 2, 2, 1, 1,
104 1, 1, 1, 1, 1, 1, 1, 1,
105 1, 1, 0, 0, 1, 1, 0, 0,
106 0, 1, 1, 1, 2, 1, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900107 },
108 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900109 2, 2, 0, 2, 1, 1, 2, 1,
110 1, 1, 0, 1, 1, -1, 1, 1,
111 2, 2, 2, 2, 1, 1, 1, 1,
112 1, 1, 1, 0, 2, 2, 1, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900113 },
114 },
115 { /* LD21 reference */
116 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900117 1, 1, 0, 1, 1, 1, 1, 1,
118 1, 0, 0, 0, 1, 1, 0, 2,
119 1, 1, 0, 0, 1, 1, 1, 1,
120 1, 0, 0, 0, 1, 0, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900121 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900122 { 1, 0, 2, 1, 1, 1, 1, 0,
123 1, 0, 0, 1, 0, 1, 0, 0,
124 1, 0, 1, 0, 1, 1, 1, 0,
125 1, 1, 1, 1, 0, 1, 0, 0,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900126 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900127 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900128 },
129 { /* LD21 TV */
130 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900131 1, 1, 0, 1, 1, 1, 1, 1,
132 1, 0, 0, 0, 1, 1, 0, 2,
133 1, 1, 0, 0, 1, 1, 1, 1,
134 1, 0, 0, 0, 1, 0, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900135 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900136 { 1, 0, 2, 1, 1, 1, 1, 0,
137 1, 0, 0, 1, 0, 1, 0, 0,
138 1, 0, 1, 0, 1, 1, 1, 0,
139 1, 1, 1, 1, 0, 1, 0, 0,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900140 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900141 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900142 },
143};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900144
145static int ddrphy_ip_dq_shift_val[DRAM_BOARD_NR][DRAM_CH_NR][32] = {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900146 { /* LD20 reference */
147 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900148 3, 3, 3, 2, 3, 2, 0, 2,
149 2, 3, 3, 1, 2, 2, 2, 2,
150 2, 2, 2, 2, 0, 1, 1, 1,
151 2, 2, 2, 2, 3, 0, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900152 },
153 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900154 2, 2, 1, 1, -1, 1, 1, 1,
155 2, 0, 2, 2, 2, 1, 0, 2,
156 2, 1, 2, 1, 0, 1, 1, 1,
157 2, 2, 2, 2, 2, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900158 },
159 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900160 2, 2, 3, 2, 1, 2, 2, 2,
161 2, 3, 4, 2, 3, 4, 3, 3,
162 2, 2, 1, 2, 1, 1, 1, 1,
163 2, 2, 2, 2, 1, 2, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900164 },
165 },
166 { /* LD20 TV */
167 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900168 3, 3, 3, 2, 3, 2, 0, 2,
169 2, 3, 3, 1, 2, 2, 2, 2,
170 2, 2, 2, 2, 0, 1, 1, 1,
171 2, 2, 2, 2, 3, 0, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900172 },
173 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900174 2, 2, 1, 1, -1, 1, 1, 1,
175 2, 0, 2, 2, 2, 1, 0, 2,
176 2, 1, 2, 1, 0, 1, 1, 1,
177 2, 2, 2, 2, 2, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900178 },
179 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900180 2, 2, 3, 2, 1, 2, 2, 2,
181 2, 3, 4, 2, 3, 4, 3, 3,
182 2, 2, 1, 2, 1, 1, 1, 1,
183 2, 2, 2, 2, 1, 2, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900184 },
185 },
186 { /* LD21 reference */
187 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900188 2, 2, 2, 2, 1, 2, 2, 2,
189 2, 3, 3, 2, 2, 2, 2, 2,
190 2, 1, 2, 2, 1, 1, 1, 1,
191 2, 2, 2, 3, 1, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900192 },
193 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900194 3, 4, 4, 1, 0, 1, 1, 1,
195 1, 2, 1, 2, 2, 3, 3, 2,
196 1, 0, 2, 1, 1, 0, 1, 0,
197 0, 1, 0, 0, 1, 1, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900198 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900199 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900200 },
201 { /* LD21 TV */
202 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900203 2, 2, 2, 2, 1, 2, 2, 2,
204 2, 3, 3, 2, 2, 2, 2, 2,
205 2, 1, 2, 2, 1, 1, 1, 1,
206 2, 2, 2, 3, 1, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900207 },
208 {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900209 3, 4, 4, 1, 0, 1, 1, 1,
210 1, 2, 1, 2, 2, 3, 3, 2,
211 1, 0, 2, 1, 1, 0, 1, 0,
212 0, 1, 0, 0, 1, 1, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900213 },
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900214 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900215 },
216};
217
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900218/* DDR PHY */
219static void ddrphy_select_lane(void __iomem *phy_base, unsigned int lane,
220 unsigned int bit)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900221{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900222 WARN_ON(lane >= (1 << PHY_LANE_SEL_LANE_WIDTH));
223 WARN_ON(bit >= (1 << PHY_LANE_SEL_BIT_WIDTH));
224
225 writel((bit << PHY_LANE_SEL_BIT_SHIFT) |
226 (lane << PHY_LANE_SEL_LANE_SHIFT),
227 phy_base + PHY_LANE_SEL);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900228}
229
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900230static void ddrphy_init(void __iomem *phy_base, enum dram_board board, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900231{
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900232 writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
233 while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1)))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900234 cpu_relax();
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900235 writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900236
237 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3);
238 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900239 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900240 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
241 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900242 ddrphy_select_lane(phy_base, 6, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900243 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
244 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900245 ddrphy_select_lane(phy_base, 12, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900246 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
247 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900248 ddrphy_select_lane(phy_base, 18, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900249 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
250 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
251 writel(0x00000001, phy_base + PHY_SCL_WINDOW_TRIM);
252 writel(0x00000000, phy_base + PHY_UNQ_ANALOG_DLL_1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900253 writel(ddrphy_phy_pad_ctrl[board][ch], phy_base + PHY_PAD_CTRL);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900254 writel(0x00000070, phy_base + PHY_VREF_TRAINING);
255 writel(0x01000075, phy_base + PHY_SCL_CONFIG_1);
256 writel(0x00000501, phy_base + PHY_SCL_CONFIG_2);
257 writel(0x00000000, phy_base + PHY_SCL_CONFIG_3);
258 writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
259 writel(0x00000000, phy_base + PHY_SCL_CONFIG_4);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900260 writel(ddrphy_scl_gate_timing[ch], phy_base + PHY_SCL_GATE_TIMING);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900261 writel(0x02a000a0, phy_base + PHY_WRLVL_DYN_ODT);
262 writel(0x00840004, phy_base + PHY_WRLVL_ON_OFF);
263 writel(0x0000020d, phy_base + PHY_DLL_ADRCTRL);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900264 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900265 writel(0x0000008d, phy_base + PHY_DLL_TRIM_CLK);
266 writel(0xa800100d, phy_base + PHY_DLL_RECALIB);
267 writel(0x00005076, phy_base + PHY_SCL_LATENCY);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900268}
269
270static int ddrphy_to_dly_step(void __iomem *phy_base, unsigned int freq,
271 int delay)
272{
273 int mdl;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900274
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900275 mdl = (readl(phy_base + PHY_DLL_ADRCTRL) & PHY_DLL_ADRCTRL_MDL_MASK) >>
276 PHY_DLL_ADRCTRL_MDL_SHIFT;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900277
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900278 return DIV_ROUND_CLOSEST((long)freq * delay * mdl, 2 * 1000000L);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900279}
280
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900281static void ddrphy_set_delay(void __iomem *phy_base, unsigned int reg,
282 u32 mask, u32 incr, int dly_step)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900283{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900284 u32 tmp;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900285
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900286 tmp = readl(phy_base + reg);
287 tmp &= ~mask;
288 tmp |= min_t(u32, abs(dly_step), mask);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900289
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900290 if (dly_step >= 0)
291 tmp |= incr;
292 else
293 tmp &= ~incr;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900294
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900295 writel(tmp, phy_base + reg);
296}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900297
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900298static void ddrphy_set_dll_recalib(void __iomem *phy_base, int dly_step)
299{
300 ddrphy_set_delay(phy_base, PHY_DLL_RECALIB,
301 PHY_DLL_RECALIB_TRIM_MASK, PHY_DLL_RECALIB_INCR,
302 dly_step);
303}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900304
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900305static void ddrphy_set_dll_adrctrl(void __iomem *phy_base, int dly_step)
306{
307 ddrphy_set_delay(phy_base, PHY_DLL_ADRCTRL,
308 PHY_DLL_ADRCTRL_TRIM_MASK, PHY_DLL_ADRCTRL_INCR,
309 dly_step);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900310}
311
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900312static void ddrphy_set_dll_trim_clk(void __iomem *phy_base, int dly_step)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900313{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900314 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900315
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900316 ddrphy_set_delay(phy_base, PHY_DLL_TRIM_CLK,
317 PHY_DLL_TRIM_CLK_MASK, PHY_DLL_TRIM_CLK_INCR,
318 dly_step);
319}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900320
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900321static void ddrphy_init_tail(void __iomem *phy_base, enum dram_board board,
322 unsigned int freq, int ch)
323{
324 int step;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900325
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900326 step = ddrphy_to_dly_step(phy_base, freq, ddrphy_adrctrl[board][ch]);
327 ddrphy_set_dll_adrctrl(phy_base, step);
328
329 step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dlltrimclk[board][ch]);
330 ddrphy_set_dll_trim_clk(phy_base, step);
331
332 step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dllrecalib[board][ch]);
333 ddrphy_set_dll_recalib(phy_base, step);
334}
335
336static void ddrphy_shift_one_dq(void __iomem *phy_base, unsigned int reg,
337 u32 mask, u32 incr, int shift_val)
338{
339 u32 tmp;
340 int val;
341
342 tmp = readl(phy_base + reg);
343
344 val = tmp & mask;
345 if (!(tmp & incr))
346 val = -val;
347
348 val += shift_val;
349
350 tmp &= ~(incr | mask);
351 tmp |= min_t(u32, abs(val), mask);
352 if (val >= 0)
353 tmp |= incr;
354
355 writel(tmp, phy_base + reg);
356}
357
358static void ddrphy_shift_dq(void __iomem *phy_base, unsigned int reg,
359 u32 mask, u32 incr, u32 override,
360 const int *shift_val_array)
361{
362 u32 tmp;
363 int dx, bit;
364
365 tmp = readl(phy_base + reg);
366 tmp |= override;
367 writel(tmp, phy_base + reg);
368
369 for (dx = 0; dx < 4; dx++) {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900370 for (bit = 0; bit < 8; bit++) {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900371 ddrphy_select_lane(phy_base,
372 (PHY_BITLVL_DLY_WIDTH + 1) * dx,
373 bit);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900374
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900375 ddrphy_shift_one_dq(phy_base, reg, mask, incr,
376 shift_val_array[dx * 8 + bit]);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900377 }
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900378 }
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900379
380 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900381}
382
383static int ddrphy_training(void __iomem *phy_base, enum dram_board board,
384 int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900385{
386 writel(0x0000000f, phy_base + PHY_WRLVL_AUTOINC_TRIM);
387 writel(0x00010000, phy_base + PHY_DLL_TRIM_2);
388 writel(0x50000000, phy_base + PHY_SCL_START);
389
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900390 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900391 cpu_relax();
392
393 writel(0x00000000, phy_base + PHY_DISABLE_GATING_FOR_SCL);
394 writel(0xff00ff00, phy_base + PHY_SCL_DATA_0);
395 writel(0xff00ff00, phy_base + PHY_SCL_DATA_1);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900396 writel(0xFBF8FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900397 writel(0x11000000, phy_base + PHY_SCL_START);
398
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900399 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900400 cpu_relax();
401
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900402 writel(0xFBF0FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900403 writel(0x30500000, phy_base + PHY_SCL_START);
404
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900405 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900406 cpu_relax();
407
408 writel(0x00000001, phy_base + PHY_DISABLE_GATING_FOR_SCL);
409 writel(0x00000010, phy_base + PHY_SCL_MAIN_CLK_DELTA);
410 writel(0x789b3de0, phy_base + PHY_SCL_DATA_0);
411 writel(0xf10e4a56, phy_base + PHY_SCL_DATA_1);
412 writel(0x11000000, phy_base + PHY_SCL_START);
413
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900414 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900415 cpu_relax();
416
417 writel(0x34000000, phy_base + PHY_SCL_START);
418
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900419 while (readl(phy_base + PHY_SCL_START) & BIT(28))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900420 cpu_relax();
421
422 writel(0x00000003, phy_base + PHY_DISABLE_GATING_FOR_SCL);
423
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900424 writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
425 writel(0x00003270, phy_base + PHY_DYNAMIC_BIT_LVL);
426 writel(0x011BD0C4, phy_base + PHY_DSCL_CNT);
427
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900428 /* shift ip_dq trim */
429 ddrphy_shift_dq(phy_base,
430 PHY_IP_DQ_DQS_BITWISE_TRIM,
431 PHY_IP_DQ_DQS_BITWISE_TRIM_MASK,
432 PHY_IP_DQ_DQS_BITWISE_TRIM_INC,
433 PHY_IP_DQ_DQS_BITWISE_TRIM_OVERRIDE,
434 ddrphy_ip_dq_shift_val[board][ch]);
435
436 /* shift op_dq trim */
437 ddrphy_shift_dq(phy_base,
438 PHY_OP_DQ_DM_DQS_BITWISE_TRIM,
439 PHY_OP_DQ_DM_DQS_BITWISE_TRIM_MASK,
440 PHY_OP_DQ_DM_DQS_BITWISE_TRIM_INC,
441 PHY_OP_DQ_DM_DQS_BITWISE_TRIM_OVERRIDE,
442 ddrphy_op_dq_shift_val[board][ch]);
443
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900444 return 0;
445}
446
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900447/* UMC */
448static u32 umc_initctla[DRAM_FREQ_NR] = {0x71016D11};
449static u32 umc_initctlb[DRAM_FREQ_NR] = {0x07E390AC};
450static u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF};
451static u32 umc_drmmr0[DRAM_FREQ_NR] = {0x00000114};
452static u32 umc_drmmr2[DRAM_FREQ_NR] = {0x000002a0};
453
454static u32 umc_memconf0a[DRAM_FREQ_NR][DRAM_SZ_NR] = {
455 /* 256MB 512MB */
456 {0x00000601, 0x00000801}, /* 1866 MHz */
457};
458
459static u32 umc_memconf0b[DRAM_FREQ_NR][DRAM_SZ_NR] = {
460 /* 256MB 512MB */
461 {0x00000120, 0x00000130}, /* 1866 MHz */
462};
463
464static u32 umc_memconfch[DRAM_FREQ_NR][DRAM_SZ_NR] = {
465 /* 256MB 512MB */
466 {0x00033603, 0x00033803}, /* 1866 MHz */
467};
468
469static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x060D0D20};
470static u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x2D211C08};
471static u32 umc_cmdctlc[DRAM_FREQ_NR] = {0x00150C04};
472static u32 umc_cmdctle[DRAM_FREQ_NR][DRAM_SZ_NR] = {
473 /* 256MB 512MB */
474 {0x0049071D, 0x0078071D}, /* 1866 MHz */
475};
476
477static u32 umc_rdatactl_d0[DRAM_FREQ_NR] = {0x00000610};
478static u32 umc_rdatactl_d1[DRAM_FREQ_NR] = {0x00000610};
479static u32 umc_wdatactl_d0[DRAM_FREQ_NR] = {0x00000204};
480static u32 umc_wdatactl_d1[DRAM_FREQ_NR] = {0x00000204};
481static u32 umc_odtctl_d0[DRAM_FREQ_NR] = {0x02000002};
482static u32 umc_odtctl_d1[DRAM_FREQ_NR] = {0x02000002};
483static u32 umc_dataset[DRAM_FREQ_NR] = {0x04000000};
484
485static u32 umc_flowctla[DRAM_FREQ_NR] = {0x0081E01E};
486static u32 umc_directbusctrla[DRAM_CH_NR] = {
487 0x00000000, 0x00000001, 0x00000001
488};
489
490static void umc_poll_phy_init_complete(void __iomem *dc_base)
491{
492 /* Wait for PHY Init Complete */
493 while (!(readl(dc_base + UMC_DFISTCTLC) & BIT(0)))
494 cpu_relax();
495}
496
497static int umc_dc_init(void __iomem *dc_base, unsigned int freq,
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900498 unsigned long size, int ch)
499{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900500 enum dram_freq freq_e;
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900501 enum dram_size size_e;
502
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900503 switch (freq) {
504 case 1866:
505 freq_e = DRAM_FREQ_1866M;
506 break;
507 default:
508 pr_err("unsupported DRAM frequency %ud MHz\n", freq);
509 return -EINVAL;
510 }
511
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900512 switch (size) {
513 case 0:
514 return 0;
515 case SZ_256M:
516 size_e = DRAM_SZ_256M;
517 break;
518 case SZ_512M:
519 size_e = DRAM_SZ_512M;
520 break;
521 default:
522 pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
523 size, ch);
524 return -EINVAL;
525 }
526
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900527 writel(0x00000001, dc_base + UMC_DFICSOVRRD);
528 writel(0x00000000, dc_base + UMC_DFITURNOFF);
529
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900530 writel(umc_initctla[freq_e], dc_base + UMC_INITCTLA);
531 writel(umc_initctlb[freq_e], dc_base + UMC_INITCTLB);
532 writel(umc_initctlc[freq_e], dc_base + UMC_INITCTLC);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900533
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900534 writel(umc_drmmr0[freq_e], dc_base + UMC_DRMMR0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900535 writel(0x00000004, dc_base + UMC_DRMMR1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900536 writel(umc_drmmr2[freq_e], dc_base + UMC_DRMMR2);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900537 writel(0x00000000, dc_base + UMC_DRMMR3);
538
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900539 writel(umc_memconf0a[freq_e][size_e], dc_base + UMC_MEMCONF0A);
540 writel(umc_memconf0b[freq_e][size_e], dc_base + UMC_MEMCONF0B);
541 writel(umc_memconfch[freq_e][size_e], dc_base + UMC_MEMCONFCH);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900542 writel(0x00000008, dc_base + UMC_MEMMAPSET);
543
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900544 writel(umc_cmdctla[freq_e], dc_base + UMC_CMDCTLA);
545 writel(umc_cmdctlb[freq_e], dc_base + UMC_CMDCTLB);
546 writel(umc_cmdctlc[freq_e], dc_base + UMC_CMDCTLC);
547 writel(umc_cmdctle[freq_e][size_e], dc_base + UMC_CMDCTLE);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900548
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900549 writel(umc_rdatactl_d0[freq_e], dc_base + UMC_RDATACTL_D0);
550 writel(umc_rdatactl_d1[freq_e], dc_base + UMC_RDATACTL_D1);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900551
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900552 writel(umc_wdatactl_d0[freq_e], dc_base + UMC_WDATACTL_D0);
553 writel(umc_wdatactl_d1[freq_e], dc_base + UMC_WDATACTL_D1);
554 writel(umc_odtctl_d0[freq_e], dc_base + UMC_ODTCTL_D0);
555 writel(umc_odtctl_d1[freq_e], dc_base + UMC_ODTCTL_D1);
556 writel(umc_dataset[freq_e], dc_base + UMC_DATASET);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900557
558 writel(0x00400020, dc_base + UMC_DCCGCTL);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900559 writel(0x00000003, dc_base + UMC_ACSSETA);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900560 writel(0x00000103, dc_base + UMC_FLOWCTLG);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900561 writel(0x00010200, dc_base + UMC_ACSSETB);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900562
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900563 writel(umc_flowctla[freq_e], dc_base + UMC_FLOWCTLA);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900564 writel(0x00004444, dc_base + UMC_FLOWCTLC);
565 writel(0x00000000, dc_base + UMC_DFICUPDCTLA);
566
567 writel(0x00202000, dc_base + UMC_FLOWCTLB);
568 writel(0x00000000, dc_base + UMC_BSICMAPSET);
569 writel(0x00000000, dc_base + UMC_ERRMASKA);
570 writel(0x00000000, dc_base + UMC_ERRMASKB);
571
572 writel(umc_directbusctrla[ch], dc_base + UMC_DIRECTBUSCTRLA);
573
574 writel(0x00000001, dc_base + UMC_INITSET);
575 /* Wait for PHY Init Complete */
576 while (readl(dc_base + UMC_INITSTAT) & BIT(0))
577 cpu_relax();
578
579 writel(0x2A0A0A00, dc_base + UMC_SPCSETB);
580 writel(0x00000000, dc_base + UMC_DFICSOVRRD);
581
582 return 0;
583}
584
585static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base,
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900586 enum dram_board board, unsigned int freq,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900587 unsigned long size, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900588{
589 void __iomem *dc_base = umc_ch_base + 0x00011000;
590 void __iomem *phy_base = phy_ch_base;
591 int ret;
592
593 /* PHY Update Mode (ON) */
594 writel(0x8000003f, dc_base + UMC_DFIPUPDCTLA);
595
596 /* deassert PHY reset signals */
597 writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST,
598 dc_base + UMC_DIOCTLA);
599
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900600 ddrphy_init(phy_base, board, ch);
601
602 umc_poll_phy_init_complete(dc_base);
603
604 ddrphy_init_tail(phy_base, board, freq, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900605
606 ret = umc_dc_init(dc_base, freq, size, ch);
607 if (ret)
608 return ret;
609
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900610 ret = ddrphy_training(phy_base, board, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900611 if (ret)
612 return ret;
613
614 return 0;
615}
616
617static void um_init(void __iomem *um_base)
618{
619 writel(0x000000ff, um_base + UMC_MBUS0);
620 writel(0x000000ff, um_base + UMC_MBUS1);
621 writel(0x000000ff, um_base + UMC_MBUS2);
622 writel(0x00000001, um_base + UMC_MBUS3);
623 writel(0x00000001, um_base + UMC_MBUS4);
624 writel(0x00000001, um_base + UMC_MBUS5);
625 writel(0x00000001, um_base + UMC_MBUS6);
626 writel(0x00000001, um_base + UMC_MBUS7);
627 writel(0x00000001, um_base + UMC_MBUS8);
628 writel(0x00000001, um_base + UMC_MBUS9);
629 writel(0x00000001, um_base + UMC_MBUS10);
630}
631
632int uniphier_ld20_umc_init(const struct uniphier_board_data *bd)
633{
634 void __iomem *um_base = (void __iomem *)0x5b600000;
635 void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
636 void __iomem *phy_ch_base = (void __iomem *)0x6e200000;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900637 enum dram_board board;
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900638 int ch, ret;
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 Yamadab1224f32016-10-08 13:25:24 +0900663 ret = umc_ch_init(umc_ch_base, phy_ch_base, board,
664 bd->dram_freq, size / (width / 16), ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900665 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}