blob: 500c1c11ba4204b7ffa3689f06d8e7b6216370b9 [file] [log] [blame]
Masahiro Yamada063eb1e2016-04-21 14:43:18 +09001/*
Masahiro Yamada5f02e282017-01-28 06:53:42 +09002 * Copyright (C) 2016-2017 Socionext Inc.
Masahiro Yamada063eb1e2016-04-21 14:43:18 +09003 *
Kotaro Hayashi4e86e352017-02-14 11:39:14 +09004 * based on commit 5ffd75ecd4929f22361ef65a35f0331d2fbc0f35 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 Yamada5f02e282017-01-28 06:53:42 +090080static const short ddrphy_op_dq_shift_val_ld20[DRAM_CH_NR][32] = {
81 {
82 2, 1, 0, 1, 2, 1, 1, 1,
83 2, 1, 1, 2, 1, 1, 1, 1,
84 1, 2, 1, 1, 1, 2, 1, 1,
85 2, 2, 0, 1, 1, 2, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090086 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +090087 {
88 1, 1, 0, 1, 2, 2, 1, 1,
89 1, 1, 1, 1, 1, 1, 1, 1,
90 1, 1, 0, 0, 1, 1, 0, 0,
91 0, 1, 1, 1, 2, 1, 2, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +090092 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +090093 {
94 2, 2, 0, 2, 1, 1, 2, 1,
95 1, 1, 0, 1, 1, -1, 1, 1,
96 2, 2, 2, 2, 1, 1, 1, 1,
97 1, 1, 1, 0, 2, 2, 1, 2,
Masahiro Yamadabf4266e2016-10-27 23:47:02 +090098 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +090099};
100
101static const short ddrphy_op_dq_shift_val_ld21[DRAM_CH_NR][32] = {
102 {
103 1, 1, 0, 1, 1, 1, 1, 1,
104 1, 0, 0, 0, 1, 1, 0, 2,
105 1, 1, 0, 0, 1, 1, 1, 1,
106 1, 0, 0, 0, 1, 0, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900107 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900108 { 1, 0, 2, 1, 1, 1, 1, 0,
109 1, 0, 0, 1, 0, 1, 0, 0,
110 1, 0, 1, 0, 1, 1, 1, 0,
111 1, 1, 1, 1, 0, 1, 0, 0,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900112 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900113 /* No CH2 */
114};
115
116static const short (* const ddrphy_op_dq_shift_val[DRAM_BOARD_NR])[32] = {
117 ddrphy_op_dq_shift_val_ld20, /* LD20 reference */
118 ddrphy_op_dq_shift_val_ld20, /* LD20 TV */
119 ddrphy_op_dq_shift_val_ld20, /* LD20 TV C */
120 ddrphy_op_dq_shift_val_ld21, /* LD21 reference */
121 ddrphy_op_dq_shift_val_ld21, /* LD21 TV */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900122};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900123
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900124static const short ddrphy_ip_dq_shift_val_ld20[DRAM_CH_NR][32] = {
125 {
126 3, 3, 3, 2, 3, 2, 0, 2,
127 2, 3, 3, 1, 2, 2, 2, 2,
128 2, 2, 2, 2, 0, 1, 1, 1,
129 2, 2, 2, 2, 3, 0, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900130 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900131 {
132 2, 2, 1, 1, -1, 1, 1, 1,
133 2, 0, 2, 2, 2, 1, 0, 2,
134 2, 1, 2, 1, 0, 1, 1, 1,
135 2, 2, 2, 2, 2, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900136 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900137 {
138 2, 2, 3, 2, 1, 2, 2, 2,
139 2, 3, 4, 2, 3, 4, 3, 3,
140 2, 2, 1, 2, 1, 1, 1, 1,
141 2, 2, 2, 2, 1, 2, 2, 1,
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900142 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900143};
144
145static const short ddrphy_ip_dq_shift_val_ld21[DRAM_CH_NR][32] = {
146 {
147 2, 2, 2, 2, 1, 2, 2, 2,
148 2, 3, 3, 2, 2, 2, 2, 2,
149 2, 1, 2, 2, 1, 1, 1, 1,
150 2, 2, 2, 3, 1, 2, 2, 2,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900151 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900152 {
153 3, 4, 4, 1, 0, 1, 1, 1,
154 1, 2, 1, 2, 2, 3, 3, 2,
155 1, 0, 2, 1, 1, 0, 1, 0,
156 0, 1, 0, 0, 1, 1, 0, 1,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900157 },
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900158 /* No CH2 */
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900159};
160
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900161static const short (* const ddrphy_ip_dq_shift_val[DRAM_BOARD_NR])[32] = {
162 ddrphy_ip_dq_shift_val_ld20, /* LD20 reference */
163 ddrphy_ip_dq_shift_val_ld20, /* LD20 TV */
164 ddrphy_ip_dq_shift_val_ld20, /* LD20 TV C */
165 ddrphy_ip_dq_shift_val_ld21, /* LD21 reference */
166 ddrphy_ip_dq_shift_val_ld21, /* LD21 TV */
167};
168
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900169static void ddrphy_select_lane(void __iomem *phy_base, unsigned int lane,
170 unsigned int bit)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900171{
Masahiro Yamada5864e162016-12-05 18:31:37 +0900172 WARN_ON(lane >= 1 << PHY_LANE_SEL_LANE_WIDTH);
173 WARN_ON(bit >= 1 << PHY_LANE_SEL_BIT_WIDTH);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900174
175 writel((bit << PHY_LANE_SEL_BIT_SHIFT) |
176 (lane << PHY_LANE_SEL_LANE_SHIFT),
177 phy_base + PHY_LANE_SEL);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900178}
179
Kotaro Hayashi4e86e352017-02-14 11:39:14 +0900180#define DDRPHY_EFUSEMON (void *)0x5f900118
181
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900182static void ddrphy_init(void __iomem *phy_base, enum dram_board board, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900183{
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900184 writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
185 while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1)))
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900186 cpu_relax();
Kotaro Hayashi4e86e352017-02-14 11:39:14 +0900187
188 if (readl(DDRPHY_EFUSEMON) & BIT(ch))
189 writel(0x00000000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
190 else
191 writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900192
193 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3);
194 writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900195 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900196 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
197 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900198 ddrphy_select_lane(phy_base, 6, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900199 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
200 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900201 ddrphy_select_lane(phy_base, 12, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900202 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
203 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900204 ddrphy_select_lane(phy_base, 18, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900205 writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
206 writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
207 writel(0x00000001, phy_base + PHY_SCL_WINDOW_TRIM);
208 writel(0x00000000, phy_base + PHY_UNQ_ANALOG_DLL_1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900209 writel(ddrphy_phy_pad_ctrl[board][ch], phy_base + PHY_PAD_CTRL);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900210 writel(0x00000070, phy_base + PHY_VREF_TRAINING);
211 writel(0x01000075, phy_base + PHY_SCL_CONFIG_1);
212 writel(0x00000501, phy_base + PHY_SCL_CONFIG_2);
213 writel(0x00000000, phy_base + PHY_SCL_CONFIG_3);
214 writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
215 writel(0x00000000, phy_base + PHY_SCL_CONFIG_4);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900216 writel(ddrphy_scl_gate_timing[ch], phy_base + PHY_SCL_GATE_TIMING);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900217 writel(0x02a000a0, phy_base + PHY_WRLVL_DYN_ODT);
218 writel(0x00840004, phy_base + PHY_WRLVL_ON_OFF);
219 writel(0x0000020d, phy_base + PHY_DLL_ADRCTRL);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900220 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900221 writel(0x0000008d, phy_base + PHY_DLL_TRIM_CLK);
222 writel(0xa800100d, phy_base + PHY_DLL_RECALIB);
223 writel(0x00005076, phy_base + PHY_SCL_LATENCY);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900224}
225
226static int ddrphy_to_dly_step(void __iomem *phy_base, unsigned int freq,
227 int delay)
228{
229 int mdl;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900230
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900231 mdl = (readl(phy_base + PHY_DLL_ADRCTRL) & PHY_DLL_ADRCTRL_MDL_MASK) >>
232 PHY_DLL_ADRCTRL_MDL_SHIFT;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900233
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900234 return DIV_ROUND_CLOSEST((long)freq * delay * mdl, 2 * 1000000L);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900235}
236
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900237static void ddrphy_set_delay(void __iomem *phy_base, unsigned int reg,
238 u32 mask, u32 incr, int dly_step)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900239{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900240 u32 tmp;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900241
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900242 tmp = readl(phy_base + reg);
243 tmp &= ~mask;
244 tmp |= min_t(u32, abs(dly_step), mask);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900245
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900246 if (dly_step >= 0)
247 tmp |= incr;
248 else
249 tmp &= ~incr;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900250
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900251 writel(tmp, phy_base + reg);
252}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900253
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900254static void ddrphy_set_dll_recalib(void __iomem *phy_base, int dly_step)
255{
256 ddrphy_set_delay(phy_base, PHY_DLL_RECALIB,
257 PHY_DLL_RECALIB_TRIM_MASK, PHY_DLL_RECALIB_INCR,
258 dly_step);
259}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900260
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900261static void ddrphy_set_dll_adrctrl(void __iomem *phy_base, int dly_step)
262{
263 ddrphy_set_delay(phy_base, PHY_DLL_ADRCTRL,
264 PHY_DLL_ADRCTRL_TRIM_MASK, PHY_DLL_ADRCTRL_INCR,
265 dly_step);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900266}
267
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900268static void ddrphy_set_dll_trim_clk(void __iomem *phy_base, int dly_step)
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900269{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900270 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900271
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900272 ddrphy_set_delay(phy_base, PHY_DLL_TRIM_CLK,
273 PHY_DLL_TRIM_CLK_MASK, PHY_DLL_TRIM_CLK_INCR,
274 dly_step);
275}
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900276
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900277static void ddrphy_init_tail(void __iomem *phy_base, enum dram_board board,
278 unsigned int freq, int ch)
279{
280 int step;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900281
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900282 step = ddrphy_to_dly_step(phy_base, freq, ddrphy_adrctrl[board][ch]);
283 ddrphy_set_dll_adrctrl(phy_base, step);
284
285 step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dlltrimclk[board][ch]);
286 ddrphy_set_dll_trim_clk(phy_base, step);
287
288 step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dllrecalib[board][ch]);
289 ddrphy_set_dll_recalib(phy_base, step);
290}
291
292static void ddrphy_shift_one_dq(void __iomem *phy_base, unsigned int reg,
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900293 u32 mask, u32 incr, short shift_val)
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900294{
295 u32 tmp;
296 int val;
297
298 tmp = readl(phy_base + reg);
299
300 val = tmp & mask;
301 if (!(tmp & incr))
302 val = -val;
303
304 val += shift_val;
305
306 tmp &= ~(incr | mask);
307 tmp |= min_t(u32, abs(val), mask);
308 if (val >= 0)
309 tmp |= incr;
310
311 writel(tmp, phy_base + reg);
312}
313
314static void ddrphy_shift_dq(void __iomem *phy_base, unsigned int reg,
315 u32 mask, u32 incr, u32 override,
Masahiro Yamada5f02e282017-01-28 06:53:42 +0900316 const short *shift_val_array)
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900317{
318 u32 tmp;
319 int dx, bit;
320
321 tmp = readl(phy_base + reg);
322 tmp |= override;
323 writel(tmp, phy_base + reg);
324
325 for (dx = 0; dx < 4; dx++) {
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900326 for (bit = 0; bit < 8; bit++) {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900327 ddrphy_select_lane(phy_base,
328 (PHY_BITLVL_DLY_WIDTH + 1) * dx,
329 bit);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900330
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900331 ddrphy_shift_one_dq(phy_base, reg, mask, incr,
332 shift_val_array[dx * 8 + bit]);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900333 }
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900334 }
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900335
336 ddrphy_select_lane(phy_base, 0, 0);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900337}
338
339static int ddrphy_training(void __iomem *phy_base, enum dram_board board,
340 int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900341{
342 writel(0x0000000f, phy_base + PHY_WRLVL_AUTOINC_TRIM);
343 writel(0x00010000, phy_base + PHY_DLL_TRIM_2);
344 writel(0x50000000, phy_base + PHY_SCL_START);
345
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900346 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900347 cpu_relax();
348
349 writel(0x00000000, phy_base + PHY_DISABLE_GATING_FOR_SCL);
350 writel(0xff00ff00, phy_base + PHY_SCL_DATA_0);
351 writel(0xff00ff00, phy_base + PHY_SCL_DATA_1);
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900352 writel(0xFBF8FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900353 writel(0x11000000, phy_base + PHY_SCL_START);
354
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900355 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900356 cpu_relax();
357
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900358 writel(0xFBF0FFFF, phy_base + PHY_SCL_START_ADDR);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900359 writel(0x30500000, phy_base + PHY_SCL_START);
360
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900361 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900362 cpu_relax();
363
364 writel(0x00000001, phy_base + PHY_DISABLE_GATING_FOR_SCL);
365 writel(0x00000010, phy_base + PHY_SCL_MAIN_CLK_DELTA);
366 writel(0x789b3de0, phy_base + PHY_SCL_DATA_0);
367 writel(0xf10e4a56, phy_base + PHY_SCL_DATA_1);
368 writel(0x11000000, phy_base + PHY_SCL_START);
369
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900370 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900371 cpu_relax();
372
373 writel(0x34000000, phy_base + PHY_SCL_START);
374
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900375 while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900376 cpu_relax();
377
378 writel(0x00000003, phy_base + PHY_DISABLE_GATING_FOR_SCL);
379
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900380 writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
381 writel(0x00003270, phy_base + PHY_DYNAMIC_BIT_LVL);
382 writel(0x011BD0C4, phy_base + PHY_DSCL_CNT);
383
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900384 /* shift ip_dq trim */
385 ddrphy_shift_dq(phy_base,
386 PHY_IP_DQ_DQS_BITWISE_TRIM,
387 PHY_IP_DQ_DQS_BITWISE_TRIM_MASK,
388 PHY_IP_DQ_DQS_BITWISE_TRIM_INC,
389 PHY_IP_DQ_DQS_BITWISE_TRIM_OVERRIDE,
390 ddrphy_ip_dq_shift_val[board][ch]);
391
392 /* shift op_dq trim */
393 ddrphy_shift_dq(phy_base,
394 PHY_OP_DQ_DM_DQS_BITWISE_TRIM,
395 PHY_OP_DQ_DM_DQS_BITWISE_TRIM_MASK,
396 PHY_OP_DQ_DM_DQS_BITWISE_TRIM_INC,
397 PHY_OP_DQ_DM_DQS_BITWISE_TRIM_OVERRIDE,
398 ddrphy_op_dq_shift_val[board][ch]);
399
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900400 return 0;
401}
402
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900403/* UMC */
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900404static const u32 umc_initctla[DRAM_FREQ_NR] = {0x71016D11};
405static const u32 umc_initctlb[DRAM_FREQ_NR] = {0x07E390AC};
406static const u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF};
407static const u32 umc_drmmr0[DRAM_FREQ_NR] = {0x00000114};
408static const u32 umc_drmmr2[DRAM_FREQ_NR] = {0x000002a0};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900409
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900410static const u32 umc_memconf0a[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900411 /* 256MB 512MB */
412 {0x00000601, 0x00000801}, /* 1866 MHz */
413};
414
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900415static const u32 umc_memconf0b[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900416 /* 256MB 512MB */
417 {0x00000120, 0x00000130}, /* 1866 MHz */
418};
419
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900420static const u32 umc_memconfch[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900421 /* 256MB 512MB */
422 {0x00033603, 0x00033803}, /* 1866 MHz */
423};
424
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900425static const u32 umc_cmdctla[DRAM_FREQ_NR] = {0x060D0D20};
426static const u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x2D211C08};
427static const u32 umc_cmdctlc[DRAM_FREQ_NR] = {0x00150C04};
428static const u32 umc_cmdctle[DRAM_FREQ_NR][DRAM_SZ_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900429 /* 256MB 512MB */
430 {0x0049071D, 0x0078071D}, /* 1866 MHz */
431};
432
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900433static const u32 umc_rdatactl[DRAM_FREQ_NR] = {0x00000610};
434static const u32 umc_wdatactl[DRAM_FREQ_NR] = {0x00000204};
435static const u32 umc_odtctl[DRAM_FREQ_NR] = {0x02000002};
436static const u32 umc_dataset[DRAM_FREQ_NR] = {0x04000000};
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900437
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900438static const u32 umc_flowctla[DRAM_FREQ_NR] = {0x0081E01E};
439static const u32 umc_directbusctrla[DRAM_CH_NR] = {
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900440 0x00000000, 0x00000001, 0x00000001
441};
442
443static void umc_poll_phy_init_complete(void __iomem *dc_base)
444{
445 /* Wait for PHY Init Complete */
446 while (!(readl(dc_base + UMC_DFISTCTLC) & BIT(0)))
447 cpu_relax();
448}
449
450static int umc_dc_init(void __iomem *dc_base, unsigned int freq,
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900451 unsigned long size, int ch)
452{
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900453 enum dram_freq freq_e;
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900454 enum dram_size size_e;
455
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900456 switch (freq) {
457 case 1866:
458 freq_e = DRAM_FREQ_1866M;
459 break;
460 default:
461 pr_err("unsupported DRAM frequency %ud MHz\n", freq);
462 return -EINVAL;
463 }
464
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900465 switch (size) {
466 case 0:
467 return 0;
468 case SZ_256M:
469 size_e = DRAM_SZ_256M;
470 break;
471 case SZ_512M:
472 size_e = DRAM_SZ_512M;
473 break;
474 default:
475 pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
476 size, ch);
477 return -EINVAL;
478 }
479
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900480 writel(0x00000001, dc_base + UMC_DFICSOVRRD);
481 writel(0x00000000, dc_base + UMC_DFITURNOFF);
482
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900483 writel(umc_initctla[freq_e], dc_base + UMC_INITCTLA);
484 writel(umc_initctlb[freq_e], dc_base + UMC_INITCTLB);
485 writel(umc_initctlc[freq_e], dc_base + UMC_INITCTLC);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900486
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900487 writel(umc_drmmr0[freq_e], dc_base + UMC_DRMMR0);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900488 writel(0x00000004, dc_base + UMC_DRMMR1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900489 writel(umc_drmmr2[freq_e], dc_base + UMC_DRMMR2);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900490 writel(0x00000000, dc_base + UMC_DRMMR3);
491
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900492 writel(umc_memconf0a[freq_e][size_e], dc_base + UMC_MEMCONF0A);
493 writel(umc_memconf0b[freq_e][size_e], dc_base + UMC_MEMCONF0B);
494 writel(umc_memconfch[freq_e][size_e], dc_base + UMC_MEMCONFCH);
Wataru Okoshi50fda9d2017-01-18 16:24:38 +0900495 writel(0x00000000, dc_base + UMC_MEMMAPSET);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900496
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900497 writel(umc_cmdctla[freq_e], dc_base + UMC_CMDCTLA);
498 writel(umc_cmdctlb[freq_e], dc_base + UMC_CMDCTLB);
499 writel(umc_cmdctlc[freq_e], dc_base + UMC_CMDCTLC);
500 writel(umc_cmdctle[freq_e][size_e], dc_base + UMC_CMDCTLE);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900501
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900502 writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
503 writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D1);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900504
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900505 writel(umc_wdatactl[freq_e], dc_base + UMC_WDATACTL_D0);
506 writel(umc_wdatactl[freq_e], dc_base + UMC_WDATACTL_D1);
507 writel(umc_odtctl[freq_e], dc_base + UMC_ODTCTL_D0);
508 writel(umc_odtctl[freq_e], dc_base + UMC_ODTCTL_D1);
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900509 writel(umc_dataset[freq_e], dc_base + UMC_DATASET);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900510
511 writel(0x00400020, dc_base + UMC_DCCGCTL);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900512 writel(0x00000003, dc_base + UMC_ACSSETA);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900513 writel(0x00000103, dc_base + UMC_FLOWCTLG);
Masahiro Yamadafc678cb2016-05-24 21:14:00 +0900514 writel(0x00010200, dc_base + UMC_ACSSETB);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900515
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900516 writel(umc_flowctla[freq_e], dc_base + UMC_FLOWCTLA);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900517 writel(0x00004444, dc_base + UMC_FLOWCTLC);
518 writel(0x00000000, dc_base + UMC_DFICUPDCTLA);
519
520 writel(0x00202000, dc_base + UMC_FLOWCTLB);
521 writel(0x00000000, dc_base + UMC_BSICMAPSET);
522 writel(0x00000000, dc_base + UMC_ERRMASKA);
523 writel(0x00000000, dc_base + UMC_ERRMASKB);
524
525 writel(umc_directbusctrla[ch], dc_base + UMC_DIRECTBUSCTRLA);
526
527 writel(0x00000001, dc_base + UMC_INITSET);
528 /* Wait for PHY Init Complete */
529 while (readl(dc_base + UMC_INITSTAT) & BIT(0))
530 cpu_relax();
531
532 writel(0x2A0A0A00, dc_base + UMC_SPCSETB);
533 writel(0x00000000, dc_base + UMC_DFICSOVRRD);
534
535 return 0;
536}
537
538static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base,
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900539 enum dram_board board, unsigned int freq,
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900540 unsigned long size, int ch)
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900541{
542 void __iomem *dc_base = umc_ch_base + 0x00011000;
543 void __iomem *phy_base = phy_ch_base;
544 int ret;
545
546 /* PHY Update Mode (ON) */
547 writel(0x8000003f, dc_base + UMC_DFIPUPDCTLA);
548
549 /* deassert PHY reset signals */
550 writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST,
551 dc_base + UMC_DIOCTLA);
552
Masahiro Yamadab1224f32016-10-08 13:25:24 +0900553 ddrphy_init(phy_base, board, ch);
554
555 umc_poll_phy_init_complete(dc_base);
556
557 ddrphy_init_tail(phy_base, board, freq, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900558
559 ret = umc_dc_init(dc_base, freq, size, ch);
560 if (ret)
561 return ret;
562
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900563 ret = ddrphy_training(phy_base, board, ch);
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900564 if (ret)
565 return ret;
566
567 return 0;
568}
569
570static void um_init(void __iomem *um_base)
571{
572 writel(0x000000ff, um_base + UMC_MBUS0);
573 writel(0x000000ff, um_base + UMC_MBUS1);
574 writel(0x000000ff, um_base + UMC_MBUS2);
575 writel(0x00000001, um_base + UMC_MBUS3);
576 writel(0x00000001, um_base + UMC_MBUS4);
577 writel(0x00000001, um_base + UMC_MBUS5);
578 writel(0x00000001, um_base + UMC_MBUS6);
579 writel(0x00000001, um_base + UMC_MBUS7);
580 writel(0x00000001, um_base + UMC_MBUS8);
581 writel(0x00000001, um_base + UMC_MBUS9);
582 writel(0x00000001, um_base + UMC_MBUS10);
583}
584
585int uniphier_ld20_umc_init(const struct uniphier_board_data *bd)
586{
587 void __iomem *um_base = (void __iomem *)0x5b600000;
588 void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
589 void __iomem *phy_ch_base = (void __iomem *)0x6e200000;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900590 enum dram_board board;
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900591 int ch, ret;
592
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900593 switch (UNIPHIER_BD_BOARD_GET_TYPE(bd->flags)) {
594 case UNIPHIER_BD_BOARD_LD20_REF:
595 board = DRAM_BOARD_LD20_REF;
596 break;
597 case UNIPHIER_BD_BOARD_LD20_GLOBAL:
598 board = DRAM_BOARD_LD20_GLOBAL;
599 break;
Masahiro Yamadabf4266e2016-10-27 23:47:02 +0900600 case UNIPHIER_BD_BOARD_LD20_C1:
601 board = DRAM_BOARD_LD20_C1;
602 break;
Masahiro Yamada40ee94e2016-09-17 03:33:12 +0900603 case UNIPHIER_BD_BOARD_LD21_REF:
604 board = DRAM_BOARD_LD21_REF;
605 break;
606 case UNIPHIER_BD_BOARD_LD21_GLOBAL:
607 board = DRAM_BOARD_LD21_GLOBAL;
608 break;
609 default:
610 pr_err("unsupported board type %d\n",
611 UNIPHIER_BD_BOARD_GET_TYPE(bd->flags));
612 return -EINVAL;
613 }
614
Masahiro Yamadae8e0a5d2017-02-16 15:59:32 +0900615 for (ch = 0; ch < DRAM_CH_NR; ch++) {
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900616 unsigned long size = bd->dram_ch[ch].size;
617 unsigned int width = bd->dram_ch[ch].width;
618
Masahiro Yamadae8e0a5d2017-02-16 15:59:32 +0900619 if (size) {
620 ret = umc_ch_init(umc_ch_base, phy_ch_base, board,
621 bd->dram_freq, size / (width / 16),
622 ch);
623 if (ret) {
624 pr_err("failed to initialize UMC ch%d\n", ch);
625 return ret;
626 }
Masahiro Yamada063eb1e2016-04-21 14:43:18 +0900627 }
628
629 umc_ch_base += 0x00200000;
630 phy_ch_base += 0x00004000;
631 }
632
633 um_init(um_base);
634
635 return 0;
636}