]>
Commit | Line | Data |
---|---|---|
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 |
19 | static 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 | 98 | static 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 | |
108 | static 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 | 137 | static 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 | 175 | static 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 | 207 | static 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 | 218 | uint32_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 |
238 | static 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 | ||
248 | static 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 | |
284 | static 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 | ||
314 | void 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 | } |