]>
Commit | Line | Data |
---|---|---|
310ae55e | 1 | /* |
effea9d1 | 2 | * SoC-specific lowlevel code for DA850 |
310ae55e HS |
3 | * |
4 | * Copyright (C) 2011 | |
5 | * Heiko Schocher, DENX Software Engineering, hs@denx.de. | |
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 modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2 of the License, or | |
13 | * (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., 675 Mass Ave, Cambridge, MA 02139, USA. | |
23 | */ | |
24 | #include <common.h> | |
25 | #include <nand.h> | |
26 | #include <ns16550.h> | |
27 | #include <post.h> | |
effea9d1 | 28 | #include <asm/arch/da850_lowlevel.h> |
310ae55e HS |
29 | #include <asm/arch/hardware.h> |
30 | #include <asm/arch/ddr2_defs.h> | |
31 | #include <asm/arch/emif_defs.h> | |
32 | ||
effea9d1 | 33 | void da850_waitloop(unsigned long loopcnt) |
310ae55e HS |
34 | { |
35 | unsigned long i; | |
36 | ||
37 | for (i = 0; i < loopcnt; i++) | |
38 | asm(" NOP"); | |
39 | } | |
40 | ||
effea9d1 | 41 | int da850_pll_init(struct davinci_pllc_regs *reg, unsigned long pllmult) |
310ae55e HS |
42 | { |
43 | if (reg == davinci_pllc0_regs) | |
44 | /* Unlock PLL registers. */ | |
45 | clrbits_le32(&davinci_syscfg_regs->cfgchip0, 0x00000010); | |
46 | ||
47 | /* | |
48 | * Set PLLENSRC '0',bit 5, PLL Enable(PLLEN) selection is controlled | |
49 | * through MMR | |
50 | */ | |
51 | clrbits_le32(®->pllctl, 0x00000020); | |
52 | /* PLLCTL.EXTCLKSRC bit 9 should be left at 0 for Freon */ | |
53 | clrbits_le32(®->pllctl, 0x00000200); | |
54 | ||
55 | /* Set PLLEN=0 => PLL BYPASS MODE */ | |
56 | clrbits_le32(®->pllctl, 0x00000001); | |
57 | ||
effea9d1 | 58 | da850_waitloop(150); |
310ae55e HS |
59 | |
60 | if (reg == davinci_pllc0_regs) { | |
61 | /* | |
62 | * Select the Clock Mode bit 8 as External Clock or On Chip | |
63 | * Oscilator | |
64 | */ | |
65 | dv_maskbits(®->pllctl, 0xFFFFFEFF); | |
66 | setbits_le32(®->pllctl, (CONFIG_SYS_DV_CLKMODE << 8)); | |
67 | } | |
68 | ||
69 | /* Clear PLLRST bit to reset the PLL */ | |
70 | clrbits_le32(®->pllctl, 0x00000008); | |
71 | ||
72 | /* Disable the PLL output */ | |
73 | setbits_le32(®->pllctl, 0x00000010); | |
74 | ||
75 | /* PLL initialization sequence */ | |
76 | /* | |
77 | * Power up the PLL- PWRDN bit set to 0 to bring the PLL out of | |
78 | * power down bit | |
79 | */ | |
80 | clrbits_le32(®->pllctl, 0x00000002); | |
81 | ||
82 | /* Enable the PLL from Disable Mode PLLDIS bit to 0 */ | |
83 | clrbits_le32(®->pllctl, 0x00000010); | |
84 | ||
85 | /* Program the required multiplier value in PLLM */ | |
86 | writel(pllmult, ®->pllm); | |
87 | ||
88 | /* program the postdiv */ | |
89 | if (reg == davinci_pllc0_regs) | |
effea9d1 | 90 | writel((0x8000 | CONFIG_SYS_DA850_PLL0_POSTDIV), |
310ae55e HS |
91 | ®->postdiv); |
92 | else | |
effea9d1 | 93 | writel((0x8000 | CONFIG_SYS_DA850_PLL1_POSTDIV), |
310ae55e HS |
94 | ®->postdiv); |
95 | ||
96 | /* | |
97 | * Check for the GOSTAT bit in PLLSTAT to clear to 0 to indicate that | |
98 | * no GO operation is currently in progress | |
99 | */ | |
100 | while ((readl(®->pllstat) & 0x1) == 1) | |
101 | ; | |
102 | ||
103 | if (reg == davinci_pllc0_regs) { | |
effea9d1 CR |
104 | writel(CONFIG_SYS_DA850_PLL0_PLLDIV1, ®->plldiv1); |
105 | writel(CONFIG_SYS_DA850_PLL0_PLLDIV2, ®->plldiv2); | |
106 | writel(CONFIG_SYS_DA850_PLL0_PLLDIV3, ®->plldiv3); | |
107 | writel(CONFIG_SYS_DA850_PLL0_PLLDIV4, ®->plldiv4); | |
108 | writel(CONFIG_SYS_DA850_PLL0_PLLDIV5, ®->plldiv5); | |
109 | writel(CONFIG_SYS_DA850_PLL0_PLLDIV6, ®->plldiv6); | |
110 | writel(CONFIG_SYS_DA850_PLL0_PLLDIV7, ®->plldiv7); | |
310ae55e | 111 | } else { |
effea9d1 CR |
112 | writel(CONFIG_SYS_DA850_PLL1_PLLDIV1, ®->plldiv1); |
113 | writel(CONFIG_SYS_DA850_PLL1_PLLDIV2, ®->plldiv2); | |
114 | writel(CONFIG_SYS_DA850_PLL1_PLLDIV3, ®->plldiv3); | |
310ae55e HS |
115 | } |
116 | ||
117 | /* | |
118 | * Set the GOSET bit in PLLCMD to 1 to initiate a new divider | |
119 | * transition. | |
120 | */ | |
121 | setbits_le32(®->pllcmd, 0x01); | |
122 | ||
123 | /* | |
124 | * Wait for the GOSTAT bit in PLLSTAT to clear to 0 | |
125 | * (completion of phase alignment). | |
126 | */ | |
127 | while ((readl(®->pllstat) & 0x1) == 1) | |
128 | ; | |
129 | ||
130 | /* Wait for PLL to reset properly. See PLL spec for PLL reset time */ | |
effea9d1 | 131 | da850_waitloop(200); |
310ae55e HS |
132 | |
133 | /* Set the PLLRST bit in PLLCTL to 1 to bring the PLL out of reset */ | |
134 | setbits_le32(®->pllctl, 0x00000008); | |
135 | ||
136 | /* Wait for PLL to lock. See PLL spec for PLL lock time */ | |
effea9d1 | 137 | da850_waitloop(2400); |
310ae55e HS |
138 | |
139 | /* | |
140 | * Set the PLLEN bit in PLLCTL to 1 to remove the PLL from bypass | |
141 | * mode | |
142 | */ | |
143 | setbits_le32(®->pllctl, 0x00000001); | |
144 | ||
145 | ||
146 | /* | |
147 | * clear EMIFA and EMIFB clock source settings, let them | |
148 | * run off SYSCLK | |
149 | */ | |
150 | if (reg == davinci_pllc0_regs) | |
151 | dv_maskbits(&davinci_syscfg_regs->cfgchip3, 0xFFFFFFF8); | |
152 | ||
153 | return 0; | |
154 | } | |
155 | ||
effea9d1 | 156 | void da850_lpc_transition(unsigned char pscnum, unsigned char module, |
310ae55e HS |
157 | unsigned char domain, unsigned char state) |
158 | { | |
159 | struct davinci_psc_regs *reg; | |
160 | dv_reg_p mdstat, mdctl; | |
161 | ||
162 | if (pscnum == 0) { | |
163 | reg = davinci_psc0_regs; | |
164 | mdstat = ®->psc0.mdstat[module]; | |
165 | mdctl = ®->psc0.mdctl[module]; | |
166 | } else { | |
167 | reg = davinci_psc1_regs; | |
168 | mdstat = ®->psc1.mdstat[module]; | |
169 | mdctl = ®->psc1.mdctl[module]; | |
170 | } | |
171 | ||
172 | /* Wait for any outstanding transition to complete */ | |
173 | while ((readl(®->ptstat) & (0x00000001 << domain))) | |
174 | ; | |
175 | ||
176 | /* If we are already in that state, just return */ | |
177 | if ((readl(mdstat) & 0x1F) == state) | |
178 | return; | |
179 | ||
180 | /* Perform transition */ | |
181 | writel((readl(mdctl) & 0xFFFFFFE0) | state, mdctl); | |
182 | setbits_le32(®->ptcmd, (0x00000001 << domain)); | |
183 | ||
184 | /* Wait for transition to complete */ | |
185 | while (readl(®->ptstat) & (0x00000001 << domain)) | |
186 | ; | |
187 | ||
188 | /* Wait and verify the state */ | |
189 | while ((readl(mdstat) & 0x1F) != state) | |
190 | ; | |
191 | } | |
192 | ||
effea9d1 | 193 | int da850_ddr_setup(unsigned int freq) |
310ae55e HS |
194 | { |
195 | unsigned long tmp; | |
196 | ||
197 | /* Enable the Clock to DDR2/mDDR */ | |
effea9d1 | 198 | da850_lpc_transition(1, 6, 0, PSC_ENABLE); |
310ae55e HS |
199 | |
200 | tmp = readl(&davinci_syscfg1_regs->vtpio_ctl); | |
201 | if ((tmp & VTP_POWERDWN) == VTP_POWERDWN) { | |
202 | /* Begin VTP Calibration */ | |
203 | clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN); | |
204 | clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK); | |
205 | setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ); | |
206 | clrbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ); | |
207 | setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_CLKRZ); | |
208 | ||
209 | /* Polling READY bit to see when VTP calibration is done */ | |
210 | tmp = readl(&davinci_syscfg1_regs->vtpio_ctl); | |
211 | while ((tmp & VTP_READY) != VTP_READY) | |
212 | tmp = readl(&davinci_syscfg1_regs->vtpio_ctl); | |
213 | ||
214 | setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_LOCK); | |
215 | setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_POWERDWN); | |
216 | ||
217 | setbits_le32(&davinci_syscfg1_regs->vtpio_ctl, VTP_IOPWRDWN); | |
218 | } | |
219 | ||
effea9d1 | 220 | writel(CONFIG_SYS_DA850_DDR2_DDRPHYCR, &dv_ddr2_regs_ctrl->ddrphycr); |
310ae55e HS |
221 | clrbits_le32(&davinci_syscfg1_regs->ddr_slew, |
222 | (1 << DDR_SLEW_CMOSEN_BIT)); | |
223 | ||
224 | setbits_le32(&dv_ddr2_regs_ctrl->sdbcr, DV_DDR_BOOTUNLOCK); | |
225 | ||
effea9d1 | 226 | writel((CONFIG_SYS_DA850_DDR2_SDBCR & ~0xf0000000) | |
310ae55e HS |
227 | (readl(&dv_ddr2_regs_ctrl->sdbcr) & 0xf0000000), /*rsv Bytes*/ |
228 | &dv_ddr2_regs_ctrl->sdbcr); | |
effea9d1 | 229 | writel(CONFIG_SYS_DA850_DDR2_SDBCR2, &dv_ddr2_regs_ctrl->sdbcr2); |
310ae55e | 230 | |
effea9d1 CR |
231 | writel(CONFIG_SYS_DA850_DDR2_SDTIMR, &dv_ddr2_regs_ctrl->sdtimr); |
232 | writel(CONFIG_SYS_DA850_DDR2_SDTIMR2, &dv_ddr2_regs_ctrl->sdtimr2); | |
310ae55e HS |
233 | |
234 | clrbits_le32(&dv_ddr2_regs_ctrl->sdbcr, | |
235 | (1 << DV_DDR_SDCR_TIMUNLOCK_SHIFT)); | |
236 | ||
237 | /* | |
238 | * LPMODEN and MCLKSTOPEN must be set! | |
239 | * Without this bits set, PSC don;t switch states !! | |
240 | */ | |
effea9d1 | 241 | writel(CONFIG_SYS_DA850_DDR2_SDRCR | |
310ae55e HS |
242 | (1 << DV_DDR_SRCR_LPMODEN_SHIFT) | |
243 | (1 << DV_DDR_SRCR_MCLKSTOPEN_SHIFT), | |
244 | &dv_ddr2_regs_ctrl->sdrcr); | |
245 | ||
246 | /* SyncReset the Clock to EMIF3A SDRAM */ | |
effea9d1 | 247 | da850_lpc_transition(1, 6, 0, PSC_SYNCRESET); |
310ae55e | 248 | /* Enable the Clock to EMIF3A SDRAM */ |
effea9d1 | 249 | da850_lpc_transition(1, 6, 0, PSC_ENABLE); |
310ae55e HS |
250 | |
251 | /* disable self refresh */ | |
252 | clrbits_le32(&dv_ddr2_regs_ctrl->sdrcr, 0xc0000000); | |
253 | writel(0x30, &dv_ddr2_regs_ctrl->pbbpr); | |
254 | ||
255 | return 0; | |
256 | } | |
257 | ||
effea9d1 | 258 | static void da850_set_mdctl(dv_reg_p mdctl) |
310ae55e HS |
259 | { |
260 | if ((readl(mdctl) & 0x1F) != PSC_ENABLE) | |
261 | writel(((readl(mdctl) & 0xFFFFFFE0) | PSC_ENABLE), mdctl); | |
262 | } | |
263 | ||
effea9d1 | 264 | void da850_psc_init(void) |
310ae55e HS |
265 | { |
266 | struct davinci_psc_regs *reg; | |
267 | int i; | |
268 | ||
269 | /* PSC 0 domain 0 init */ | |
270 | reg = davinci_psc0_regs; | |
271 | while ((readl(®->ptstat) & 0x00000001)) | |
272 | ; | |
273 | ||
274 | for (i = 3; i <= 4 ; i++) | |
effea9d1 | 275 | da850_set_mdctl(®->psc0.mdctl[i]); |
310ae55e HS |
276 | |
277 | for (i = 7; i <= 12 ; i++) | |
effea9d1 | 278 | da850_set_mdctl(®->psc0.mdctl[i]); |
310ae55e HS |
279 | |
280 | /* Do Always-On Power Domain Transitions */ | |
281 | setbits_le32(®->ptcmd, 0x00000001); | |
282 | while (readl(®->ptstat) & 0x00000001) | |
283 | ; | |
284 | ||
285 | /* PSC1, domain 1 init */ | |
286 | reg = davinci_psc1_regs; | |
287 | while ((readl(®->ptstat) & 0x00000001)) | |
288 | ; | |
289 | ||
effea9d1 CR |
290 | da850_set_mdctl(®->psc1.mdctl[3]); |
291 | da850_set_mdctl(®->psc1.mdctl[6]); | |
310ae55e HS |
292 | |
293 | /* UART1 + UART2 */ | |
294 | for (i = 12 ; i <= 13 ; i++) | |
effea9d1 | 295 | da850_set_mdctl(®->psc1.mdctl[i]); |
310ae55e | 296 | |
effea9d1 CR |
297 | da850_set_mdctl(®->psc1.mdctl[26]); |
298 | da850_set_mdctl(®->psc1.mdctl[31]); | |
310ae55e HS |
299 | |
300 | /* Do Always-On Power Domain Transitions */ | |
301 | setbits_le32(®->ptcmd, 0x00000001); | |
302 | while (readl(®->ptstat) & 0x00000001) | |
303 | ; | |
304 | } | |
305 | ||
effea9d1 | 306 | void da850_pinmux_ctl(unsigned long offset, unsigned long mask, |
310ae55e HS |
307 | unsigned long value) |
308 | { | |
309 | clrbits_le32(&davinci_syscfg_regs->pinmux[offset], mask); | |
310 | setbits_le32(&davinci_syscfg_regs->pinmux[offset], (mask & value)); | |
311 | } | |
312 | ||
313 | __attribute__((weak)) | |
314 | void board_gpio_init(void) | |
315 | { | |
316 | return; | |
317 | } | |
318 | ||
319 | #if defined(CONFIG_NAND_SPL) | |
320 | void nand_boot(void) | |
321 | { | |
322 | __attribute__((noreturn)) void (*uboot)(void); | |
323 | ||
324 | /* copy image from NOR to RAM */ | |
325 | memcpy((void *)CONFIG_SYS_NAND_U_BOOT_DST, | |
326 | (void *)CONFIG_SYS_NAND_U_BOOT_OFFS, | |
327 | CONFIG_SYS_NAND_U_BOOT_SIZE); | |
328 | ||
329 | /* and jump to it ... */ | |
330 | uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START; | |
331 | (*uboot)(); | |
332 | } | |
333 | #endif | |
334 | ||
335 | #if defined(CONFIG_NAND_SPL) | |
336 | void board_init_f(ulong bootflag) | |
337 | #else | |
338 | int arch_cpu_init(void) | |
339 | #endif | |
340 | { | |
341 | /* | |
342 | * copied from arch/arm/cpu/arm926ejs/start.S | |
343 | * | |
344 | * flush v4 I/D caches | |
345 | */ | |
346 | asm("mov r0, #0"); | |
347 | asm("mcr p15, 0, r0, c7, c7, 0"); /* flush v3/v4 cache */ | |
348 | asm("mcr p15, 0, r0, c8, c7, 0"); /* flush v4 TLB */ | |
349 | ||
350 | /* | |
351 | * disable MMU stuff and caches | |
352 | */ | |
353 | asm("mrc p15, 0, r0, c1, c0, 0"); | |
354 | /* clear bits 13, 9:8 (--V- --RS) */ | |
355 | asm("bic r0, r0, #0x00002300"); | |
356 | /* clear bits 7, 2:0 (B--- -CAM) */ | |
357 | asm("bic r0, r0, #0x00000087"); | |
358 | /* set bit 2 (A) Align */ | |
359 | asm("orr r0, r0, #0x00000002"); | |
360 | /* set bit 12 (I) I-Cache */ | |
361 | asm("orr r0, r0, #0x00001000"); | |
362 | asm("mcr p15, 0, r0, c1, c0, 0"); | |
363 | ||
364 | /* Unlock kick registers */ | |
365 | writel(0x83e70b13, &davinci_syscfg_regs->kick0); | |
366 | writel(0x95a4f1e0, &davinci_syscfg_regs->kick1); | |
367 | ||
368 | dv_maskbits(&davinci_syscfg_regs->suspsrc, | |
369 | ((1 << 27) | (1 << 22) | (1 << 20) | (1 << 5) | (1 << 16))); | |
370 | ||
371 | /* System PSC setup - enable all */ | |
effea9d1 | 372 | da850_psc_init(); |
310ae55e HS |
373 | |
374 | /* Setup Pinmux */ | |
effea9d1 CR |
375 | da850_pinmux_ctl(0, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX0); |
376 | da850_pinmux_ctl(1, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX1); | |
377 | da850_pinmux_ctl(2, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX2); | |
378 | da850_pinmux_ctl(3, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX3); | |
379 | da850_pinmux_ctl(4, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX4); | |
380 | da850_pinmux_ctl(5, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX5); | |
381 | da850_pinmux_ctl(6, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX6); | |
382 | da850_pinmux_ctl(7, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX7); | |
383 | da850_pinmux_ctl(8, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX8); | |
384 | da850_pinmux_ctl(9, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX9); | |
385 | da850_pinmux_ctl(10, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX10); | |
386 | da850_pinmux_ctl(11, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX11); | |
387 | da850_pinmux_ctl(12, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX12); | |
388 | da850_pinmux_ctl(13, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX13); | |
389 | da850_pinmux_ctl(14, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX14); | |
390 | da850_pinmux_ctl(15, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX15); | |
391 | da850_pinmux_ctl(16, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX16); | |
392 | da850_pinmux_ctl(17, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX17); | |
393 | da850_pinmux_ctl(18, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX18); | |
394 | da850_pinmux_ctl(19, 0xFFFFFFFF, CONFIG_SYS_DA850_PINMUX19); | |
310ae55e HS |
395 | |
396 | /* PLL setup */ | |
effea9d1 CR |
397 | da850_pll_init(davinci_pllc0_regs, CONFIG_SYS_DA850_PLL0_PLLM); |
398 | da850_pll_init(davinci_pllc1_regs, CONFIG_SYS_DA850_PLL1_PLLM); | |
310ae55e HS |
399 | |
400 | /* GPIO setup */ | |
401 | board_gpio_init(); | |
402 | ||
403 | /* setup CSn config */ | |
effea9d1 CR |
404 | writel(CONFIG_SYS_DA850_CS2CFG, &davinci_emif_regs->ab1cr); |
405 | writel(CONFIG_SYS_DA850_CS3CFG, &davinci_emif_regs->ab2cr); | |
310ae55e | 406 | |
effea9d1 | 407 | da850_lpc_transition(1, 13, 0, PSC_ENABLE); |
310ae55e HS |
408 | NS16550_init((NS16550_t)(CONFIG_SYS_NS16550_COM1), |
409 | CONFIG_SYS_NS16550_CLK / 16 / CONFIG_BAUDRATE); | |
410 | ||
411 | /* | |
412 | * Fix Power and Emulation Management Register | |
413 | * see sprufw3a.pdf page 37 Table 24 | |
414 | */ | |
415 | writel(readl((CONFIG_SYS_NS16550_COM1 + 0x30)) | 0x00006001, | |
416 | (CONFIG_SYS_NS16550_COM1 + 0x30)); | |
417 | #if defined(CONFIG_NAND_SPL) | |
418 | puts("ddr init\n"); | |
effea9d1 | 419 | da850_ddr_setup(132); |
310ae55e HS |
420 | |
421 | puts("boot u-boot ...\n"); | |
422 | ||
423 | nand_boot(); | |
424 | #else | |
effea9d1 | 425 | da850_ddr_setup(132); |
310ae55e HS |
426 | return 0; |
427 | #endif | |
428 | } |