]>
Commit | Line | Data |
---|---|---|
16f21704 WD |
1 | /* |
2 | * (C) Copyright 2000 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | #include <common.h> | |
25 | #include <mpc8xx.h> | |
26 | ||
d87080b7 WD |
27 | DECLARE_GLOBAL_DATA_PTR; |
28 | ||
16f21704 WD |
29 | /* ------------------------------------------------------------------------- */ |
30 | ||
31 | static long int dram_size (long int, long int *, long int); | |
32 | static void read_hw_vers (void); | |
33 | ||
34 | /* ------------------------------------------------------------------------- */ | |
35 | ||
36 | #define _NOT_USED_ 0xFFFFFFFF | |
37 | ||
38 | const uint sdram_table[] = { | |
39 | ||
40 | /* single read (offset 0x00 in upm ram) */ | |
41 | ||
42 | 0xEECEFC24, 0x100DFC24, 0xE02FBC04, 0x01AA7C04, | |
43 | 0x1FB5FC00, 0xFFFFFC05, _NOT_USED_, _NOT_USED_, | |
44 | ||
45 | /* burst read (offset 0x08 in upm ram) */ | |
46 | ||
47 | 0xEECEFC24, 0x100DFC24, 0xE0FFBC04, 0x10FF7C04, | |
48 | 0xF0FFFC00, 0xF0FFFC00, 0xF0FFFC00, 0xFFFFFC00, | |
49 | 0xFFFFFC05, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
50 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
51 | ||
52 | /* single write (offset 0x18 in upm ram) */ | |
53 | ||
54 | 0xEECEFC24, 0x100DFC24, 0xE02BBC04, 0x01A27C00, | |
55 | 0xEFAAFC04, 0x1FB5FC05, _NOT_USED_, _NOT_USED_, | |
56 | ||
57 | /* burst write (offset 0x20 in upm ram) */ | |
58 | ||
59 | 0xEECEFC24, 0x103DFC24, 0xE0FBBC00, 0x10F77C00, | |
60 | 0xF0FFFC00, 0xF0FFFC00, 0xF0FFFC04, 0xFFFFFC05, | |
61 | ||
62 | /* init part1 (offset 0x28 in upm ram) */ | |
63 | ||
64 | 0xEFFAFC3C, 0x1FF4FC34, 0xEFFCBC34, 0x1FFC3C34, | |
65 | 0xFFFC3C35, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
66 | ||
67 | /* refresh (offset 0x30 in upm ram) */ | |
68 | ||
69 | 0xEFFEBC0C, 0x1FFD7C04, 0xFFFFFC04, 0xFFFFFC05, | |
70 | ||
71 | /* init part2 (offset 0x34 in upm ram) */ | |
72 | ||
73 | 0xFFFEBC04, 0xEFFC3CB4, 0x1FFC3C34, 0xFFFC3C34, | |
74 | 0xFFFC3C34, 0xEFE83CB4, 0x1FB57C35, _NOT_USED_, | |
75 | ||
76 | /* exception (offset 0x3C in upm ram) */ | |
77 | ||
78 | 0xFFFFFC05, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
79 | ||
80 | }; | |
81 | ||
82 | /* ------------------------------------------------------------------------- */ | |
83 | ||
84 | ||
85 | /* | |
86 | * Check Board Identity: | |
87 | * | |
88 | * Test ETX ID string (ETX_xxx...) | |
89 | * | |
90 | * Return 1 always. | |
91 | */ | |
92 | ||
93 | int checkboard (void) | |
94 | { | |
f0c0b3a9 WD |
95 | char buf[64]; |
96 | int i; | |
97 | int l = getenv_f("serial#", buf, sizeof(buf)); | |
16f21704 WD |
98 | |
99 | puts ("Board: "); | |
100 | ||
101 | #ifdef SB_ETX094 | |
102 | gd->board_type = 0; /* 0 = 2SDRAM-Device */ | |
103 | #else | |
104 | gd->board_type = 1; /* 1 = 1SDRAM-Device */ | |
105 | #endif | |
106 | ||
f0c0b3a9 | 107 | if (l < 0 || strncmp(buf, "ETX_", 4)) { |
16f21704 WD |
108 | puts ("### No HW ID - assuming ETX_094\n"); |
109 | read_hw_vers (); | |
110 | return (0); | |
111 | } | |
112 | ||
f0c0b3a9 WD |
113 | for (i = 0; i < l; ++i) { |
114 | if (buf[i] == ' ') | |
16f21704 | 115 | break; |
f0c0b3a9 | 116 | putc(buf[i]); |
16f21704 WD |
117 | } |
118 | putc ('\n'); | |
119 | ||
120 | read_hw_vers (); | |
121 | return (0); | |
122 | } | |
123 | ||
124 | /* ------------------------------------------------------------------------- */ | |
125 | ||
9973e3c6 | 126 | phys_size_t initdram (int board_type) |
16f21704 | 127 | { |
6d0f6bcf | 128 | volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; |
16f21704 WD |
129 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
130 | long int size_b0, size_b1, size8, size9; | |
131 | ||
132 | upmconfig (UPMA, (uint *) sdram_table, | |
133 | sizeof (sdram_table) / sizeof (uint)); | |
134 | ||
135 | /* | |
136 | * Preliminary prescaler for refresh (depends on number of | |
137 | * banks): This value is selected for four cycles every 62.4 us | |
138 | * with two SDRAM banks or four cycles every 31.2 us with one | |
139 | * bank. It will be adjusted after memory sizing. | |
140 | */ | |
6d0f6bcf | 141 | memctl->memc_mptpr = CONFIG_SYS_MPTPR_1BK_4K; /* MPTPR_PTP_DIV32 0x0200 */ |
16f21704 WD |
142 | |
143 | /* A3(SDRAM)=0 => Bursttype = Sequential | |
144 | * A2-A0(SDRAM)=010 => Burst length = 4 | |
145 | * A4-A6(SDRAM)=010 => CasLat=2 | |
146 | */ | |
147 | memctl->memc_mar = 0x00000088; | |
148 | ||
149 | /* | |
150 | * Map controller banks 2 and 3 to the SDRAM banks 2 and 3 at | |
151 | * preliminary addresses - these have to be modified after the | |
152 | * SDRAM size has been determined. | |
153 | */ | |
6d0f6bcf JCPV |
154 | memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM; |
155 | memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM; | |
16f21704 WD |
156 | |
157 | if (board_type == 0) { /* "L" type boards have only one bank SDRAM */ | |
6d0f6bcf JCPV |
158 | memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM; |
159 | memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM; | |
16f21704 WD |
160 | } |
161 | ||
6d0f6bcf | 162 | memctl->memc_mamr = CONFIG_SYS_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */ |
16f21704 WD |
163 | |
164 | udelay (200); | |
165 | ||
166 | /* perform SDRAM initializsation sequence */ | |
167 | ||
168 | memctl->memc_mcr = 0x80004128; /* SDRAM bank 0 (CS2) - Init Part 1 */ | |
169 | memctl->memc_mcr = 0x80004734; /* SDRAM bank 0 (CS2) - Init Part 2 */ | |
170 | udelay (1); | |
171 | ||
172 | if (board_type == 0) { /* "L" type boards have only one bank SDRAM */ | |
173 | memctl->memc_mcr = 0x80006128; /* SDRAM bank 1 (CS3) - Init Part 1 */ | |
174 | memctl->memc_mcr = 0x80006734; /* SDRAM bank 1 (CS3) - Init Part 2 */ | |
175 | udelay (1); | |
176 | } | |
177 | ||
178 | memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */ | |
179 | ||
180 | udelay (1000); | |
181 | ||
182 | /* | |
183 | * Check Bank 0 Memory Size for re-configuration | |
184 | * | |
185 | * try 8 column mode | |
186 | */ | |
6d0f6bcf | 187 | size8 = dram_size (CONFIG_SYS_MAMR_8COL, (long *) SDRAM_BASE2_PRELIM, |
16f21704 WD |
188 | SDRAM_MAX_SIZE); |
189 | ||
190 | udelay (1000); | |
191 | ||
192 | /* | |
193 | * try 9 column mode | |
194 | */ | |
6d0f6bcf | 195 | size9 = dram_size (CONFIG_SYS_MAMR_9COL, (long *) SDRAM_BASE2_PRELIM, |
16f21704 WD |
196 | SDRAM_MAX_SIZE); |
197 | ||
198 | if (size8 < size9) { /* leave configuration at 9 columns */ | |
199 | size_b0 = size9; | |
200 | /* debug ("SDRAM Bank 0 in 9 column mode: %ld MB\n", size >> 20); */ | |
201 | } else { /* back to 8 columns */ | |
202 | size_b0 = size8; | |
6d0f6bcf | 203 | memctl->memc_mamr = CONFIG_SYS_MAMR_8COL; |
16f21704 WD |
204 | udelay (500); |
205 | /* debug ("SDRAM Bank 0 in 8 column mode: %ld MB\n", size >> 20); */ | |
206 | } | |
207 | ||
208 | if (board_type == 0) { /* "L" type boards have only one bank SDRAM */ | |
209 | /* | |
210 | * Check Bank 1 Memory Size | |
211 | * use current column settings | |
212 | * [9 column SDRAM may also be used in 8 column mode, | |
213 | * but then only half the real size will be used.] | |
214 | */ | |
215 | size_b1 = | |
77ddac94 | 216 | dram_size (memctl->memc_mamr, (long *) SDRAM_BASE3_PRELIM, |
16f21704 WD |
217 | SDRAM_MAX_SIZE); |
218 | /* debug ("SDRAM Bank 1: %ld MB\n", size8 >> 20); */ | |
219 | } else { | |
220 | size_b1 = 0; | |
221 | } | |
222 | ||
223 | udelay (1000); | |
224 | ||
225 | /* | |
226 | * Adjust refresh rate depending on SDRAM type, both banks | |
227 | * For types > 128 MBit leave it at the current (fast) rate | |
228 | */ | |
229 | if ((size_b0 < 0x02000000) && (size_b1 < 0x02000000)) { | |
230 | /* reduce to 15.6 us (62.4 us / quad) */ | |
6d0f6bcf | 231 | memctl->memc_mptpr = CONFIG_SYS_MPTPR_2BK_4K; /*DIV16 */ |
16f21704 WD |
232 | udelay (1000); |
233 | } | |
234 | ||
235 | /* | |
236 | * Final mapping: map bigger bank first | |
237 | */ | |
238 | if (size_b1 > size_b0) { /* SDRAM Bank 1 is bigger - map first */ | |
239 | ||
6d0f6bcf | 240 | memctl->memc_or3 = ((-size_b1) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM; |
16f21704 | 241 | memctl->memc_br3 = |
6d0f6bcf | 242 | (CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; |
16f21704 WD |
243 | |
244 | if (size_b0 > 0) { | |
245 | /* | |
246 | * Position Bank 0 immediately above Bank 1 | |
247 | */ | |
248 | memctl->memc_or2 = | |
6d0f6bcf | 249 | ((-size_b0) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM; |
16f21704 | 250 | memctl->memc_br2 = |
6d0f6bcf | 251 | ((CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V) |
16f21704 WD |
252 | + size_b1; |
253 | } else { | |
254 | unsigned long reg; | |
255 | ||
256 | /* | |
257 | * No bank 0 | |
258 | * | |
259 | * invalidate bank | |
260 | */ | |
261 | memctl->memc_br2 = 0; | |
262 | ||
263 | /* adjust refresh rate depending on SDRAM type, one bank */ | |
264 | reg = memctl->memc_mptpr; | |
6d0f6bcf | 265 | reg >>= 1; /* reduce to CONFIG_SYS_MPTPR_1BK_8K / _4K */ |
16f21704 WD |
266 | memctl->memc_mptpr = reg; |
267 | } | |
268 | ||
269 | } else { /* SDRAM Bank 0 is bigger - map first */ | |
270 | ||
6d0f6bcf | 271 | memctl->memc_or2 = ((-size_b0) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM; |
16f21704 | 272 | memctl->memc_br2 = |
6d0f6bcf | 273 | (CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; |
16f21704 WD |
274 | |
275 | if (size_b1 > 0) { | |
276 | /* | |
277 | * Position Bank 1 immediately above Bank 0 | |
278 | */ | |
279 | memctl->memc_or3 = | |
6d0f6bcf | 280 | ((-size_b1) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM; |
16f21704 | 281 | memctl->memc_br3 = |
6d0f6bcf | 282 | ((CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V) |
16f21704 WD |
283 | + size_b0; |
284 | } else { | |
285 | unsigned long reg; | |
286 | ||
287 | /* | |
288 | * No bank 1 | |
289 | * | |
290 | * invalidate bank | |
291 | */ | |
292 | memctl->memc_br3 = 0; | |
293 | ||
294 | /* adjust refresh rate depending on SDRAM type, one bank */ | |
295 | reg = memctl->memc_mptpr; | |
6d0f6bcf | 296 | reg >>= 1; /* reduce to CONFIG_SYS_MPTPR_1BK_8K / _4K */ |
16f21704 WD |
297 | memctl->memc_mptpr = reg; |
298 | } | |
299 | } | |
300 | ||
301 | udelay (10000); | |
302 | ||
303 | return (size_b0 + size_b1); | |
304 | } | |
305 | ||
306 | /* ------------------------------------------------------------------------- */ | |
307 | ||
308 | /* | |
309 | * Check memory range for valid RAM. A simple memory test determines | |
310 | * the actually available RAM size between addresses `base' and | |
311 | * `base + maxsize'. Some (not all) hardware errors are detected: | |
312 | * - short between address lines | |
313 | * - short between data lines | |
314 | */ | |
315 | ||
316 | static long int dram_size (long int mamr_value, long int *base, | |
317 | long int maxsize) | |
318 | { | |
6d0f6bcf | 319 | volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; |
16f21704 | 320 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
16f21704 WD |
321 | |
322 | memctl->memc_mamr = mamr_value; | |
323 | ||
c83bf6a2 | 324 | return (get_ram_size(base, maxsize)); |
16f21704 WD |
325 | } |
326 | ||
327 | /* ------------------------------------------------------------------------- */ | |
328 | ||
329 | /* HW-ID Table (Bits: 2^9;2^7;2^5) */ | |
330 | #define HW_ID_0 0x0000 | |
331 | #define HW_ID_1 0x0020 | |
332 | #define HW_ID_2 0x0080 | |
333 | #define HW_ID_3 0x00a0 | |
334 | #define HW_ID_4 0x0200 | |
335 | #define HW_ID_5 0x0220 | |
336 | #define HW_ID_6 0x0280 | |
337 | #define HW_ID_7 0x02a0 | |
338 | ||
339 | void read_hw_vers () | |
340 | { | |
341 | unsigned short rd_msk = 0x02A0; | |
342 | ||
343 | /* HW-ID pin-definition */ | |
6d0f6bcf | 344 | volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; |
16f21704 WD |
345 | |
346 | immr->im_ioport.iop_pddir &= ~(rd_msk); | |
347 | immr->im_ioport.iop_pdpar &= ~(rd_msk); | |
348 | ||
349 | /* debug printf("State of PD: %x\n",immr->im_ioport.iop_pddat); */ | |
350 | ||
351 | /* Check the HW-ID */ | |
352 | printf ("HW-Version: "); | |
353 | switch (immr->im_ioport.iop_pddat & rd_msk) { | |
354 | case HW_ID_0: | |
355 | printf ("V0.1 - V0.3 / W97238-Q3162-A1-1-2\n"); | |
356 | break; | |
357 | case HW_ID_1: | |
358 | printf ("V0.9 / W50037-Q1-D6-1\n"); | |
359 | break; | |
360 | case HW_ID_2: | |
361 | printf ("NOT USED - assuming ID#2\n"); | |
362 | break; | |
363 | case HW_ID_3: | |
364 | printf ("NOT USED - assuming ID#3\n"); | |
365 | break; | |
366 | case HW_ID_4: | |
367 | printf ("NOT USED - assuming ID#4\n"); | |
368 | break; | |
369 | case HW_ID_5: | |
370 | printf ("NOT USED - assuming ID#5\n"); | |
371 | break; | |
372 | case HW_ID_6: | |
373 | printf ("NOT USED - assuming ID#6\n"); | |
374 | break; | |
375 | case HW_ID_7: | |
376 | printf ("NOT USED - assuming ID#7\n"); | |
377 | break; | |
378 | default: | |
379 | printf ("###Error###\n"); | |
380 | break; | |
381 | } | |
382 | } | |
383 | ||
384 | /* ------------------------------------------------------------------------- */ |