]>
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 | * | |
7 | * See file CREDITS for list of people who contributed to this | |
8 | * project. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU General Public License as | |
12 | * published by the Free Software Foundation; either version 2 of | |
13 | * the License, or (at your option) any later version. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU General Public License | |
21 | * along with this program; if not, write to the Free Software | |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
23 | * MA 02111-1307 USA | |
24 | */ | |
25 | ||
26 | #include <common.h> | |
27 | #include <config.h> | |
28 | #include <asm/io.h> | |
29 | #include <asm/arch/iomux-mx28.h> | |
30 | #include <asm/arch/imx-regs.h> | |
31 | ||
c944a3ef | 32 | #include "mx28_init.h" |
04fe4273 MV |
33 | |
34 | uint32_t dram_vals[] = { | |
35 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
36 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
37 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
38 | 0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000, | |
39 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
40 | 0x00000000, 0x00010101, 0x01010101, 0x000f0f01, 0x0f02020a, | |
41 | 0x00000000, 0x00010101, 0x00000100, 0x00000100, 0x00000000, | |
42 | 0x00000002, 0x01010000, 0x05060302, 0x06005003, 0x0a0000c8, | |
43 | 0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612, 0x02030202, | |
44 | 0x00c8001c, 0x00000000, 0x00000000, 0x00012100, 0xffff0303, | |
45 | 0x00012100, 0xffff0303, 0x00012100, 0xffff0303, 0x00012100, | |
46 | 0xffff0303, 0x00000003, 0x00000000, 0x00000000, 0x00000000, | |
47 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
48 | 0x00000000, 0x00000612, 0x01000F02, 0x06120612, 0x00000200, | |
49 | 0x00020007, 0xf5014b27, 0xf5014b27, 0xf5014b27, 0xf5014b27, | |
50 | 0x07000300, 0x07000300, 0x07000300, 0x07000300, 0x00000006, | |
51 | 0x00000000, 0x00000000, 0x01000000, 0x01020408, 0x08040201, | |
52 | 0x000f1133, 0x00000000, 0x00001f04, 0x00001f04, 0x00001f04, | |
53 | 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, | |
54 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
55 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
56 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
57 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
58 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
59 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
60 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
61 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
62 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
63 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
64 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
65 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
66 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
67 | 0x00000000, 0x00000000, 0x00010000, 0x00020304, 0x00000004, | |
68 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | |
69 | 0x00000000, 0x01010000, 0x01000000, 0x03030000, 0x00010303, | |
70 | 0x01020202, 0x00000000, 0x02040303, 0x21002103, 0x00061200, | |
71 | 0x06120612, 0x04320432, 0x04320432, 0x00040004, 0x00040004, | |
72 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010001 | |
73 | }; | |
74 | ||
75 | void init_m28_200mhz_ddr2(void) | |
76 | { | |
77 | int i; | |
78 | ||
79 | for (i = 0; i < ARRAY_SIZE(dram_vals); i++) | |
80 | writel(dram_vals[i], MXS_DRAM_BASE + (4 * i)); | |
81 | } | |
82 | ||
83 | void mx28_mem_init_clock(void) | |
84 | { | |
85 | struct mx28_clkctrl_regs *clkctrl_regs = | |
86 | (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE; | |
87 | ||
88 | /* Gate EMI clock */ | |
89 | writel(CLKCTRL_FRAC0_CLKGATEEMI, | |
90 | &clkctrl_regs->hw_clkctrl_frac0_set); | |
91 | ||
92 | /* EMI = 205MHz */ | |
93 | writel(CLKCTRL_FRAC0_EMIFRAC_MASK, | |
94 | &clkctrl_regs->hw_clkctrl_frac0_set); | |
95 | writel((0x2a << CLKCTRL_FRAC0_EMIFRAC_OFFSET) & | |
96 | CLKCTRL_FRAC0_EMIFRAC_MASK, | |
97 | &clkctrl_regs->hw_clkctrl_frac0_clr); | |
98 | ||
99 | /* Ungate EMI clock */ | |
100 | writel(CLKCTRL_FRAC0_CLKGATEEMI, | |
101 | &clkctrl_regs->hw_clkctrl_frac0_clr); | |
102 | ||
103 | early_delay(11000); | |
104 | ||
105 | writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) | | |
106 | (1 << CLKCTRL_EMI_DIV_XTAL_OFFSET), | |
107 | &clkctrl_regs->hw_clkctrl_emi); | |
108 | ||
109 | /* Unbypass EMI */ | |
110 | writel(CLKCTRL_CLKSEQ_BYPASS_EMI, | |
111 | &clkctrl_regs->hw_clkctrl_clkseq_clr); | |
112 | ||
113 | early_delay(10000); | |
114 | } | |
115 | ||
116 | void mx28_mem_setup_cpu_and_hbus(void) | |
117 | { | |
118 | struct mx28_clkctrl_regs *clkctrl_regs = | |
119 | (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE; | |
120 | ||
121 | /* CPU = 454MHz and ungate CPU clock */ | |
122 | clrsetbits_le32(&clkctrl_regs->hw_clkctrl_frac0, | |
123 | CLKCTRL_FRAC0_CPUFRAC_MASK | CLKCTRL_FRAC0_CLKGATECPU, | |
124 | 19 << CLKCTRL_FRAC0_CPUFRAC_OFFSET); | |
125 | ||
126 | /* Set CPU bypass */ | |
127 | writel(CLKCTRL_CLKSEQ_BYPASS_CPU, | |
128 | &clkctrl_regs->hw_clkctrl_clkseq_set); | |
129 | ||
130 | /* HBUS = 151MHz */ | |
131 | writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set); | |
132 | writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK, | |
133 | &clkctrl_regs->hw_clkctrl_hbus_clr); | |
134 | ||
135 | early_delay(10000); | |
136 | ||
137 | /* CPU clock divider = 1 */ | |
138 | clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu, | |
139 | CLKCTRL_CPU_DIV_CPU_MASK, 1); | |
140 | ||
141 | /* Disable CPU bypass */ | |
142 | writel(CLKCTRL_CLKSEQ_BYPASS_CPU, | |
143 | &clkctrl_regs->hw_clkctrl_clkseq_clr); | |
144 | } | |
145 | ||
146 | void mx28_mem_setup_vdda(void) | |
147 | { | |
148 | struct mx28_power_regs *power_regs = | |
149 | (struct mx28_power_regs *)MXS_POWER_BASE; | |
150 | ||
151 | writel((0xc << POWER_VDDACTRL_TRG_OFFSET) | | |
152 | (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) | | |
153 | POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW, | |
154 | &power_regs->hw_power_vddactrl); | |
155 | } | |
156 | ||
157 | void mx28_mem_setup_vddd(void) | |
158 | { | |
159 | struct mx28_power_regs *power_regs = | |
160 | (struct mx28_power_regs *)MXS_POWER_BASE; | |
161 | ||
162 | writel((0x1c << POWER_VDDDCTRL_TRG_OFFSET) | | |
163 | (0x7 << POWER_VDDDCTRL_BO_OFFSET_OFFSET) | | |
164 | POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW, | |
165 | &power_regs->hw_power_vdddctrl); | |
166 | } | |
167 | ||
3a4ce833 MV |
168 | #define HW_DIGCTRL_SCRATCH0 0x8001c280 |
169 | #define HW_DIGCTRL_SCRATCH1 0x8001c290 | |
170 | void data_abort_memdetect_handler(void) __attribute__((naked)); | |
171 | void data_abort_memdetect_handler(void) | |
172 | { | |
173 | asm volatile("subs pc, r14, #4"); | |
174 | } | |
175 | ||
176 | void mx28_mem_get_size(void) | |
177 | { | |
178 | uint32_t sz, da; | |
179 | uint32_t *vt = (uint32_t *)0x20; | |
180 | ||
181 | /* Replace the DABT handler. */ | |
182 | da = vt[4]; | |
183 | vt[4] = (uint32_t)&data_abort_memdetect_handler; | |
184 | ||
185 | sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); | |
186 | writel(sz, HW_DIGCTRL_SCRATCH0); | |
187 | writel(sz, HW_DIGCTRL_SCRATCH1); | |
188 | ||
189 | /* Restore the old DABT handler. */ | |
190 | vt[4] = da; | |
191 | } | |
192 | ||
04fe4273 MV |
193 | void mx28_mem_init(void) |
194 | { | |
195 | struct mx28_clkctrl_regs *clkctrl_regs = | |
196 | (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE; | |
197 | struct mx28_pinctrl_regs *pinctrl_regs = | |
198 | (struct mx28_pinctrl_regs *)MXS_PINCTRL_BASE; | |
199 | ||
200 | /* Set DDR2 mode */ | |
201 | writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2, | |
202 | &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set); | |
203 | ||
204 | /* Power up PLL0 */ | |
205 | writel(CLKCTRL_PLL0CTRL0_POWER, | |
206 | &clkctrl_regs->hw_clkctrl_pll0ctrl0_set); | |
207 | ||
208 | early_delay(11000); | |
209 | ||
210 | mx28_mem_init_clock(); | |
211 | ||
212 | mx28_mem_setup_vdda(); | |
213 | ||
214 | /* | |
215 | * Configure the DRAM registers | |
216 | */ | |
217 | ||
218 | /* Clear START bit from DRAM_CTL16 */ | |
219 | clrbits_le32(MXS_DRAM_BASE + 0x40, 1); | |
220 | ||
221 | init_m28_200mhz_ddr2(); | |
222 | ||
223 | /* Clear SREFRESH bit from DRAM_CTL17 */ | |
224 | clrbits_le32(MXS_DRAM_BASE + 0x44, 1); | |
225 | ||
226 | /* Set START bit in DRAM_CTL16 */ | |
227 | setbits_le32(MXS_DRAM_BASE + 0x40, 1); | |
228 | ||
229 | /* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */ | |
230 | while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20))) | |
231 | ; | |
232 | ||
233 | mx28_mem_setup_vddd(); | |
234 | ||
235 | early_delay(10000); | |
236 | ||
237 | mx28_mem_setup_cpu_and_hbus(); | |
3a4ce833 MV |
238 | |
239 | mx28_mem_get_size(); | |
04fe4273 | 240 | } |