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