]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[people/ms/u-boot.git] / arch / arm / cpu / arm926ejs / mxs / spl_mem_init.c
CommitLineData
04fe4273
MV
1/*
2 * Freescale i.MX28 RAM init
3 *
4 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
5 * on behalf of DENX Software Engineering GmbH
6 *
1a459660 7 * SPDX-License-Identifier: GPL-2.0+
04fe4273
MV
8 */
9
10#include <common.h>
11#include <config.h>
12#include <asm/io.h>
04fe4273 13#include <asm/arch/imx-regs.h>
5c2f444c 14#include <asm/arch/sys_proto.h>
f0930882 15#include <linux/compiler.h>
04fe4273 16
1e0cf5c3 17#include "mxs_init.h"
04fe4273 18
393ff47b
OS
19static uint32_t dram_vals[] = {
20/*
21 * i.MX28 DDR2 at 200MHz
22 */
23#if defined(CONFIG_MX28)
40083c52
MV
24 0x00000000, 0x00000000, 0x00000000, 0x00000000,
25 0x00000000, 0x00000000, 0x00000000, 0x00000000,
26 0x00000000, 0x00000000, 0x00000000, 0x00000000,
27 0x00000000, 0x00000000, 0x00000000, 0x00000000,
28 0x00000000, 0x00000100, 0x00000000, 0x00000000,
29 0x00000000, 0x00000000, 0x00000000, 0x00000000,
30 0x00000000, 0x00000000, 0x00010101, 0x01010101,
d2f7ae14 31 0x000f0f01, 0x0f02020a, 0x00000000, 0x00010101,
40083c52 32 0x00000100, 0x00000100, 0x00000000, 0x00000002,
b33426ca
FE
33 0x01010000, 0x07080403, 0x06005003, 0x0a0000c8,
34 0x02009c40, 0x0002030c, 0x0036a609, 0x031a0612,
40083c52
MV
35 0x02030202, 0x00c8001c, 0x00000000, 0x00000000,
36 0x00012100, 0xffff0303, 0x00012100, 0xffff0303,
37 0x00012100, 0xffff0303, 0x00012100, 0xffff0303,
38 0x00000003, 0x00000000, 0x00000000, 0x00000000,
39 0x00000000, 0x00000000, 0x00000000, 0x00000000,
40 0x00000000, 0x00000000, 0x00000612, 0x01000F02,
b33426ca
FE
41 0x06120612, 0x00000200, 0x00020007, 0xf4004a27,
42 0xf4004a27, 0xf4004a27, 0xf4004a27, 0x07000300,
43 0x07000300, 0x07400300, 0x07400300, 0x00000005,
40083c52
MV
44 0x00000000, 0x00000000, 0x01000000, 0x01020408,
45 0x08040201, 0x000f1133, 0x00000000, 0x00001f04,
46 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
47 0x00001f04, 0x00001f04, 0x00001f04, 0x00000000,
48 0x00000000, 0x00000000, 0x00000000, 0x00000000,
49 0x00000000, 0x00000000, 0x00000000, 0x00000000,
50 0x00000000, 0x00000000, 0x00000000, 0x00000000,
51 0x00000000, 0x00000000, 0x00000000, 0x00000000,
52 0x00000000, 0x00000000, 0x00000000, 0x00000000,
53 0x00000000, 0x00000000, 0x00000000, 0x00000000,
54 0x00000000, 0x00000000, 0x00000000, 0x00000000,
55 0x00000000, 0x00000000, 0x00000000, 0x00000000,
56 0x00000000, 0x00000000, 0x00000000, 0x00000000,
57 0x00000000, 0x00000000, 0x00000000, 0x00000000,
58 0x00000000, 0x00000000, 0x00000000, 0x00000000,
59 0x00000000, 0x00000000, 0x00000000, 0x00000000,
60 0x00000000, 0x00000000, 0x00000000, 0x00000000,
61 0x00000000, 0x00000000, 0x00000000, 0x00000000,
62 0x00000000, 0x00000000, 0x00000000, 0x00000000,
63 0x00000000, 0x00000000, 0x00000000, 0x00000000,
b33426ca
FE
64 0x00000000, 0x00000000, 0x00010000, 0x00030404,
65 0x00000003, 0x00000000, 0x00000000, 0x00000000,
40083c52
MV
66 0x00000000, 0x00000000, 0x00000000, 0x01010000,
67 0x01000000, 0x03030000, 0x00010303, 0x01020202,
68 0x00000000, 0x02040303, 0x21002103, 0x00061200,
b33426ca 69 0x06120612, 0x04420442, 0x04420442, 0x00040004,
40083c52 70 0x00040004, 0x00000000, 0x00000000, 0x00000000,
b33426ca 71 0x00000000, 0xffffffff
1ddf386e
OS
72
73/*
74 * i.MX23 DDR at 133MHz
75 */
76#elif defined(CONFIG_MX23)
77 0x01010001, 0x00010100, 0x01000101, 0x00000001,
78 0x00000101, 0x00000000, 0x00010000, 0x01000001,
79 0x00000000, 0x00000001, 0x07000200, 0x00070202,
80 0x02020000, 0x04040a01, 0x00000201, 0x02040000,
81 0x02000000, 0x19000f08, 0x0d0d0000, 0x02021313,
82 0x02061521, 0x0000000a, 0x00080008, 0x00200020,
83 0x00200020, 0x00200020, 0x000003f7, 0x00000000,
84 0x00000000, 0x00000020, 0x00000020, 0x00c80000,
85 0x000a23cd, 0x000000c8, 0x00006665, 0x00000000,
86 0x00000101, 0x00040001, 0x00000000, 0x00000000,
87 0x00010000
393ff47b
OS
88#else
89#error Unsupported memory initialization
90#endif
04fe4273
MV
91};
92
f0930882 93__weak void mxs_adjust_memory_params(uint32_t *dram_vals)
e3ddc646
MV
94{
95}
e3ddc646 96
39a538d9 97#ifdef CONFIG_MX28
393ff47b 98static void initialize_dram_values(void)
04fe4273
MV
99{
100 int i;
101
393ff47b 102 mxs_adjust_memory_params(dram_vals);
e3ddc646 103
393ff47b
OS
104 for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
105 writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
39a538d9
FE
106}
107#else
108static void initialize_dram_values(void)
109{
110 int i;
111
112 mxs_adjust_memory_params(dram_vals);
113
286a88cf
FE
114 /*
115 * HW_DRAM_CTL27, HW_DRAM_CTL28 and HW_DRAM_CTL35 are not initialized as
116 * per FSL bootlets code.
117 *
118 * mx23 Reference Manual marks HW_DRAM_CTL27 and HW_DRAM_CTL28 as
119 * "reserved".
120 * HW_DRAM_CTL8 is setup as the last element.
121 * So skip the initialization of these HW_DRAM_CTL registers.
122 */
39a538d9
FE
123 for (i = 0; i < ARRAY_SIZE(dram_vals); i++) {
124 if (i == 8 || i == 27 || i == 28 || i == 35)
125 continue;
126 writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
127 }
1ddf386e 128
89075d3f
OS
129 /*
130 * Enable tRAS lockout in HW_DRAM_CTL08 ; it must be the last
131 * element to be set
132 */
1ddf386e 133 writel((1 << 24), MXS_DRAM_BASE + (4 * 8));
04fe4273 134}
39a538d9 135#endif
04fe4273 136
a918a53c 137static void mxs_mem_init_clock(void)
04fe4273 138{
9c471142
OS
139 struct mxs_clkctrl_regs *clkctrl_regs =
140 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
30af6c0b
OS
141#if defined(CONFIG_MX23)
142 /* Fractional divider for ref_emi is 33 ; 480 * 18 / 33 = 266MHz */
143 const unsigned char divider = 33;
144#elif defined(CONFIG_MX28)
145 /* Fractional divider for ref_emi is 21 ; 480 * 18 / 21 = 411MHz */
146 const unsigned char divider = 21;
147#endif
04fe4273
MV
148
149 /* Gate EMI clock */
56df16f2
RD
150 writeb(CLKCTRL_FRAC_CLKGATE,
151 &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]);
04fe4273 152
30af6c0b
OS
153 /* Set fractional divider for ref_emi */
154 writeb(CLKCTRL_FRAC_CLKGATE | (divider & CLKCTRL_FRAC_FRAC_MASK),
56df16f2 155 &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]);
04fe4273
MV
156
157 /* Ungate EMI clock */
56df16f2
RD
158 writeb(CLKCTRL_FRAC_CLKGATE,
159 &clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_EMI]);
04fe4273
MV
160
161 early_delay(11000);
162
56df16f2 163 /* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */
04fe4273
MV
164 writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
165 (1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
166 &clkctrl_regs->hw_clkctrl_emi);
167
168 /* Unbypass EMI */
169 writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
170 &clkctrl_regs->hw_clkctrl_clkseq_clr);
171
172 early_delay(10000);
173}
174
a918a53c 175static void mxs_mem_setup_cpu_and_hbus(void)
04fe4273 176{
9c471142
OS
177 struct mxs_clkctrl_regs *clkctrl_regs =
178 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
04fe4273 179
56df16f2
RD
180 /* Set fractional divider for ref_cpu to 480 * 18 / 19 = 454MHz
181 * and ungate CPU clock */
182 writeb(19 & CLKCTRL_FRAC_FRAC_MASK,
183 (uint8_t *)&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]);
04fe4273
MV
184
185 /* Set CPU bypass */
186 writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
187 &clkctrl_regs->hw_clkctrl_clkseq_set);
188
189 /* HBUS = 151MHz */
190 writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
191 writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
192 &clkctrl_regs->hw_clkctrl_hbus_clr);
193
194 early_delay(10000);
195
196 /* CPU clock divider = 1 */
197 clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
198 CLKCTRL_CPU_DIV_CPU_MASK, 1);
199
200 /* Disable CPU bypass */
201 writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
202 &clkctrl_regs->hw_clkctrl_clkseq_clr);
8f975865
MV
203
204 early_delay(15000);
04fe4273
MV
205}
206
a918a53c 207static void mxs_mem_setup_vdda(void)
04fe4273 208{
9c471142
OS
209 struct mxs_power_regs *power_regs =
210 (struct mxs_power_regs *)MXS_POWER_BASE;
04fe4273
MV
211
212 writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
213 (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
214 POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
215 &power_regs->hw_power_vddactrl);
216}
217
1e0cf5c3 218uint32_t mxs_mem_get_size(void)
3a4ce833
MV
219{
220 uint32_t sz, da;
221 uint32_t *vt = (uint32_t *)0x20;
494931a6
MV
222 /* The following is "subs pc, r14, #4", used as return from DABT. */
223 const uint32_t data_abort_memdetect_handler = 0xe25ef004;
3a4ce833
MV
224
225 /* Replace the DABT handler. */
226 da = vt[4];
494931a6 227 vt[4] = data_abort_memdetect_handler;
3a4ce833
MV
228
229 sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
3a4ce833
MV
230
231 /* Restore the old DABT handler. */
232 vt[4] = da;
0239c2fb
MV
233
234 return sz;
3a4ce833
MV
235}
236
30af6c0b
OS
237#ifdef CONFIG_MX23
238static void mx23_mem_setup_vddmem(void)
239{
240 struct mxs_power_regs *power_regs =
241 (struct mxs_power_regs *)MXS_POWER_BASE;
242
dd3ecf02
MV
243 clrbits_le32(&power_regs->hw_power_vddmemctrl,
244 POWER_VDDMEMCTRL_ENABLE_ILIMIT);
30af6c0b 245
30af6c0b
OS
246}
247
248static void mx23_mem_init(void)
249{
5c2f444c
MV
250 /*
251 * Reset/ungate the EMI block. This is essential, otherwise the system
252 * suffers from memory instability. This thing is mx23 specific and is
253 * no longer present on mx28.
254 */
255 mxs_reset_block((struct mxs_register_32 *)MXS_EMI_BASE);
256
30af6c0b
OS
257 mx23_mem_setup_vddmem();
258
259 /*
260 * Configure the DRAM registers
261 */
262
263 /* Clear START and SREFRESH bit from DRAM_CTL8 */
264 clrbits_le32(MXS_DRAM_BASE + 0x20, (1 << 16) | (1 << 8));
265
266 initialize_dram_values();
267
8a47c997 268 /* Set START bit in DRAM_CTL8 */
30af6c0b
OS
269 setbits_le32(MXS_DRAM_BASE + 0x20, 1 << 16);
270
271 clrbits_le32(MXS_DRAM_BASE + 0x40, 1 << 17);
272 early_delay(20000);
273
274 /* Adjust EMI port priority. */
fb7383a7 275 clrsetbits_le32(0x80020000, 0x1f << 16, 0x2);
30af6c0b
OS
276 early_delay(20000);
277
278 setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 19);
279 setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 11);
30af6c0b
OS
280}
281#endif
282
283#ifdef CONFIG_MX28
284static void mx28_mem_init(void)
04fe4273 285{
9c471142
OS
286 struct mxs_pinctrl_regs *pinctrl_regs =
287 (struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE;
04fe4273
MV
288
289 /* Set DDR2 mode */
290 writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
291 &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
292
04fe4273
MV
293 /*
294 * Configure the DRAM registers
295 */
296
297 /* Clear START bit from DRAM_CTL16 */
298 clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
299
393ff47b 300 initialize_dram_values();
04fe4273
MV
301
302 /* Clear SREFRESH bit from DRAM_CTL17 */
303 clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
304
305 /* Set START bit in DRAM_CTL16 */
306 setbits_le32(MXS_DRAM_BASE + 0x40, 1);
307
308 /* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
309 while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
310 ;
30af6c0b
OS
311}
312#endif
313
314void mxs_mem_init(void)
315{
316 early_delay(11000);
317
318 mxs_mem_init_clock();
319
320 mxs_mem_setup_vdda();
321
322#if defined(CONFIG_MX23)
323 mx23_mem_init();
324#elif defined(CONFIG_MX28)
325 mx28_mem_init();
326#endif
04fe4273 327
04fe4273
MV
328 early_delay(10000);
329
1e0cf5c3 330 mxs_mem_setup_cpu_and_hbus();
04fe4273 331}