]>
Commit | Line | Data |
---|---|---|
f8cac651 | 1 | /* |
7c803be2 | 2 | * (C) Copyright 2000-2008 |
f8cac651 WD |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
f8cac651 WD |
6 | */ |
7 | ||
8 | #include <common.h> | |
6ed3b9d4 | 9 | #include <hwconfig.h> |
f8cac651 | 10 | #include <mpc8xx.h> |
1c43771b WD |
11 | #ifdef CONFIG_PS2MULT |
12 | #include <ps2mult.h> | |
13 | #endif | |
f8cac651 | 14 | |
6ed3b9d4 HS |
15 | #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) |
16 | #include <libfdt.h> | |
17 | #endif | |
18 | ||
7c803be2 WD |
19 | extern flash_info_t flash_info[]; /* FLASH chips info */ |
20 | ||
d87080b7 | 21 | DECLARE_GLOBAL_DATA_PTR; |
f8cac651 WD |
22 | |
23 | static long int dram_size (long int, long int *, long int); | |
24 | ||
f8cac651 WD |
25 | #define _NOT_USED_ 0xFFFFFFFF |
26 | ||
22d1a56c | 27 | /* UPM initialization table for SDRAM: 40, 50, 66 MHz CLKOUT @ CAS latency 2, tWR=2 */ |
f8cac651 WD |
28 | const uint sdram_table[] = |
29 | { | |
30 | /* | |
31 | * Single Read. (Offset 0 in UPMA RAM) | |
32 | */ | |
33 | 0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBAFC00, | |
34 | 0x1FF5FC47, /* last */ | |
35 | /* | |
36 | * SDRAM Initialization (offset 5 in UPMA RAM) | |
37 | * | |
38 | * This is no UPM entry point. The following definition uses | |
39 | * the remaining space to establish an initialization | |
40 | * sequence, which is executed by a RUN command. | |
41 | * | |
42 | */ | |
43 | 0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */ | |
44 | /* | |
45 | * Burst Read. (Offset 8 in UPMA RAM) | |
46 | */ | |
47 | 0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00, | |
48 | 0xF0AFFC00, 0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */ | |
49 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
50 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
51 | /* | |
52 | * Single Write. (Offset 18 in UPMA RAM) | |
53 | */ | |
22d1a56c JG |
54 | 0x1F0DFC04, 0xEEABBC00, 0x11B77C04, 0xEFFAFC44, |
55 | 0x1FF5FC47, /* last */ | |
56 | _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
f8cac651 WD |
57 | /* |
58 | * Burst Write. (Offset 20 in UPMA RAM) | |
59 | */ | |
60 | 0x1F0DFC04, 0xEEABBC00, 0x10A77C00, 0xF0AFFC00, | |
22d1a56c | 61 | 0xF0AFFC00, 0xF0AFFC04, 0xE1BAFC44, 0x1FF5FC47, /* last */ |
f8cac651 WD |
62 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, |
63 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
64 | /* | |
65 | * Refresh (Offset 30 in UPMA RAM) | |
66 | */ | |
67 | 0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, | |
68 | 0xFFFFFC84, 0xFFFFFC07, /* last */ | |
69 | _NOT_USED_, _NOT_USED_, | |
70 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
71 | /* | |
72 | * Exception. (Offset 3c in UPMA RAM) | |
73 | */ | |
22d1a56c | 74 | 0xFFFFFC07, /* last */ |
f8cac651 WD |
75 | _NOT_USED_, _NOT_USED_, _NOT_USED_, |
76 | }; | |
77 | ||
78 | /* ------------------------------------------------------------------------- */ | |
79 | ||
80 | ||
81 | /* | |
82 | * Check Board Identity: | |
83 | * | |
84 | * Test TQ ID string (TQM8xx...) | |
85 | * If present, check for "L" type (no second DRAM bank), | |
86 | * otherwise "L" type is assumed as default. | |
87 | * | |
d4ca31c4 | 88 | * Set board_type to 'L' for "L" type, 'M' for "M" type, 0 else. |
f8cac651 WD |
89 | */ |
90 | ||
91 | int checkboard (void) | |
92 | { | |
f0c0b3a9 WD |
93 | char buf[64]; |
94 | int i; | |
95 | int l = getenv_f("serial#", buf, sizeof(buf)); | |
f8cac651 WD |
96 | |
97 | puts ("Board: "); | |
98 | ||
f0c0b3a9 | 99 | if (l < 0 || strncmp(buf, "TQM8", 4)) { |
f8cac651 WD |
100 | puts ("### No HW ID - assuming TQM8xxL\n"); |
101 | return (0); | |
102 | } | |
103 | ||
f0c0b3a9 | 104 | if ((buf[6] == 'L')) { /* a TQM8xxL type */ |
f8cac651 WD |
105 | gd->board_type = 'L'; |
106 | } | |
107 | ||
f0c0b3a9 | 108 | if ((buf[6] == 'M')) { /* a TQM8xxM type */ |
d4ca31c4 WD |
109 | gd->board_type = 'M'; |
110 | } | |
111 | ||
f0c0b3a9 | 112 | if ((buf[6] == 'D')) { /* a TQM885D type */ |
090eb735 MK |
113 | gd->board_type = 'D'; |
114 | } | |
115 | ||
f0c0b3a9 WD |
116 | for (i = 0; i < l; ++i) { |
117 | if (buf[i] == ' ') | |
f8cac651 | 118 | break; |
f0c0b3a9 | 119 | putc (buf[i]); |
f8cac651 | 120 | } |
8cba090c WD |
121 | #ifdef CONFIG_VIRTLAB2 |
122 | puts (" (Virtlab2)"); | |
123 | #endif | |
f8cac651 WD |
124 | putc ('\n'); |
125 | ||
126 | return (0); | |
127 | } | |
128 | ||
129 | /* ------------------------------------------------------------------------- */ | |
130 | ||
9973e3c6 | 131 | phys_size_t initdram (int board_type) |
f8cac651 | 132 | { |
6d0f6bcf | 133 | volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; |
f8cac651 | 134 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
c178d3da | 135 | long int size8, size9, size10; |
f8cac651 WD |
136 | long int size_b0 = 0; |
137 | long int size_b1 = 0; | |
138 | ||
139 | upmconfig (UPMA, (uint *) sdram_table, | |
140 | sizeof (sdram_table) / sizeof (uint)); | |
141 | ||
142 | /* | |
143 | * Preliminary prescaler for refresh (depends on number of | |
144 | * banks): This value is selected for four cycles every 62.4 us | |
145 | * with two SDRAM banks or four cycles every 31.2 us with one | |
146 | * bank. It will be adjusted after memory sizing. | |
147 | */ | |
6d0f6bcf | 148 | memctl->memc_mptpr = CONFIG_SYS_MPTPR_2BK_8K; |
f8cac651 WD |
149 | |
150 | /* | |
151 | * The following value is used as an address (i.e. opcode) for | |
152 | * the LOAD MODE REGISTER COMMAND during SDRAM initialisation. If | |
153 | * the port size is 32bit the SDRAM does NOT "see" the lower two | |
154 | * address lines, i.e. mar=0x00000088 -> opcode=0x00000022 for | |
155 | * MICRON SDRAMs: | |
156 | * -> 0 00 010 0 010 | |
157 | * | | | | +- Burst Length = 4 | |
158 | * | | | +----- Burst Type = Sequential | |
159 | * | | +------- CAS Latency = 2 | |
160 | * | +----------- Operating Mode = Standard | |
161 | * +-------------- Write Burst Mode = Programmed Burst Length | |
162 | */ | |
163 | memctl->memc_mar = 0x00000088; | |
164 | ||
165 | /* | |
166 | * Map controller banks 2 and 3 to the SDRAM banks 2 and 3 at | |
167 | * preliminary addresses - these have to be modified after the | |
168 | * SDRAM size has been determined. | |
169 | */ | |
6d0f6bcf JCPV |
170 | memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM; |
171 | memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM; | |
f8cac651 WD |
172 | |
173 | #ifndef CONFIG_CAN_DRIVER | |
d4ca31c4 | 174 | if ((board_type != 'L') && |
090eb735 | 175 | (board_type != 'M') && |
11d9eec4 | 176 | (board_type != 'D') ) { /* only one SDRAM bank on L, M and D modules */ |
6d0f6bcf JCPV |
177 | memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM; |
178 | memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM; | |
f8cac651 WD |
179 | } |
180 | #endif /* CONFIG_CAN_DRIVER */ | |
181 | ||
6d0f6bcf | 182 | memctl->memc_mamr = CONFIG_SYS_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */ |
f8cac651 WD |
183 | |
184 | udelay (200); | |
185 | ||
186 | /* perform SDRAM initializsation sequence */ | |
187 | ||
188 | memctl->memc_mcr = 0x80004105; /* SDRAM bank 0 */ | |
189 | udelay (1); | |
190 | memctl->memc_mcr = 0x80004230; /* SDRAM bank 0 - execute twice */ | |
191 | udelay (1); | |
192 | ||
193 | #ifndef CONFIG_CAN_DRIVER | |
d4ca31c4 | 194 | if ((board_type != 'L') && |
090eb735 | 195 | (board_type != 'M') && |
fc1840e8 | 196 | (board_type != 'D') ) { /* only one SDRAM bank on L, M and D modules */ |
f8cac651 WD |
197 | memctl->memc_mcr = 0x80006105; /* SDRAM bank 1 */ |
198 | udelay (1); | |
199 | memctl->memc_mcr = 0x80006230; /* SDRAM bank 1 - execute twice */ | |
200 | udelay (1); | |
201 | } | |
202 | #endif /* CONFIG_CAN_DRIVER */ | |
203 | ||
204 | memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */ | |
205 | ||
206 | udelay (1000); | |
207 | ||
208 | /* | |
209 | * Check Bank 0 Memory Size for re-configuration | |
210 | * | |
211 | * try 8 column mode | |
212 | */ | |
6d0f6bcf | 213 | size8 = dram_size (CONFIG_SYS_MAMR_8COL, SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE); |
d4ca31c4 | 214 | debug ("SDRAM Bank 0 in 8 column mode: %ld MB\n", size8 >> 20); |
f8cac651 WD |
215 | |
216 | udelay (1000); | |
217 | ||
218 | /* | |
219 | * try 9 column mode | |
220 | */ | |
6d0f6bcf | 221 | size9 = dram_size (CONFIG_SYS_MAMR_9COL, SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE); |
d4ca31c4 | 222 | debug ("SDRAM Bank 0 in 9 column mode: %ld MB\n", size9 >> 20); |
f8cac651 | 223 | |
c178d3da WD |
224 | udelay(1000); |
225 | ||
6d0f6bcf | 226 | #if defined(CONFIG_SYS_MAMR_10COL) |
c178d3da WD |
227 | /* |
228 | * try 10 column mode | |
229 | */ | |
6d0f6bcf | 230 | size10 = dram_size (CONFIG_SYS_MAMR_10COL, SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE); |
c178d3da WD |
231 | debug ("SDRAM Bank 0 in 10 column mode: %ld MB\n", size10 >> 20); |
232 | #else | |
233 | size10 = 0; | |
6d0f6bcf | 234 | #endif /* CONFIG_SYS_MAMR_10COL */ |
c178d3da WD |
235 | |
236 | if ((size8 < size10) && (size9 < size10)) { | |
237 | size_b0 = size10; | |
238 | } else if ((size8 < size9) && (size10 < size9)) { | |
f8cac651 | 239 | size_b0 = size9; |
6d0f6bcf | 240 | memctl->memc_mamr = CONFIG_SYS_MAMR_9COL; |
c178d3da WD |
241 | udelay (500); |
242 | } else { | |
f8cac651 | 243 | size_b0 = size8; |
6d0f6bcf | 244 | memctl->memc_mamr = CONFIG_SYS_MAMR_8COL; |
f8cac651 | 245 | udelay (500); |
f8cac651 | 246 | } |
d4ca31c4 | 247 | debug ("SDRAM Bank 0: %ld MB\n", size_b0 >> 20); |
f8cac651 WD |
248 | |
249 | #ifndef CONFIG_CAN_DRIVER | |
d4ca31c4 | 250 | if ((board_type != 'L') && |
090eb735 | 251 | (board_type != 'M') && |
11d9eec4 | 252 | (board_type != 'D') ) { /* only one SDRAM bank on L, M and D modules */ |
f8cac651 WD |
253 | /* |
254 | * Check Bank 1 Memory Size | |
255 | * use current column settings | |
256 | * [9 column SDRAM may also be used in 8 column mode, | |
257 | * but then only half the real size will be used.] | |
258 | */ | |
77ddac94 | 259 | size_b1 = dram_size (memctl->memc_mamr, (long int *)SDRAM_BASE3_PRELIM, |
d4ca31c4 WD |
260 | SDRAM_MAX_SIZE); |
261 | debug ("SDRAM Bank 1: %ld MB\n", size_b1 >> 20); | |
f8cac651 WD |
262 | } else { |
263 | size_b1 = 0; | |
264 | } | |
d4ca31c4 | 265 | #endif /* CONFIG_CAN_DRIVER */ |
f8cac651 WD |
266 | |
267 | udelay (1000); | |
268 | ||
269 | /* | |
270 | * Adjust refresh rate depending on SDRAM type, both banks | |
271 | * For types > 128 MBit leave it at the current (fast) rate | |
272 | */ | |
273 | if ((size_b0 < 0x02000000) && (size_b1 < 0x02000000)) { | |
274 | /* reduce to 15.6 us (62.4 us / quad) */ | |
6d0f6bcf | 275 | memctl->memc_mptpr = CONFIG_SYS_MPTPR_2BK_4K; |
f8cac651 WD |
276 | udelay (1000); |
277 | } | |
278 | ||
279 | /* | |
280 | * Final mapping: map bigger bank first | |
281 | */ | |
282 | if (size_b1 > size_b0) { /* SDRAM Bank 1 is bigger - map first */ | |
283 | ||
6d0f6bcf JCPV |
284 | memctl->memc_or3 = ((-size_b1) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM; |
285 | memctl->memc_br3 = (CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; | |
f8cac651 WD |
286 | |
287 | if (size_b0 > 0) { | |
288 | /* | |
289 | * Position Bank 0 immediately above Bank 1 | |
290 | */ | |
6d0f6bcf JCPV |
291 | memctl->memc_or2 = ((-size_b0) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM; |
292 | memctl->memc_br2 = ((CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V) | |
c178d3da | 293 | + size_b1; |
f8cac651 WD |
294 | } else { |
295 | unsigned long reg; | |
296 | ||
297 | /* | |
298 | * No bank 0 | |
299 | * | |
300 | * invalidate bank | |
301 | */ | |
302 | memctl->memc_br2 = 0; | |
303 | ||
304 | /* adjust refresh rate depending on SDRAM type, one bank */ | |
305 | reg = memctl->memc_mptpr; | |
6d0f6bcf | 306 | reg >>= 1; /* reduce to CONFIG_SYS_MPTPR_1BK_8K / _4K */ |
f8cac651 WD |
307 | memctl->memc_mptpr = reg; |
308 | } | |
309 | ||
310 | } else { /* SDRAM Bank 0 is bigger - map first */ | |
311 | ||
6d0f6bcf | 312 | memctl->memc_or2 = ((-size_b0) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM; |
f8cac651 | 313 | memctl->memc_br2 = |
6d0f6bcf | 314 | (CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; |
f8cac651 WD |
315 | |
316 | if (size_b1 > 0) { | |
317 | /* | |
318 | * Position Bank 1 immediately above Bank 0 | |
319 | */ | |
320 | memctl->memc_or3 = | |
6d0f6bcf | 321 | ((-size_b1) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM; |
f8cac651 | 322 | memctl->memc_br3 = |
6d0f6bcf | 323 | ((CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V) |
f8cac651 WD |
324 | + size_b0; |
325 | } else { | |
326 | unsigned long reg; | |
327 | ||
328 | #ifndef CONFIG_CAN_DRIVER | |
329 | /* | |
330 | * No bank 1 | |
331 | * | |
332 | * invalidate bank | |
333 | */ | |
334 | memctl->memc_br3 = 0; | |
335 | #endif /* CONFIG_CAN_DRIVER */ | |
336 | ||
337 | /* adjust refresh rate depending on SDRAM type, one bank */ | |
338 | reg = memctl->memc_mptpr; | |
6d0f6bcf | 339 | reg >>= 1; /* reduce to CONFIG_SYS_MPTPR_1BK_8K / _4K */ |
f8cac651 WD |
340 | memctl->memc_mptpr = reg; |
341 | } | |
342 | } | |
343 | ||
344 | udelay (10000); | |
345 | ||
346 | #ifdef CONFIG_CAN_DRIVER | |
9d29250e JG |
347 | /* UPM initialization for CAN @ CLKOUT <= 66 MHz */ |
348 | ||
f8cac651 | 349 | /* Initialize OR3 / BR3 */ |
6d0f6bcf JCPV |
350 | memctl->memc_or3 = CONFIG_SYS_OR3_CAN; |
351 | memctl->memc_br3 = CONFIG_SYS_BR3_CAN; | |
f8cac651 WD |
352 | |
353 | /* Initialize MBMR */ | |
fd3103bb | 354 | memctl->memc_mbmr = MBMR_GPL_B4DIS; /* GPL_B4 ouput line Disable */ |
f8cac651 WD |
355 | |
356 | /* Initialize UPMB for CAN: single read */ | |
9d29250e | 357 | memctl->memc_mdr = 0xFFFFCC04; |
f8cac651 WD |
358 | memctl->memc_mcr = 0x0100 | UPMB; |
359 | ||
360 | memctl->memc_mdr = 0x0FFFD004; | |
361 | memctl->memc_mcr = 0x0101 | UPMB; | |
362 | ||
363 | memctl->memc_mdr = 0x0FFFC000; | |
364 | memctl->memc_mcr = 0x0102 | UPMB; | |
365 | ||
366 | memctl->memc_mdr = 0x3FFFC004; | |
367 | memctl->memc_mcr = 0x0103 | UPMB; | |
368 | ||
9d29250e | 369 | memctl->memc_mdr = 0xFFFFDC07; |
f8cac651 WD |
370 | memctl->memc_mcr = 0x0104 | UPMB; |
371 | ||
372 | /* Initialize UPMB for CAN: single write */ | |
9d29250e | 373 | memctl->memc_mdr = 0xFFFCCC04; |
f8cac651 WD |
374 | memctl->memc_mcr = 0x0118 | UPMB; |
375 | ||
9d29250e | 376 | memctl->memc_mdr = 0xCFFCDC04; |
f8cac651 WD |
377 | memctl->memc_mcr = 0x0119 | UPMB; |
378 | ||
9d29250e | 379 | memctl->memc_mdr = 0x3FFCC000; |
f8cac651 WD |
380 | memctl->memc_mcr = 0x011A | UPMB; |
381 | ||
9d29250e | 382 | memctl->memc_mdr = 0xFFFCC004; |
f8cac651 WD |
383 | memctl->memc_mcr = 0x011B | UPMB; |
384 | ||
9d29250e | 385 | memctl->memc_mdr = 0xFFFDC405; |
f8cac651 WD |
386 | memctl->memc_mcr = 0x011C | UPMB; |
387 | #endif /* CONFIG_CAN_DRIVER */ | |
388 | ||
bdccc4fe WD |
389 | #ifdef CONFIG_ISP1362_USB |
390 | /* Initialize OR5 / BR5 */ | |
6d0f6bcf JCPV |
391 | memctl->memc_or5 = CONFIG_SYS_OR5_ISP1362; |
392 | memctl->memc_br5 = CONFIG_SYS_BR5_ISP1362; | |
bdccc4fe | 393 | #endif /* CONFIG_ISP1362_USB */ |
f8cac651 WD |
394 | return (size_b0 + size_b1); |
395 | } | |
396 | ||
397 | /* ------------------------------------------------------------------------- */ | |
398 | ||
399 | /* | |
400 | * Check memory range for valid RAM. A simple memory test determines | |
401 | * the actually available RAM size between addresses `base' and | |
402 | * `base + maxsize'. Some (not all) hardware errors are detected: | |
403 | * - short between address lines | |
404 | * - short between data lines | |
405 | */ | |
406 | ||
d4ca31c4 | 407 | static long int dram_size (long int mamr_value, long int *base, long int maxsize) |
f8cac651 | 408 | { |
6d0f6bcf | 409 | volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; |
f8cac651 | 410 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
f8cac651 WD |
411 | |
412 | memctl->memc_mamr = mamr_value; | |
413 | ||
c83bf6a2 | 414 | return (get_ram_size(base, maxsize)); |
f8cac651 WD |
415 | } |
416 | ||
417 | /* ------------------------------------------------------------------------- */ | |
1c43771b | 418 | |
7c803be2 | 419 | #ifdef CONFIG_MISC_INIT_R |
9c150102 | 420 | extern void load_sernum_ethaddr(void); |
1c43771b WD |
421 | int misc_init_r (void) |
422 | { | |
6d0f6bcf | 423 | volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; |
7c803be2 WD |
424 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
425 | ||
9c150102 MF |
426 | load_sernum_ethaddr(); |
427 | ||
6d0f6bcf | 428 | #ifdef CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ |
7c803be2 WD |
429 | int scy, trlx, flash_or_timing, clk_diff; |
430 | ||
6d0f6bcf JCPV |
431 | scy = (CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ & OR_SCY_MSK) >> 4; |
432 | if (CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ & OR_TRLX) { | |
7c803be2 WD |
433 | trlx = OR_TRLX; |
434 | scy *= 2; | |
87b4ef56 | 435 | } else { |
7c803be2 | 436 | trlx = 0; |
87b4ef56 | 437 | } |
7c803be2 | 438 | |
87b4ef56 WD |
439 | /* |
440 | * We assume that each 10MHz of bus clock require 1-clk SCY | |
441 | * adjustment. | |
442 | */ | |
7c803be2 WD |
443 | clk_diff = (gd->bus_clk / 1000000) - 50; |
444 | ||
87b4ef56 WD |
445 | /* |
446 | * We need proper rounding here. This is what the "+5" and "-5" | |
447 | * are here for. | |
448 | */ | |
7c803be2 WD |
449 | if (clk_diff >= 0) |
450 | scy += (clk_diff + 5) / 10; | |
451 | else | |
452 | scy += (clk_diff - 5) / 10; | |
453 | ||
87b4ef56 WD |
454 | /* |
455 | * For bus frequencies above 50MHz, we want to use relaxed timing | |
456 | * (OR_TRLX). | |
457 | */ | |
7c803be2 WD |
458 | if (gd->bus_clk >= 50000000) |
459 | trlx = OR_TRLX; | |
460 | else | |
461 | trlx = 0; | |
462 | ||
463 | if (trlx) | |
464 | scy /= 2; | |
465 | ||
466 | if (scy > 0xf) | |
467 | scy = 0xf; | |
468 | if (scy < 1) | |
469 | scy = 1; | |
470 | ||
471 | flash_or_timing = (scy << 4) | trlx | | |
6d0f6bcf | 472 | (CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ & ~(OR_TRLX | OR_SCY_MSK)); |
7c803be2 | 473 | |
87b4ef56 WD |
474 | memctl->memc_or0 = |
475 | flash_or_timing | (-flash_info[0].size & OR_AM_MSK); | |
7c803be2 | 476 | #else |
87b4ef56 | 477 | memctl->memc_or0 = |
6d0f6bcf | 478 | CONFIG_SYS_OR_TIMING_FLASH | (-flash_info[0].size & OR_AM_MSK); |
7c803be2 | 479 | #endif |
6d0f6bcf | 480 | memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V; |
7c803be2 WD |
481 | |
482 | debug ("## BR0: 0x%08x OR0: 0x%08x\n", | |
87b4ef56 | 483 | memctl->memc_br0, memctl->memc_or0); |
1c43771b | 484 | |
7c803be2 | 485 | if (flash_info[1].size) { |
6d0f6bcf | 486 | #ifdef CONFIG_SYS_OR_TIMING_FLASH_AT_50MHZ |
7c803be2 | 487 | memctl->memc_or1 = flash_or_timing | |
87b4ef56 | 488 | (-flash_info[1].size & 0xFFFF8000); |
7c803be2 | 489 | #else |
6d0f6bcf | 490 | memctl->memc_or1 = CONFIG_SYS_OR_TIMING_FLASH | |
87b4ef56 | 491 | (-flash_info[1].size & 0xFFFF8000); |
7c803be2 | 492 | #endif |
87b4ef56 | 493 | memctl->memc_br1 = |
6d0f6bcf | 494 | ((CONFIG_SYS_FLASH_BASE + |
87b4ef56 WD |
495 | flash_info[0]. |
496 | size) & BR_BA_MSK) | BR_MS_GPCM | BR_V; | |
7c803be2 WD |
497 | |
498 | debug ("## BR1: 0x%08x OR1: 0x%08x\n", | |
87b4ef56 | 499 | memctl->memc_br1, memctl->memc_or1); |
7c803be2 | 500 | } else { |
87b4ef56 | 501 | memctl->memc_br1 = 0; /* invalidate bank */ |
7c803be2 WD |
502 | |
503 | debug ("## DISABLE BR1: 0x%08x OR1: 0x%08x\n", | |
87b4ef56 | 504 | memctl->memc_br1, memctl->memc_or1); |
7c803be2 WD |
505 | } |
506 | ||
507 | # ifdef CONFIG_IDE_LED | |
1c43771b WD |
508 | /* Configure PA15 as output port */ |
509 | immap->im_ioport.iop_padir |= 0x0001; | |
510 | immap->im_ioport.iop_paodr |= 0x0001; | |
511 | immap->im_ioport.iop_papar &= ~0x0001; | |
512 | immap->im_ioport.iop_padat &= ~0x0001; /* turn it off */ | |
cfca5e60 | 513 | # endif |
7c803be2 WD |
514 | |
515 | #ifdef CONFIG_NSCU | |
516 | /* wake up ethernet module */ | |
87b4ef56 WD |
517 | immap->im_ioport.iop_pcpar &= ~0x0004; /* GPIO pin */ |
518 | immap->im_ioport.iop_pcdir |= 0x0004; /* output */ | |
519 | immap->im_ioport.iop_pcso &= ~0x0004; /* for clarity */ | |
520 | immap->im_ioport.iop_pcdat |= 0x0004; /* enable */ | |
521 | #endif /* CONFIG_NSCU */ | |
7c803be2 | 522 | |
1c43771b WD |
523 | return (0); |
524 | } | |
7c803be2 WD |
525 | #endif /* CONFIG_MISC_INIT_R */ |
526 | ||
1c43771b | 527 | |
cfca5e60 | 528 | # ifdef CONFIG_IDE_LED |
1c43771b WD |
529 | void ide_led (uchar led, uchar status) |
530 | { | |
6d0f6bcf | 531 | volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; |
1c43771b WD |
532 | |
533 | /* We have one led for both pcmcia slots */ | |
534 | if (status) { /* led on */ | |
535 | immap->im_ioport.iop_padat |= 0x0001; | |
536 | } else { | |
537 | immap->im_ioport.iop_padat &= ~0x0001; | |
538 | } | |
539 | } | |
cfca5e60 | 540 | # endif |
1c43771b | 541 | |
6b59e03e HS |
542 | #ifdef CONFIG_LCD_INFO |
543 | #include <lcd.h> | |
1450c4a6 | 544 | #include <version.h> |
561858ee | 545 | #include <timestamp.h> |
6b59e03e HS |
546 | |
547 | void lcd_show_board_info(void) | |
548 | { | |
1450c4a6 AG |
549 | char temp[32]; |
550 | ||
561858ee | 551 | lcd_printf ("%s (%s - %s)\n", U_BOOT_VERSION, U_BOOT_DATE, U_BOOT_TIME); |
6b59e03e HS |
552 | lcd_printf ("(C) 2008 DENX Software Engineering GmbH\n"); |
553 | lcd_printf (" Wolfgang DENK, wd@denx.de\n"); | |
554 | #ifdef CONFIG_LCD_INFO_BELOW_LOGO | |
555 | lcd_printf ("MPC823 CPU at %s MHz\n", | |
556 | strmhz(temp, gd->cpu_clk)); | |
6b59e03e HS |
557 | lcd_printf (" %ld MB RAM, %ld MB Flash\n", |
558 | gd->ram_size >> 20, | |
559 | gd->bd->bi_flashsize >> 20 ); | |
560 | #else | |
561 | /* leave one blank line */ | |
562 | lcd_printf ("\nMPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash\n", | |
563 | strmhz(temp, gd->cpu_clk), | |
564 | gd->ram_size >> 20, | |
565 | gd->bd->bi_flashsize >> 20 ); | |
566 | #endif /* CONFIG_LCD_INFO_BELOW_LOGO */ | |
567 | } | |
568 | #endif /* CONFIG_LCD_INFO */ | |
569 | ||
6ed3b9d4 HS |
570 | /* |
571 | * Device Tree Support | |
572 | */ | |
573 | #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) | |
574 | int fdt_set_node_and_value (void *blob, | |
575 | char *nodename, | |
576 | char *regname, | |
577 | void *var, | |
578 | int size) | |
579 | { | |
580 | int ret = 0; | |
581 | int nodeoffset = 0; | |
582 | ||
583 | nodeoffset = fdt_path_offset (blob, nodename); | |
584 | if (nodeoffset >= 0) { | |
585 | ret = fdt_setprop (blob, nodeoffset, regname, var, | |
586 | size); | |
587 | if (ret < 0) { | |
588 | printf("ft_blob_update(): " | |
589 | "cannot set %s/%s property; err: %s\n", | |
590 | nodename, regname, fdt_strerror (ret)); | |
591 | } | |
592 | } else { | |
593 | printf("ft_blob_update(): " | |
594 | "cannot find %s node err:%s\n", | |
595 | nodename, fdt_strerror (nodeoffset)); | |
596 | } | |
597 | return ret; | |
598 | } | |
599 | ||
600 | int fdt_del_node_name (void *blob, char *nodename) | |
601 | { | |
602 | int ret = 0; | |
603 | int nodeoffset = 0; | |
604 | ||
605 | nodeoffset = fdt_path_offset (blob, nodename); | |
606 | if (nodeoffset >= 0) { | |
607 | ret = fdt_del_node (blob, nodeoffset); | |
608 | if (ret < 0) { | |
609 | printf("%s: cannot delete %s; err: %s\n", | |
610 | __func__, nodename, fdt_strerror (ret)); | |
611 | } | |
612 | } else { | |
613 | printf("%s: cannot find %s node err:%s\n", | |
614 | __func__, nodename, fdt_strerror (nodeoffset)); | |
615 | } | |
616 | return ret; | |
617 | } | |
618 | ||
619 | int fdt_del_prop_name (void *blob, char *nodename, char *propname) | |
620 | { | |
621 | int ret = 0; | |
622 | int nodeoffset = 0; | |
623 | ||
624 | nodeoffset = fdt_path_offset (blob, nodename); | |
625 | if (nodeoffset >= 0) { | |
626 | ret = fdt_delprop (blob, nodeoffset, propname); | |
627 | if (ret < 0) { | |
628 | printf("%s: cannot delete %s %s; err: %s\n", | |
629 | __func__, nodename, propname, | |
630 | fdt_strerror (ret)); | |
631 | } | |
632 | } else { | |
633 | printf("%s: cannot find %s node err:%s\n", | |
634 | __func__, nodename, fdt_strerror (nodeoffset)); | |
635 | } | |
636 | return ret; | |
637 | } | |
638 | ||
639 | /* | |
640 | * update "brg" property in the blob | |
641 | */ | |
642 | void ft_blob_update (void *blob, bd_t *bd) | |
643 | { | |
644 | uchar enetaddr[6]; | |
645 | ulong brg_data = 0; | |
646 | ||
647 | /* BRG */ | |
648 | brg_data = cpu_to_be32(bd->bi_busfreq); | |
649 | fdt_set_node_and_value(blob, | |
650 | "/soc/cpm", "brg-frequency", | |
651 | &brg_data, sizeof(brg_data)); | |
652 | ||
653 | /* MAC addr */ | |
654 | if (eth_getenv_enetaddr("ethaddr", enetaddr)) { | |
655 | fdt_set_node_and_value(blob, | |
656 | "ethernet0", "local-mac-address", | |
657 | enetaddr, sizeof(u8) * 6); | |
658 | } | |
659 | ||
660 | if (hwconfig_arg_cmp("fec", "off")) { | |
661 | /* no FEC on this plattform, delete DTS nodes */ | |
662 | fdt_del_node_name (blob, "ethernet1"); | |
663 | fdt_del_node_name (blob, "mdio1"); | |
664 | /* also the aliases entries */ | |
665 | fdt_del_prop_name (blob, "/aliases", "ethernet1"); | |
666 | fdt_del_prop_name (blob, "/aliases", "mdio1"); | |
667 | } else { | |
668 | /* adjust local-mac-address for FEC ethernet */ | |
669 | if (eth_getenv_enetaddr("eth1addr", enetaddr)) { | |
670 | fdt_set_node_and_value(blob, | |
671 | "ethernet1", "local-mac-address", | |
672 | enetaddr, sizeof(u8) * 6); | |
673 | } | |
674 | } | |
675 | } | |
676 | ||
e895a4b0 | 677 | int ft_board_setup(void *blob, bd_t *bd) |
6ed3b9d4 HS |
678 | { |
679 | ft_cpu_setup(blob, bd); | |
680 | ft_blob_update(blob, bd); | |
e895a4b0 SG |
681 | |
682 | return 0; | |
6ed3b9d4 HS |
683 | } |
684 | #endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */ | |
685 | ||
efc6f447 GL |
686 | /* ---------------------------------------------------------------------------- */ |
687 | /* TK885D specific initializaion */ | |
688 | /* ---------------------------------------------------------------------------- */ | |
689 | #ifdef CONFIG_TK885D | |
690 | #include <miiphy.h> | |
691 | int last_stage_init(void) | |
692 | { | |
693 | const unsigned char phy[] = {CONFIG_FEC1_PHY, CONFIG_FEC2_PHY}; | |
694 | unsigned short reg; | |
695 | int ret, i = 100; | |
696 | char *s; | |
697 | ||
698 | mii_init(); | |
699 | /* Without this delay 0xff is read from the UART buffer later in | |
700 | * abortboot() and autoboot is aborted */ | |
701 | udelay(10000); | |
702 | while (tstc() && i--) | |
703 | (void)getc(); | |
704 | ||
705 | /* Check if auto-negotiation is prohibited */ | |
706 | s = getenv("phy_auto_nego"); | |
707 | ||
708 | if (!s || !strcmp(s, "on")) | |
709 | /* Nothing to do - autonegotiation by default */ | |
710 | return 0; | |
711 | ||
712 | for (i = 0; i < 2; i++) { | |
8ef583a0 | 713 | ret = miiphy_read("FEC", phy[i], MII_BMCR, ®); |
efc6f447 GL |
714 | if (ret) { |
715 | printf("Cannot read BMCR on PHY %d\n", phy[i]); | |
716 | return 0; | |
717 | } | |
718 | /* Auto-negotiation off, hard set full duplex, 100Mbps */ | |
48690d80 | 719 | ret = miiphy_write("FEC", phy[i], |
8ef583a0 MF |
720 | MII_BMCR, (reg | BMCR_SPEED100 | |
721 | BMCR_FULLDPLX) & ~BMCR_ANENABLE); | |
efc6f447 GL |
722 | if (ret) { |
723 | printf("Cannot write BMCR on PHY %d\n", phy[i]); | |
724 | return 0; | |
725 | } | |
726 | } | |
727 | ||
728 | return 0; | |
729 | } | |
efc6f447 | 730 | #endif |