2 * Copyright (C) 2016 Socionext Inc.
4 * based on commit f7a4c9efe333fb1536efa86f9e96dc0ee109fedd of Diag
6 * SPDX-License-Identifier: GPL-2.0+
10 #include <linux/bitops.h>
11 #include <linux/err.h>
13 #include <linux/sizes.h>
14 #include <asm/processor.h>
17 #include "ddrphy-ld20-regs.h"
18 #include "umc-ld20-regs.h"
34 static u32 umc_initctla
[DRAM_FREQ_NR
] = {0x71016D11};
35 static u32 umc_initctlb
[DRAM_FREQ_NR
] = {0x07E390AC};
36 static u32 umc_initctlc
[DRAM_FREQ_NR
] = {0x00FF00FF};
37 static u32 umc_drmmr0
[DRAM_FREQ_NR
] = {0x00000114};
38 static u32 umc_drmmr2
[DRAM_FREQ_NR
] = {0x000002a0};
40 static u32 umc_memconf0a
[DRAM_FREQ_NR
] = {0x00000801};
41 static u32 umc_memconf0b
[DRAM_FREQ_NR
] = {0x00000130};
42 static u32 umc_memconfch
[DRAM_FREQ_NR
] = {0x00033803};
44 static u32 umc_cmdctla
[DRAM_FREQ_NR
] = {0x060D0D20};
45 static u32 umc_cmdctlb
[DRAM_FREQ_NR
] = {0x2D211C08};
46 static u32 umc_cmdctlc
[DRAM_FREQ_NR
] = {0x00150C04};
47 static u32 umc_cmdctle
[DRAM_FREQ_NR
][DRAM_SZ_NR
] = {
48 {0x0049071D, 0x0078071D},
51 static u32 umc_rdatactl_d0
[DRAM_FREQ_NR
] = {0x00000610};
52 static u32 umc_rdatactl_d1
[DRAM_FREQ_NR
] = {0x00000610};
53 static u32 umc_wdatactl_d0
[DRAM_FREQ_NR
] = {0x00000204};
54 static u32 umc_wdatactl_d1
[DRAM_FREQ_NR
] = {0x00000204};
55 static u32 umc_odtctl_d0
[DRAM_FREQ_NR
] = {0x02000002};
56 static u32 umc_odtctl_d1
[DRAM_FREQ_NR
] = {0x02000002};
57 static u32 umc_dataset
[DRAM_FREQ_NR
] = {0x04000000};
59 static u32 umc_flowctla
[DRAM_FREQ_NR
] = {0x0081E01E};
60 static u32 umc_directbusctrla
[DRAM_CH_NR
] = {
61 0x00000000, 0x00000001, 0x00000001
65 static void ddrphy_init(void __iomem
*phy_base
, enum dram_freq freq
)
67 writel(0x00000001, phy_base
+ PHY_UNIQUIFY_TSMC_IO_1
);
68 while ((readl(phy_base
+ PHY_UNIQUIFY_TSMC_IO_1
) & BIT(1)))
71 writel(0x00000000, phy_base
+ PHY_DLL_INCR_TRIM_3
);
72 writel(0x00000000, phy_base
+ PHY_DLL_INCR_TRIM_1
);
73 writel(0x00000000, phy_base
+ PHY_LANE_SEL
);
74 writel(0x00000005, phy_base
+ PHY_DLL_TRIM_1
);
75 writel(0x0000000a, phy_base
+ PHY_DLL_TRIM_3
);
76 writel(0x00000006, phy_base
+ PHY_LANE_SEL
);
77 writel(0x00000005, phy_base
+ PHY_DLL_TRIM_1
);
78 writel(0x0000000a, phy_base
+ PHY_DLL_TRIM_3
);
79 writel(0x0000000c, phy_base
+ PHY_LANE_SEL
);
80 writel(0x00000005, phy_base
+ PHY_DLL_TRIM_1
);
81 writel(0x0000000a, phy_base
+ PHY_DLL_TRIM_3
);
82 writel(0x00000012, phy_base
+ PHY_LANE_SEL
);
83 writel(0x00000005, phy_base
+ PHY_DLL_TRIM_1
);
84 writel(0x0000000a, phy_base
+ PHY_DLL_TRIM_3
);
85 writel(0x00000001, phy_base
+ PHY_SCL_WINDOW_TRIM
);
86 writel(0x00000000, phy_base
+ PHY_UNQ_ANALOG_DLL_1
);
87 writel(0x50bb40b1, phy_base
+ PHY_PAD_CTRL
);
88 writel(0x00000070, phy_base
+ PHY_VREF_TRAINING
);
89 writel(0x01000075, phy_base
+ PHY_SCL_CONFIG_1
);
90 writel(0x00000501, phy_base
+ PHY_SCL_CONFIG_2
);
91 writel(0x00000000, phy_base
+ PHY_SCL_CONFIG_3
);
92 writel(0x000261c0, phy_base
+ PHY_DYNAMIC_WRITE_BIT_LVL
);
93 writel(0x00000000, phy_base
+ PHY_SCL_CONFIG_4
);
94 writel(0x000000a0, phy_base
+ PHY_SCL_GATE_TIMING
);
95 writel(0x02a000a0, phy_base
+ PHY_WRLVL_DYN_ODT
);
96 writel(0x00840004, phy_base
+ PHY_WRLVL_ON_OFF
);
97 writel(0x0000020d, phy_base
+ PHY_DLL_ADRCTRL
);
98 writel(0x00000000, phy_base
+ PHY_LANE_SEL
);
99 writel(0x0000008d, phy_base
+ PHY_DLL_TRIM_CLK
);
100 writel(0xa800100d, phy_base
+ PHY_DLL_RECALIB
);
101 writel(0x00005076, phy_base
+ PHY_SCL_LATENCY
);
104 static int ddrphy_training(void __iomem
*phy_base
)
106 writel(0x0000000f, phy_base
+ PHY_WRLVL_AUTOINC_TRIM
);
107 writel(0x00010000, phy_base
+ PHY_DLL_TRIM_2
);
108 writel(0x50000000, phy_base
+ PHY_SCL_START
);
110 while ((readl(phy_base
+ PHY_SCL_START
) & BIT(28)))
113 writel(0x00000000, phy_base
+ PHY_DISABLE_GATING_FOR_SCL
);
114 writel(0xff00ff00, phy_base
+ PHY_SCL_DATA_0
);
115 writel(0xff00ff00, phy_base
+ PHY_SCL_DATA_1
);
116 writel(0x00080000, phy_base
+ PHY_SCL_START_ADDR
);
117 writel(0x11000000, phy_base
+ PHY_SCL_START
);
119 while ((readl(phy_base
+ PHY_SCL_START
) & BIT(28)))
122 writel(0x00000000, phy_base
+ PHY_SCL_START_ADDR
);
123 writel(0x30500000, phy_base
+ PHY_SCL_START
);
125 while ((readl(phy_base
+ PHY_SCL_START
) & BIT(28)))
128 writel(0x00000001, phy_base
+ PHY_DISABLE_GATING_FOR_SCL
);
129 writel(0x00000010, phy_base
+ PHY_SCL_MAIN_CLK_DELTA
);
130 writel(0x789b3de0, phy_base
+ PHY_SCL_DATA_0
);
131 writel(0xf10e4a56, phy_base
+ PHY_SCL_DATA_1
);
132 writel(0x11000000, phy_base
+ PHY_SCL_START
);
134 while ((readl(phy_base
+ PHY_SCL_START
) & BIT(28)))
137 writel(0x34000000, phy_base
+ PHY_SCL_START
);
139 while ((readl(phy_base
+ PHY_SCL_START
) & BIT(28)))
142 writel(0x00000003, phy_base
+ PHY_DISABLE_GATING_FOR_SCL
);
147 static int umc_dc_init(void __iomem
*dc_base
, enum dram_freq freq
,
148 unsigned long size
, int ch
)
150 enum dram_size size_e
;
156 size_e
= DRAM_SZ_256M
;
159 size_e
= DRAM_SZ_512M
;
162 pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
167 /* Wait for PHY Init Complete */
168 while (!(readl(dc_base
+ UMC_DFISTCTLC
) & BIT(0)))
171 writel(0x00000001, dc_base
+ UMC_DFICSOVRRD
);
172 writel(0x00000000, dc_base
+ UMC_DFITURNOFF
);
174 writel(umc_initctla
[freq
], dc_base
+ UMC_INITCTLA
);
175 writel(umc_initctlb
[freq
], dc_base
+ UMC_INITCTLB
);
176 writel(umc_initctlc
[freq
], dc_base
+ UMC_INITCTLC
);
178 writel(umc_drmmr0
[freq
], dc_base
+ UMC_DRMMR0
);
179 writel(0x00000004, dc_base
+ UMC_DRMMR1
);
180 writel(umc_drmmr2
[freq
], dc_base
+ UMC_DRMMR2
);
181 writel(0x00000000, dc_base
+ UMC_DRMMR3
);
183 writel(umc_memconf0a
[freq
], dc_base
+ UMC_MEMCONF0A
);
184 writel(umc_memconf0b
[freq
], dc_base
+ UMC_MEMCONF0B
);
185 writel(umc_memconfch
[freq
], dc_base
+ UMC_MEMCONFCH
);
186 writel(0x00000008, dc_base
+ UMC_MEMMAPSET
);
188 writel(umc_cmdctla
[freq
], dc_base
+ UMC_CMDCTLA
);
189 writel(umc_cmdctlb
[freq
], dc_base
+ UMC_CMDCTLB
);
190 writel(umc_cmdctlc
[freq
], dc_base
+ UMC_CMDCTLC
);
191 writel(umc_cmdctle
[freq
][size_e
], dc_base
+ UMC_CMDCTLE
);
193 writel(umc_rdatactl_d0
[freq
], dc_base
+ UMC_RDATACTL_D0
);
194 writel(umc_rdatactl_d1
[freq
], dc_base
+ UMC_RDATACTL_D1
);
196 writel(umc_wdatactl_d0
[freq
], dc_base
+ UMC_WDATACTL_D0
);
197 writel(umc_wdatactl_d1
[freq
], dc_base
+ UMC_WDATACTL_D1
);
198 writel(umc_odtctl_d0
[freq
], dc_base
+ UMC_ODTCTL_D0
);
199 writel(umc_odtctl_d1
[freq
], dc_base
+ UMC_ODTCTL_D1
);
200 writel(umc_dataset
[freq
], dc_base
+ UMC_DATASET
);
202 writel(0x00400020, dc_base
+ UMC_DCCGCTL
);
203 writel(0x00000003, dc_base
+ UMC_ACSCTLA
);
204 writel(0x00000103, dc_base
+ UMC_FLOWCTLG
);
205 writel(0x00010200, dc_base
+ UMC_ACSSETA
);
207 writel(umc_flowctla
[freq
], dc_base
+ UMC_FLOWCTLA
);
208 writel(0x00004444, dc_base
+ UMC_FLOWCTLC
);
209 writel(0x00000000, dc_base
+ UMC_DFICUPDCTLA
);
211 writel(0x00202000, dc_base
+ UMC_FLOWCTLB
);
212 writel(0x00000000, dc_base
+ UMC_BSICMAPSET
);
213 writel(0x00000000, dc_base
+ UMC_ERRMASKA
);
214 writel(0x00000000, dc_base
+ UMC_ERRMASKB
);
216 writel(umc_directbusctrla
[ch
], dc_base
+ UMC_DIRECTBUSCTRLA
);
218 writel(0x00000001, dc_base
+ UMC_INITSET
);
219 /* Wait for PHY Init Complete */
220 while (readl(dc_base
+ UMC_INITSTAT
) & BIT(0))
223 writel(0x2A0A0A00, dc_base
+ UMC_SPCSETB
);
224 writel(0x00000000, dc_base
+ UMC_DFICSOVRRD
);
229 static int umc_ch_init(void __iomem
*umc_ch_base
, void __iomem
*phy_ch_base
,
230 enum dram_freq freq
, unsigned long size
, int ch
)
232 void __iomem
*dc_base
= umc_ch_base
+ 0x00011000;
233 void __iomem
*phy_base
= phy_ch_base
;
236 /* PHY Update Mode (ON) */
237 writel(0x8000003f, dc_base
+ UMC_DFIPUPDCTLA
);
239 /* deassert PHY reset signals */
240 writel(UMC_DIOCTLA_CTL_NRST
| UMC_DIOCTLA_CFG_NRST
,
241 dc_base
+ UMC_DIOCTLA
);
243 ddrphy_init(phy_base
, freq
);
245 ret
= umc_dc_init(dc_base
, freq
, size
, ch
);
249 ret
= ddrphy_training(phy_base
);
256 static void um_init(void __iomem
*um_base
)
258 writel(0x000000ff, um_base
+ UMC_MBUS0
);
259 writel(0x000000ff, um_base
+ UMC_MBUS1
);
260 writel(0x000000ff, um_base
+ UMC_MBUS2
);
261 writel(0x00000001, um_base
+ UMC_MBUS3
);
262 writel(0x00000001, um_base
+ UMC_MBUS4
);
263 writel(0x00000001, um_base
+ UMC_MBUS5
);
264 writel(0x00000001, um_base
+ UMC_MBUS6
);
265 writel(0x00000001, um_base
+ UMC_MBUS7
);
266 writel(0x00000001, um_base
+ UMC_MBUS8
);
267 writel(0x00000001, um_base
+ UMC_MBUS9
);
268 writel(0x00000001, um_base
+ UMC_MBUS10
);
271 int uniphier_ld20_umc_init(const struct uniphier_board_data
*bd
)
273 void __iomem
*um_base
= (void __iomem
*)0x5b600000;
274 void __iomem
*umc_ch_base
= (void __iomem
*)0x5b800000;
275 void __iomem
*phy_ch_base
= (void __iomem
*)0x6e200000;
279 switch (bd
->dram_freq
) {
281 freq
= DRAM_FREQ_1866M
;
284 pr_err("unsupported DRAM frequency %d MHz\n", bd
->dram_freq
);
288 for (ch
= 0; ch
< bd
->dram_nr_ch
; ch
++) {
289 unsigned long size
= bd
->dram_ch
[ch
].size
;
290 unsigned int width
= bd
->dram_ch
[ch
].width
;
292 ret
= umc_ch_init(umc_ch_base
, phy_ch_base
, freq
,
293 size
/ (width
/ 16), ch
);
295 pr_err("failed to initialize UMC ch%d\n", ch
);
299 umc_ch_base
+= 0x00200000;
300 phy_ch_base
+= 0x00004000;