]>
Commit | Line | Data |
---|---|---|
9171fc81 MF |
1 | /* |
2 | * initcode.c - Initialize the processor. This is usually entails things | |
3 | * like external memory, voltage regulators, etc... Note that this file | |
4 | * cannot make any function calls as it may be executed all by itself by | |
5 | * the Blackfin's bootrom in LDR format. | |
6 | * | |
7 | * Copyright (c) 2004-2008 Analog Devices Inc. | |
8 | * | |
9 | * Licensed under the GPL-2 or later. | |
10 | */ | |
11 | ||
dbda2c65 MF |
12 | #define BFIN_IN_INITCODE |
13 | ||
9171fc81 MF |
14 | #include <config.h> |
15 | #include <asm/blackfin.h> | |
16 | #include <asm/mach-common/bits/bootrom.h> | |
74398b23 | 17 | #include <asm/mach-common/bits/core.h> |
9171fc81 MF |
18 | #include <asm/mach-common/bits/ebiu.h> |
19 | #include <asm/mach-common/bits/pll.h> | |
20 | #include <asm/mach-common/bits/uart.h> | |
21 | ||
9171fc81 MF |
22 | #include "serial.h" |
23 | ||
24 | __attribute__((always_inline)) | |
f790ef6f | 25 | static inline void serial_init(void) |
9171fc81 MF |
26 | { |
27 | #ifdef __ADSPBF54x__ | |
28 | # ifdef BFIN_BOOT_UART_USE_RTS | |
29 | # define BFIN_UART_USE_RTS 1 | |
30 | # else | |
31 | # define BFIN_UART_USE_RTS 0 | |
32 | # endif | |
33 | if (BFIN_UART_USE_RTS && CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { | |
34 | size_t i; | |
35 | ||
36 | /* force RTS rather than relying on auto RTS */ | |
f948158f | 37 | bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) | FCPOL); |
9171fc81 MF |
38 | |
39 | /* Wait for the line to clear up. We cannot rely on UART | |
40 | * registers as none of them reflect the status of the RSR. | |
41 | * Instead, we'll sleep for ~10 bit times at 9600 baud. | |
42 | * We can precalc things here by assuming boot values for | |
43 | * PLL rather than loading registers and calculating. | |
44 | * baud = SCLK / (16 ^ (1 - EDBO) * Divisor) | |
45 | * EDB0 = 0 | |
46 | * Divisor = (SCLK / baud) / 16 | |
47 | * SCLK = baud * 16 * Divisor | |
48 | * SCLK = (0x14 * CONFIG_CLKIN_HZ) / 5 | |
49 | * CCLK = (16 * Divisor * 5) * (9600 / 10) | |
50 | * In reality, this will probably be just about 1 second delay, | |
51 | * so assuming 9600 baud is OK (both as a very low and too high | |
52 | * speed as this will buffer things enough). | |
53 | */ | |
54 | #define _NUMBITS (10) /* how many bits to delay */ | |
55 | #define _LOWBAUD (9600) /* low baud rate */ | |
56 | #define _SCLK ((0x14 * CONFIG_CLKIN_HZ) / 5) /* SCLK based on PLL */ | |
57 | #define _DIVISOR ((_SCLK / _LOWBAUD) / 16) /* UART DLL/DLH */ | |
58 | #define _NUMINS (3) /* how many instructions in loop */ | |
59 | #define _CCLK (((16 * _DIVISOR * 5) * (_LOWBAUD / _NUMBITS)) / _NUMINS) | |
60 | i = _CCLK; | |
61 | while (i--) | |
62 | asm volatile("" : : : "memory"); | |
63 | } | |
64 | #endif | |
65 | ||
9171fc81 | 66 | if (BFIN_DEBUG_EARLY_SERIAL) { |
f948158f | 67 | int ucen = bfin_read16(&pUART->gctl) & UCEN; |
9171fc81 MF |
68 | serial_early_init(); |
69 | ||
70 | /* If the UART is off, that means we need to program | |
71 | * the baud rate ourselves initially. | |
72 | */ | |
f790ef6f | 73 | if (ucen != UCEN) |
9171fc81 | 74 | serial_early_set_baud(CONFIG_BAUDRATE); |
9171fc81 | 75 | } |
9171fc81 MF |
76 | } |
77 | ||
78 | __attribute__((always_inline)) | |
79 | static inline void serial_deinit(void) | |
80 | { | |
81 | #ifdef __ADSPBF54x__ | |
82 | if (BFIN_UART_USE_RTS && CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { | |
83 | /* clear forced RTS rather than relying on auto RTS */ | |
f948158f | 84 | bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) & ~FCPOL); |
9171fc81 MF |
85 | } |
86 | #endif | |
87 | } | |
88 | ||
9171fc81 MF |
89 | __attribute__((always_inline)) |
90 | static inline void serial_putc(char c) | |
91 | { | |
92 | if (!BFIN_DEBUG_EARLY_SERIAL) | |
93 | return; | |
94 | ||
95 | if (c == '\n') | |
af2c3737 | 96 | serial_putc('\r'); |
9171fc81 | 97 | |
f948158f | 98 | bfin_write16(&pUART->thr, c); |
9171fc81 | 99 | |
f948158f | 100 | while (!(bfin_read16(&pUART->lsr) & TEMT)) |
9171fc81 MF |
101 | continue; |
102 | } | |
103 | ||
104 | ||
97f265f1 MF |
105 | /* Max SCLK can be 133MHz ... dividing that by (2*4) gives |
106 | * us a freq of 16MHz for SPI which should generally be | |
9171fc81 MF |
107 | * slow enough for the slow reads the bootrom uses. |
108 | */ | |
97f265f1 MF |
109 | #if !defined(CONFIG_SPI_FLASH_SLOW_READ) && \ |
110 | ((defined(__ADSPBF52x__) && __SILICON_REVISION__ >= 2) || \ | |
111 | (defined(__ADSPBF54x__) && __SILICON_REVISION__ >= 1)) | |
112 | # define BOOTROM_SUPPORTS_SPI_FAST_READ 1 | |
113 | #else | |
114 | # define BOOTROM_SUPPORTS_SPI_FAST_READ 0 | |
115 | #endif | |
9171fc81 | 116 | #ifndef CONFIG_SPI_BAUD_INITBLOCK |
97f265f1 MF |
117 | # define CONFIG_SPI_BAUD_INITBLOCK (BOOTROM_SUPPORTS_SPI_FAST_READ ? 2 : 4) |
118 | #endif | |
119 | #ifdef SPI0_BAUD | |
120 | # define bfin_write_SPI_BAUD bfin_write_SPI0_BAUD | |
9171fc81 MF |
121 | #endif |
122 | ||
123 | /* PLL_DIV defines */ | |
124 | #ifndef CONFIG_PLL_DIV_VAL | |
125 | # if (CONFIG_CCLK_DIV == 1) | |
126 | # define CONFIG_CCLK_ACT_DIV CCLK_DIV1 | |
127 | # elif (CONFIG_CCLK_DIV == 2) | |
128 | # define CONFIG_CCLK_ACT_DIV CCLK_DIV2 | |
129 | # elif (CONFIG_CCLK_DIV == 4) | |
130 | # define CONFIG_CCLK_ACT_DIV CCLK_DIV4 | |
131 | # elif (CONFIG_CCLK_DIV == 8) | |
132 | # define CONFIG_CCLK_ACT_DIV CCLK_DIV8 | |
133 | # else | |
134 | # define CONFIG_CCLK_ACT_DIV CONFIG_CCLK_DIV_not_defined_properly | |
135 | # endif | |
136 | # define CONFIG_PLL_DIV_VAL (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV) | |
137 | #endif | |
138 | ||
139 | #ifndef CONFIG_PLL_LOCKCNT_VAL | |
140 | # define CONFIG_PLL_LOCKCNT_VAL 0x0300 | |
141 | #endif | |
142 | ||
143 | #ifndef CONFIG_PLL_CTL_VAL | |
4f6a3132 | 144 | # define CONFIG_PLL_CTL_VAL (SPORT_HYST | (CONFIG_VCO_MULT << 9) | CONFIG_CLKIN_HALF) |
9171fc81 MF |
145 | #endif |
146 | ||
147 | #ifndef CONFIG_EBIU_RSTCTL_VAL | |
148 | # define CONFIG_EBIU_RSTCTL_VAL 0 /* only MDDRENABLE is useful */ | |
149 | #endif | |
67619982 MF |
150 | #if ((CONFIG_EBIU_RSTCTL_VAL & 0xFFFFFFC4) != 0) |
151 | # error invalid EBIU_RSTCTL value: must not set reserved bits | |
152 | #endif | |
9171fc81 MF |
153 | |
154 | #ifndef CONFIG_EBIU_MBSCTL_VAL | |
155 | # define CONFIG_EBIU_MBSCTL_VAL 0 | |
156 | #endif | |
157 | ||
67619982 MF |
158 | #if defined(CONFIG_EBIU_DDRQUE_VAL) && ((CONFIG_EBIU_DDRQUE_VAL & 0xFFFF8000) != 0) |
159 | # error invalid EBIU_DDRQUE value: must not set reserved bits | |
160 | #endif | |
161 | ||
9171fc81 MF |
162 | /* Make sure our voltage value is sane so we don't blow up! */ |
163 | #ifndef CONFIG_VR_CTL_VAL | |
164 | # define BFIN_CCLK ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_CCLK_DIV) | |
165 | # if defined(__ADSPBF533__) || defined(__ADSPBF532__) || defined(__ADSPBF531__) | |
166 | # define CCLK_VLEV_120 400000000 | |
167 | # define CCLK_VLEV_125 533000000 | |
168 | # elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) | |
169 | # define CCLK_VLEV_120 401000000 | |
170 | # define CCLK_VLEV_125 401000000 | |
171 | # elif defined(__ADSPBF561__) | |
172 | # define CCLK_VLEV_120 300000000 | |
173 | # define CCLK_VLEV_125 501000000 | |
174 | # endif | |
175 | # if BFIN_CCLK < CCLK_VLEV_120 | |
176 | # define CONFIG_VR_CTL_VLEV VLEV_120 | |
177 | # elif BFIN_CCLK < CCLK_VLEV_125 | |
178 | # define CONFIG_VR_CTL_VLEV VLEV_125 | |
179 | # else | |
180 | # define CONFIG_VR_CTL_VLEV VLEV_130 | |
181 | # endif | |
182 | # if defined(__ADSPBF52x__) /* TBD; use default */ | |
183 | # undef CONFIG_VR_CTL_VLEV | |
184 | # define CONFIG_VR_CTL_VLEV VLEV_110 | |
185 | # elif defined(__ADSPBF54x__) /* TBD; use default */ | |
186 | # undef CONFIG_VR_CTL_VLEV | |
187 | # define CONFIG_VR_CTL_VLEV VLEV_120 | |
622a8dc0 MF |
188 | # elif defined(__ADSPBF538__) || defined(__ADSPBF539__) /* TBD; use default */ |
189 | # undef CONFIG_VR_CTL_VLEV | |
190 | # define CONFIG_VR_CTL_VLEV VLEV_125 | |
9171fc81 MF |
191 | # endif |
192 | ||
193 | # ifdef CONFIG_BFIN_MAC | |
194 | # define CONFIG_VR_CTL_CLKBUF CLKBUFOE | |
195 | # else | |
196 | # define CONFIG_VR_CTL_CLKBUF 0 | |
197 | # endif | |
198 | ||
199 | # if defined(__ADSPBF52x__) | |
200 | # define CONFIG_VR_CTL_FREQ FREQ_1000 | |
201 | # else | |
202 | # define CONFIG_VR_CTL_FREQ (GAIN_20 | FREQ_1000) | |
203 | # endif | |
204 | ||
205 | # define CONFIG_VR_CTL_VAL (CONFIG_VR_CTL_CLKBUF | CONFIG_VR_CTL_VLEV | CONFIG_VR_CTL_FREQ) | |
206 | #endif | |
207 | ||
d347d572 MF |
208 | /* some parts do not have an on-chip voltage regulator */ |
209 | #if defined(__ADSPBF51x__) | |
210 | # define CONFIG_HAS_VR 0 | |
211 | # undef CONFIG_VR_CTL_VAL | |
212 | # define CONFIG_VR_CTL_VAL 0 | |
213 | #else | |
214 | # define CONFIG_HAS_VR 1 | |
215 | #endif | |
216 | ||
dbda2c65 | 217 | #if CONFIG_MEM_SIZE |
0d4f24b7 MF |
218 | #ifndef EBIU_RSTCTL |
219 | /* Blackfin with SDRAM */ | |
220 | #ifndef CONFIG_EBIU_SDBCTL_VAL | |
221 | # if CONFIG_MEM_SIZE == 16 | |
222 | # define CONFIG_EBSZ_VAL EBSZ_16 | |
223 | # elif CONFIG_MEM_SIZE == 32 | |
224 | # define CONFIG_EBSZ_VAL EBSZ_32 | |
225 | # elif CONFIG_MEM_SIZE == 64 | |
226 | # define CONFIG_EBSZ_VAL EBSZ_64 | |
227 | # elif CONFIG_MEM_SIZE == 128 | |
228 | # define CONFIG_EBSZ_VAL EBSZ_128 | |
229 | # elif CONFIG_MEM_SIZE == 256 | |
230 | # define CONFIG_EBSZ_VAL EBSZ_256 | |
231 | # elif CONFIG_MEM_SIZE == 512 | |
232 | # define CONFIG_EBSZ_VAL EBSZ_512 | |
233 | # else | |
234 | # error You need to define CONFIG_EBIU_SDBCTL_VAL or CONFIG_MEM_SIZE | |
235 | # endif | |
236 | # if CONFIG_MEM_ADD_WDTH == 8 | |
237 | # define CONFIG_EBCAW_VAL EBCAW_8 | |
238 | # elif CONFIG_MEM_ADD_WDTH == 9 | |
239 | # define CONFIG_EBCAW_VAL EBCAW_9 | |
240 | # elif CONFIG_MEM_ADD_WDTH == 10 | |
241 | # define CONFIG_EBCAW_VAL EBCAW_10 | |
242 | # elif CONFIG_MEM_ADD_WDTH == 11 | |
243 | # define CONFIG_EBCAW_VAL EBCAW_11 | |
244 | # else | |
245 | # error You need to define CONFIG_EBIU_SDBCTL_VAL or CONFIG_MEM_ADD_WDTH | |
246 | # endif | |
247 | # define CONFIG_EBIU_SDBCTL_VAL (CONFIG_EBCAW_VAL | CONFIG_EBSZ_VAL | EBE) | |
248 | #endif | |
249 | #endif | |
dbda2c65 | 250 | #endif |
0d4f24b7 | 251 | |
8ef929af MF |
252 | /* Conflicting Column Address Widths Causes SDRAM Errors: |
253 | * EB2CAW and EB3CAW must be the same | |
254 | */ | |
255 | #if ANOMALY_05000362 | |
256 | # if ((CONFIG_EBIU_SDBCTL_VAL & 0x30000000) >> 8) != (CONFIG_EBIU_SDBCTL_VAL & 0x00300000) | |
257 | # error "Anomaly 05000362: EB2CAW and EB3CAW must be the same" | |
258 | # endif | |
259 | #endif | |
260 | ||
dbda2c65 MF |
261 | __attribute__((always_inline)) static inline void |
262 | program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB) | |
9171fc81 | 263 | { |
dbda2c65 | 264 | serial_putc('a'); |
ad907321 | 265 | |
f790ef6f | 266 | /* Save the clock pieces that are used in baud rate calculation */ |
f790ef6f | 267 | if (BFIN_DEBUG_EARLY_SERIAL || CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { |
dbda2c65 MF |
268 | serial_putc('b'); |
269 | *sdivB = bfin_read_PLL_DIV() & 0xf; | |
270 | *vcoB = (bfin_read_PLL_CTL() >> 9) & 0x3f; | |
271 | *divB = serial_early_get_div(); | |
272 | serial_putc('c'); | |
f790ef6f | 273 | } |
9171fc81 | 274 | |
dbda2c65 | 275 | serial_putc('d'); |
ad907321 | 276 | |
9171fc81 MF |
277 | #ifdef CONFIG_HW_WATCHDOG |
278 | # ifndef CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE | |
279 | # define CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE 20000 | |
280 | # endif | |
281 | /* Program the watchdog with an initial timeout of ~20 seconds. | |
282 | * Hopefully that should be long enough to load the u-boot LDR | |
283 | * (from wherever) and then the common u-boot code can take over. | |
284 | * In bypass mode, the start.S would have already set a much lower | |
285 | * timeout, so don't clobber that. | |
286 | */ | |
287 | if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) { | |
dbda2c65 | 288 | serial_putc('e'); |
9171fc81 MF |
289 | bfin_write_WDOG_CNT(MSEC_TO_SCLK(CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE)); |
290 | bfin_write_WDOG_CTL(0); | |
dbda2c65 | 291 | serial_putc('f'); |
9171fc81 MF |
292 | } |
293 | #endif | |
294 | ||
dbda2c65 MF |
295 | serial_putc('g'); |
296 | ||
297 | /* Blackfin bootroms use the SPI slow read opcode instead of the SPI | |
298 | * fast read, so we need to slow down the SPI clock a lot more during | |
299 | * boot. Once we switch over to u-boot's SPI flash driver, we'll | |
300 | * increase the speed appropriately. | |
301 | */ | |
302 | if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) { | |
303 | serial_putc('h'); | |
304 | if (BOOTROM_SUPPORTS_SPI_FAST_READ && CONFIG_SPI_BAUD_INITBLOCK < 4) | |
305 | bs->dFlags |= BFLAG_FASTREAD; | |
306 | bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK); | |
307 | serial_putc('i'); | |
308 | } | |
309 | ||
310 | serial_putc('j'); | |
311 | } | |
312 | ||
313 | __attribute__((always_inline)) static inline bool | |
314 | maybe_self_refresh(ADI_BOOT_DATA *bs) | |
315 | { | |
316 | serial_putc('a'); | |
317 | ||
318 | if (!CONFIG_MEM_SIZE) | |
319 | return false; | |
74398b23 MF |
320 | |
321 | /* If external memory is enabled, put it into self refresh first. */ | |
74398b23 MF |
322 | #ifdef EBIU_RSTCTL |
323 | if (bfin_read_EBIU_RSTCTL() & DDR_SRESET) { | |
dbda2c65 | 324 | serial_putc('b'); |
74398b23 | 325 | bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | SRREQ); |
dbda2c65 | 326 | return true; |
74398b23 MF |
327 | } |
328 | #else | |
329 | if (bfin_read_EBIU_SDBCTL() & EBE) { | |
dbda2c65 | 330 | serial_putc('b'); |
74398b23 | 331 | bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS); |
dbda2c65 | 332 | return true; |
74398b23 MF |
333 | } |
334 | #endif | |
335 | ||
dbda2c65 | 336 | serial_putc('c'); |
9171fc81 | 337 | |
dbda2c65 MF |
338 | return false; |
339 | } | |
9171fc81 | 340 | |
dbda2c65 MF |
341 | __attribute__((always_inline)) static inline u16 |
342 | program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs) | |
343 | { | |
344 | u16 vr_ctl; | |
345 | ||
346 | serial_putc('a'); | |
347 | ||
348 | vr_ctl = bfin_read_VR_CTL(); | |
349 | ||
350 | serial_putc('b'); | |
9171fc81 | 351 | |
74398b23 MF |
352 | /* If we're entering self refresh, make sure it has happened. */ |
353 | if (put_into_srfs) | |
354 | #ifdef EBIU_RSTCTL | |
355 | while (!(bfin_read_EBIU_RSTCTL() & SRACK)) | |
9171fc81 | 356 | #else |
74398b23 | 357 | while (!(bfin_read_EBIU_SDSTAT() & SDSRA)) |
9171fc81 | 358 | #endif |
74398b23 MF |
359 | continue; |
360 | ||
dbda2c65 | 361 | serial_putc('c'); |
9171fc81 | 362 | |
09dc6b0b MF |
363 | /* With newer bootroms, we use the helper function to set up |
364 | * the memory controller. Older bootroms lacks such helpers | |
365 | * so we do it ourselves. | |
366 | */ | |
74398b23 | 367 | if (!ANOMALY_05000386) { |
dbda2c65 | 368 | serial_putc('d'); |
9171fc81 | 369 | |
c2e07449 | 370 | /* Always programming PLL_LOCKCNT avoids Anomaly 05000430 */ |
09dc6b0b | 371 | ADI_SYSCTRL_VALUES memory_settings; |
d347d572 MF |
372 | uint32_t actions = SYSCTRL_WRITE | SYSCTRL_PLLCTL | SYSCTRL_PLLDIV | SYSCTRL_LOCKCNT; |
373 | if (CONFIG_HAS_VR) { | |
374 | actions |= SYSCTRL_VRCTL; | |
375 | if (CONFIG_VR_CTL_VAL & FREQ_MASK) | |
376 | actions |= SYSCTRL_INTVOLTAGE; | |
377 | else | |
378 | actions |= SYSCTRL_EXTVOLTAGE; | |
379 | memory_settings.uwVrCtl = CONFIG_VR_CTL_VAL; | |
380 | } else | |
381 | actions |= SYSCTRL_EXTVOLTAGE; | |
09dc6b0b MF |
382 | memory_settings.uwPllCtl = CONFIG_PLL_CTL_VAL; |
383 | memory_settings.uwPllDiv = CONFIG_PLL_DIV_VAL; | |
384 | memory_settings.uwPllLockCnt = CONFIG_PLL_LOCKCNT_VAL; | |
3986e981 MF |
385 | #if ANOMALY_05000432 |
386 | bfin_write_SIC_IWR1(0); | |
387 | #endif | |
dbda2c65 | 388 | serial_putc('e'); |
d347d572 | 389 | bfrom_SysControl(actions, &memory_settings, NULL); |
dbda2c65 | 390 | serial_putc('f'); |
3986e981 MF |
391 | #if ANOMALY_05000432 |
392 | bfin_write_SIC_IWR1(-1); | |
ce1fe4ba MF |
393 | #endif |
394 | #if ANOMALY_05000171 | |
395 | bfin_write_SICA_IWR0(-1); | |
396 | bfin_write_SICA_IWR1(-1); | |
3986e981 | 397 | #endif |
dbda2c65 | 398 | serial_putc('g'); |
09dc6b0b | 399 | } else { |
dbda2c65 | 400 | serial_putc('h'); |
74398b23 MF |
401 | |
402 | /* Disable all peripheral wakeups except for the PLL event. */ | |
403 | #ifdef SIC_IWR0 | |
404 | bfin_write_SIC_IWR0(1); | |
405 | bfin_write_SIC_IWR1(0); | |
406 | # ifdef SIC_IWR2 | |
407 | bfin_write_SIC_IWR2(0); | |
408 | # endif | |
409 | #elif defined(SICA_IWR0) | |
410 | bfin_write_SICA_IWR0(1); | |
411 | bfin_write_SICA_IWR1(0); | |
412 | #else | |
413 | bfin_write_SIC_IWR(1); | |
414 | #endif | |
415 | ||
dbda2c65 | 416 | serial_putc('i'); |
9171fc81 | 417 | |
c2e07449 | 418 | /* Always programming PLL_LOCKCNT avoids Anomaly 05000430 */ |
09dc6b0b | 419 | bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL); |
9171fc81 | 420 | |
dbda2c65 | 421 | serial_putc('j'); |
9171fc81 | 422 | |
09dc6b0b MF |
423 | /* Only reprogram when needed to avoid triggering unnecessary |
424 | * PLL relock sequences. | |
425 | */ | |
74398b23 | 426 | if (vr_ctl != CONFIG_VR_CTL_VAL) { |
dbda2c65 | 427 | serial_putc('?'); |
09dc6b0b MF |
428 | bfin_write_VR_CTL(CONFIG_VR_CTL_VAL); |
429 | asm("idle;"); | |
dbda2c65 | 430 | serial_putc('!'); |
09dc6b0b | 431 | } |
9171fc81 | 432 | |
dbda2c65 | 433 | serial_putc('k'); |
9171fc81 | 434 | |
09dc6b0b | 435 | bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL); |
9171fc81 | 436 | |
dbda2c65 | 437 | serial_putc('l'); |
09dc6b0b MF |
438 | |
439 | /* Only reprogram when needed to avoid triggering unnecessary | |
440 | * PLL relock sequences. | |
441 | */ | |
48ab1509 | 442 | if (ANOMALY_05000242 || bfin_read_PLL_CTL() != CONFIG_PLL_CTL_VAL) { |
dbda2c65 | 443 | serial_putc('?'); |
09dc6b0b MF |
444 | bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL); |
445 | asm("idle;"); | |
dbda2c65 | 446 | serial_putc('!'); |
09dc6b0b | 447 | } |
74398b23 | 448 | |
dbda2c65 | 449 | serial_putc('m'); |
74398b23 MF |
450 | |
451 | /* Restore all peripheral wakeups. */ | |
452 | #ifdef SIC_IWR0 | |
453 | bfin_write_SIC_IWR0(-1); | |
454 | bfin_write_SIC_IWR1(-1); | |
455 | # ifdef SIC_IWR2 | |
456 | bfin_write_SIC_IWR2(-1); | |
457 | # endif | |
458 | #elif defined(SICA_IWR0) | |
459 | bfin_write_SICA_IWR0(-1); | |
460 | bfin_write_SICA_IWR1(-1); | |
461 | #else | |
462 | bfin_write_SIC_IWR(-1); | |
463 | #endif | |
dbda2c65 MF |
464 | |
465 | serial_putc('n'); | |
9171fc81 MF |
466 | } |
467 | ||
dbda2c65 MF |
468 | serial_putc('o'); |
469 | ||
470 | return vr_ctl; | |
471 | } | |
472 | ||
473 | __attribute__((always_inline)) static inline void | |
474 | update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB) | |
475 | { | |
476 | serial_putc('a'); | |
74398b23 | 477 | |
9171fc81 MF |
478 | /* Since we've changed the SCLK above, we may need to update |
479 | * the UART divisors (UART baud rates are based on SCLK). | |
f790ef6f MF |
480 | * Do the division by hand as there are no native instructions |
481 | * for dividing which means we'd generate a libgcc reference. | |
9171fc81 | 482 | */ |
f790ef6f | 483 | if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { |
dbda2c65 | 484 | serial_putc('b'); |
f790ef6f MF |
485 | unsigned int sdivR, vcoR; |
486 | sdivR = bfin_read_PLL_DIV() & 0xf; | |
487 | vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f; | |
488 | int dividend = sdivB * divB * vcoR; | |
489 | int divisor = vcoB * sdivR; | |
490 | unsigned int quotient; | |
491 | for (quotient = 0; dividend > 0; ++quotient) | |
492 | dividend -= divisor; | |
493 | serial_early_put_div(quotient - ANOMALY_05000230); | |
dbda2c65 | 494 | serial_putc('c'); |
f790ef6f | 495 | } |
9171fc81 | 496 | |
dbda2c65 MF |
497 | serial_putc('d'); |
498 | } | |
499 | ||
500 | __attribute__((always_inline)) static inline void | |
501 | program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs) | |
502 | { | |
503 | serial_putc('a'); | |
504 | ||
505 | if (!CONFIG_MEM_SIZE) | |
506 | return; | |
507 | ||
508 | serial_putc('b'); | |
9171fc81 | 509 | |
74398b23 MF |
510 | /* Program the external memory controller before we come out of |
511 | * self-refresh. This only works with our SDRAM controller. | |
512 | */ | |
513 | #ifndef EBIU_RSTCTL | |
dbda2c65 | 514 | # ifdef CONFIG_EBIU_SDRRC_VAL |
74398b23 | 515 | bfin_write_EBIU_SDRRC(CONFIG_EBIU_SDRRC_VAL); |
dbda2c65 MF |
516 | # endif |
517 | # ifdef CONFIG_EBIU_SDBCTL_VAL | |
74398b23 | 518 | bfin_write_EBIU_SDBCTL(CONFIG_EBIU_SDBCTL_VAL); |
dbda2c65 MF |
519 | # endif |
520 | # ifdef CONFIG_EBIU_SDGCTL_VAL | |
74398b23 | 521 | bfin_write_EBIU_SDGCTL(CONFIG_EBIU_SDGCTL_VAL); |
dbda2c65 | 522 | # endif |
74398b23 | 523 | #endif |
9171fc81 | 524 | |
dbda2c65 | 525 | serial_putc('c'); |
74398b23 MF |
526 | |
527 | /* Now that we've reprogrammed, take things out of self refresh. */ | |
528 | if (put_into_srfs) | |
529 | #ifdef EBIU_RSTCTL | |
530 | bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ)); | |
531 | #else | |
532 | bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() & ~(SRFS)); | |
9171fc81 MF |
533 | #endif |
534 | ||
dbda2c65 | 535 | serial_putc('d'); |
9171fc81 | 536 | |
74398b23 MF |
537 | /* Our DDR controller sucks and cannot be programmed while in |
538 | * self-refresh. So we have to pull it out before programming. | |
539 | */ | |
9171fc81 | 540 | #ifdef EBIU_RSTCTL |
7527feef | 541 | # ifdef CONFIG_EBIU_RSTCTL_VAL |
9171fc81 | 542 | bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | 0x1 /*DDRSRESET*/ | CONFIG_EBIU_RSTCTL_VAL); |
7527feef MF |
543 | # endif |
544 | # ifdef CONFIG_EBIU_DDRCTL0_VAL | |
9171fc81 | 545 | bfin_write_EBIU_DDRCTL0(CONFIG_EBIU_DDRCTL0_VAL); |
7527feef MF |
546 | # endif |
547 | # ifdef CONFIG_EBIU_DDRCTL1_VAL | |
9171fc81 | 548 | bfin_write_EBIU_DDRCTL1(CONFIG_EBIU_DDRCTL1_VAL); |
7527feef MF |
549 | # endif |
550 | # ifdef CONFIG_EBIU_DDRCTL2_VAL | |
9171fc81 | 551 | bfin_write_EBIU_DDRCTL2(CONFIG_EBIU_DDRCTL2_VAL); |
7527feef | 552 | # endif |
9171fc81 MF |
553 | # ifdef CONFIG_EBIU_DDRCTL3_VAL |
554 | /* default is disable, so don't need to force this */ | |
555 | bfin_write_EBIU_DDRCTL3(CONFIG_EBIU_DDRCTL3_VAL); | |
556 | # endif | |
74398b23 MF |
557 | # ifdef CONFIG_EBIU_DDRQUE_VAL |
558 | bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE() | CONFIG_EBIU_DDRQUE_VAL); | |
559 | # endif | |
9171fc81 MF |
560 | #endif |
561 | ||
dbda2c65 MF |
562 | serial_putc('e'); |
563 | } | |
564 | ||
565 | __attribute__((always_inline)) static inline void | |
566 | check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs) | |
567 | { | |
568 | serial_putc('a'); | |
569 | ||
570 | if (!CONFIG_MEM_SIZE) | |
571 | return; | |
572 | ||
573 | serial_putc('b'); | |
9171fc81 | 574 | |
74398b23 MF |
575 | /* Are we coming out of hibernate (suspend to memory) ? |
576 | * The memory layout is: | |
577 | * 0x0: hibernate magic for anomaly 307 (0xDEADBEEF) | |
578 | * 0x4: return address | |
579 | * 0x8: stack pointer | |
580 | * | |
581 | * SCKELOW is unreliable on older parts (anomaly 307) | |
582 | */ | |
583 | if (ANOMALY_05000307 || vr_ctl & 0x8000) { | |
584 | uint32_t *hibernate_magic = 0; | |
585 | __builtin_bfin_ssync(); /* make sure memory controller is done */ | |
586 | if (hibernate_magic[0] == 0xDEADBEEF) { | |
dbda2c65 | 587 | serial_putc('c'); |
74398b23 MF |
588 | bfin_write_EVT15(hibernate_magic[1]); |
589 | bfin_write_IMASK(EVT_IVG15); | |
590 | __asm__ __volatile__ ( | |
591 | /* load reti early to avoid anomaly 281 */ | |
592 | "reti = %0;" | |
593 | /* clear hibernate magic */ | |
594 | "[%0] = %1;" | |
595 | /* load stack pointer */ | |
596 | "SP = [%0 + 8];" | |
597 | /* lower ourselves from reset ivg to ivg15 */ | |
598 | "raise 15;" | |
599 | "rti;" | |
600 | : | |
601 | : "p"(hibernate_magic), "d"(0x2000 /* jump.s 0 */) | |
602 | ); | |
603 | } | |
dbda2c65 | 604 | serial_putc('d'); |
74398b23 MF |
605 | } |
606 | ||
dbda2c65 MF |
607 | serial_putc('e'); |
608 | } | |
609 | ||
610 | __attribute__((always_inline)) static inline void | |
611 | program_async_controller(ADI_BOOT_DATA *bs) | |
612 | { | |
613 | serial_putc('a'); | |
74398b23 MF |
614 | |
615 | /* Program the async banks controller. */ | |
616 | bfin_write_EBIU_AMBCTL0(CONFIG_EBIU_AMBCTL0_VAL); | |
617 | bfin_write_EBIU_AMBCTL1(CONFIG_EBIU_AMBCTL1_VAL); | |
618 | bfin_write_EBIU_AMGCTL(CONFIG_EBIU_AMGCTL_VAL); | |
619 | ||
dbda2c65 MF |
620 | serial_putc('b'); |
621 | ||
74398b23 | 622 | /* Not all parts have these additional MMRs. */ |
7527feef MF |
623 | #ifdef EBIU_MODE |
624 | # ifdef CONFIG_EBIU_MBSCTL_VAL | |
74398b23 | 625 | bfin_write_EBIU_MBSCTL(CONFIG_EBIU_MBSCTL_VAL); |
7527feef MF |
626 | # endif |
627 | # ifdef CONFIG_EBIU_MODE_VAL | |
74398b23 | 628 | bfin_write_EBIU_MODE(CONFIG_EBIU_MODE_VAL); |
7527feef MF |
629 | # endif |
630 | # ifdef CONFIG_EBIU_FCTL_VAL | |
74398b23 | 631 | bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTL_VAL); |
7527feef | 632 | # endif |
9171fc81 MF |
633 | #endif |
634 | ||
dbda2c65 MF |
635 | serial_putc('c'); |
636 | } | |
637 | ||
638 | BOOTROM_CALLED_FUNC_ATTR | |
639 | void initcode(ADI_BOOT_DATA *bs) | |
640 | { | |
641 | ADI_BOOT_DATA bootstruct_scratch; | |
642 | ||
643 | serial_init(); | |
644 | ||
645 | serial_putc('A'); | |
646 | ||
647 | /* If the bootstruct is NULL, then it's because we're loading | |
648 | * dynamically and not via LDR (bootrom). So set the struct to | |
649 | * some scratch space. | |
650 | */ | |
651 | if (!bs) | |
652 | bs = &bootstruct_scratch; | |
653 | ||
654 | serial_putc('B'); | |
655 | bool put_into_srfs = maybe_self_refresh(bs); | |
656 | ||
657 | serial_putc('C'); | |
658 | uint sdivB, divB, vcoB; | |
659 | program_early_devices(bs, &sdivB, &divB, &vcoB); | |
660 | ||
661 | serial_putc('D'); | |
662 | u16 vr_ctl = program_clocks(bs, put_into_srfs); | |
663 | ||
664 | serial_putc('E'); | |
665 | update_serial_clocks(bs, sdivB, divB, vcoB); | |
666 | ||
667 | serial_putc('F'); | |
668 | program_memory_controller(bs, put_into_srfs); | |
669 | ||
670 | serial_putc('G'); | |
671 | check_hibernation(bs, vr_ctl, put_into_srfs); | |
672 | ||
673 | serial_putc('H'); | |
674 | program_async_controller(bs); | |
74398b23 | 675 | |
02778f2f | 676 | #ifdef CONFIG_BFIN_BOOTROM_USES_EVT1 |
dbda2c65 | 677 | serial_putc('I'); |
7e1d212b MF |
678 | /* tell the bootrom where our entry point is */ |
679 | if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) | |
680 | bfin_write_EVT1(CONFIG_SYS_MONITOR_BASE); | |
02778f2f | 681 | #endif |
7e1d212b | 682 | |
9171fc81 MF |
683 | serial_putc('>'); |
684 | serial_putc('\n'); | |
685 | ||
686 | serial_deinit(); | |
687 | } |