]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | /* |
2 | * (C) Copyright 2001 | |
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 | #include <commproc.h> | |
27 | #include <command.h> | |
28 | ||
29 | /* ------------------------------------------------------------------------- */ | |
30 | ||
31 | static long int dram_size (long int, long int *, long int); | |
32 | void can_driver_enable (void); | |
33 | void can_driver_disable (void); | |
34 | ||
35 | int fpga_init(void); | |
36 | ||
37 | /* ------------------------------------------------------------------------- */ | |
38 | ||
39 | #define _NOT_USED_ 0xFFFFFFFF | |
40 | ||
41 | const uint sdram_table[] = | |
42 | { | |
43 | /* | |
44 | * Single Read. (Offset 0 in UPMA RAM) | |
45 | */ | |
46 | 0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBAFC00, | |
47 | 0x1FF5FC47, /* last */ | |
48 | /* | |
49 | * SDRAM Initialization (offset 5 in UPMA RAM) | |
50 | * | |
51 | * This is no UPM entry point. The following definition uses | |
52 | * the remaining space to establish an initialization | |
53 | * sequence, which is executed by a RUN command. | |
54 | * | |
55 | */ | |
56 | 0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */ | |
57 | /* | |
58 | * Burst Read. (Offset 8 in UPMA RAM) | |
59 | */ | |
60 | 0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00, | |
61 | 0xF0AFFC00, 0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */ | |
62 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
63 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
64 | /* | |
65 | * Single Write. (Offset 18 in UPMA RAM) | |
66 | */ | |
67 | 0x1F0DFC04, 0xEEABBC00, 0x01B27C04, 0x1FF5FC47, /* last */ | |
68 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
69 | /* | |
70 | * Burst Write. (Offset 20 in UPMA RAM) | |
71 | */ | |
72 | 0x1F0DFC04, 0xEEABBC00, 0x10A77C00, 0xF0AFFC00, | |
73 | 0xF0AFFC00, 0xE1BAFC04, 0x1FF5FC47, /* last */ | |
74 | _NOT_USED_, | |
75 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
76 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
77 | /* | |
78 | * Refresh (Offset 30 in UPMA RAM) | |
79 | */ | |
80 | 0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, | |
81 | 0xFFFFFC84, 0xFFFFFC07, /* last */ | |
82 | _NOT_USED_, _NOT_USED_, | |
83 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
84 | /* | |
85 | * Exception. (Offset 3c in UPMA RAM) | |
86 | */ | |
87 | 0x7FFFFC07, /* last */ | |
88 | _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
89 | }; | |
90 | ||
91 | /* ------------------------------------------------------------------------- */ | |
92 | ||
93 | ||
94 | /* | |
95 | * Check Board Identity: | |
96 | * | |
97 | * Always return 1 (no second DRAM bank since based on TQM8xxL module) | |
98 | */ | |
99 | ||
100 | int checkboard (void) | |
101 | { | |
102 | unsigned char *s; | |
103 | unsigned char buf[64]; | |
104 | ||
77ddac94 | 105 | s = (getenv_r ("serial#", (char *)&buf, sizeof(buf)) > 0) ? buf : NULL; |
c609719b WD |
106 | |
107 | puts ("Board: Siemens CCM"); | |
108 | ||
109 | if (s) { | |
110 | puts (" ("); | |
111 | ||
112 | for (; *s; ++s) { | |
113 | if (*s == ' ') | |
114 | break; | |
115 | putc (*s); | |
116 | } | |
117 | putc (')'); | |
118 | } | |
119 | ||
120 | putc ('\n'); | |
121 | ||
122 | return (0); | |
123 | } | |
124 | ||
125 | /* ------------------------------------------------------------------------- */ | |
126 | ||
127 | /* | |
128 | * If Power-On-Reset switch off the Red and Green LED: At reset, the | |
129 | * data direction registers are cleared and must therefore be restored. | |
130 | */ | |
131 | #define RSR_CSRS 0x08000000 | |
132 | ||
133 | int power_on_reset(void) | |
134 | { | |
135 | /* Test Reset Status Register */ | |
6d0f6bcf | 136 | return ((volatile immap_t *)CONFIG_SYS_IMMR)->im_clkrst.car_rsr & RSR_CSRS ? 0:1; |
c609719b WD |
137 | } |
138 | ||
139 | #define PB_LED_GREEN 0x10000 /* red LED is on PB.15 */ | |
140 | #define PB_LED_RED 0x20000 /* red LED is on PB.14 */ | |
141 | #define PB_LEDS (PB_LED_GREEN | PB_LED_RED); | |
142 | ||
143 | static void init_leds (void) | |
144 | { | |
6d0f6bcf | 145 | volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; |
c609719b WD |
146 | |
147 | immap->im_cpm.cp_pbpar &= ~PB_LEDS; | |
148 | immap->im_cpm.cp_pbodr &= ~PB_LEDS; | |
149 | immap->im_cpm.cp_pbdir |= PB_LEDS; | |
150 | /* Check stop reset status */ | |
151 | if (power_on_reset()) { | |
152 | immap->im_cpm.cp_pbdat &= ~PB_LEDS; | |
153 | } | |
154 | } | |
155 | ||
156 | /* ------------------------------------------------------------------------- */ | |
157 | ||
9973e3c6 | 158 | phys_size_t initdram (int board_type) |
c609719b | 159 | { |
6d0f6bcf | 160 | volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; |
c609719b WD |
161 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
162 | long int size8, size9; | |
163 | long int size = 0; | |
164 | unsigned long reg; | |
165 | ||
166 | upmconfig(UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint)); | |
167 | ||
168 | /* | |
169 | * Preliminary prescaler for refresh (depends on number of | |
170 | * banks): This value is selected for four cycles every 62.4 us | |
171 | * with two SDRAM banks or four cycles every 31.2 us with one | |
172 | * bank. It will be adjusted after memory sizing. | |
173 | */ | |
6d0f6bcf | 174 | memctl->memc_mptpr = CONFIG_SYS_MPTPR_2BK_8K; |
c609719b WD |
175 | |
176 | memctl->memc_mar = 0x00000088; | |
177 | ||
178 | /* | |
179 | * Map controller banks 2 and 3 to the SDRAM banks 2 and 3 at | |
180 | * preliminary addresses - these have to be modified after the | |
181 | * SDRAM size has been determined. | |
182 | */ | |
6d0f6bcf JCPV |
183 | memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM; |
184 | memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM; | |
c609719b | 185 | |
6d0f6bcf | 186 | memctl->memc_mamr = CONFIG_SYS_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */ |
c609719b WD |
187 | |
188 | udelay(200); | |
189 | ||
190 | /* perform SDRAM initializsation sequence */ | |
191 | ||
192 | memctl->memc_mcr = 0x80004105; /* SDRAM bank 0 */ | |
193 | udelay(1); | |
194 | memctl->memc_mcr = 0x80004230; /* SDRAM bank 0 - execute twice */ | |
195 | udelay(1); | |
196 | ||
197 | memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */ | |
198 | ||
199 | udelay (1000); | |
200 | ||
201 | /* | |
202 | * Check Bank 0 Memory Size for re-configuration | |
203 | * | |
204 | * try 8 column mode | |
205 | */ | |
6d0f6bcf | 206 | size8 = dram_size (CONFIG_SYS_MAMR_8COL, SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE); |
c609719b WD |
207 | |
208 | udelay (1000); | |
209 | ||
210 | /* | |
211 | * try 9 column mode | |
212 | */ | |
6d0f6bcf | 213 | size9 = dram_size (CONFIG_SYS_MAMR_9COL, SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE); |
c609719b WD |
214 | |
215 | if (size8 < size9) { /* leave configuration at 9 columns */ | |
216 | size = size9; | |
217 | /* debug ("SDRAM in 9 column mode: %ld MB\n", size >> 20); */ | |
218 | } else { /* back to 8 columns */ | |
219 | size = size8; | |
6d0f6bcf | 220 | memctl->memc_mamr = CONFIG_SYS_MAMR_8COL; |
c609719b WD |
221 | udelay(500); |
222 | /* debug ("SDRAM in 8 column mode: %ld MB\n", size >> 20); */ | |
223 | } | |
224 | ||
225 | udelay (1000); | |
226 | ||
227 | /* | |
228 | * Adjust refresh rate depending on SDRAM type | |
229 | * For types > 128 MBit leave it at the current (fast) rate | |
230 | */ | |
231 | if (size < 0x02000000) { | |
232 | /* reduce to 15.6 us (62.4 us / quad) */ | |
6d0f6bcf | 233 | memctl->memc_mptpr = CONFIG_SYS_MPTPR_2BK_4K; |
c609719b WD |
234 | udelay(1000); |
235 | } | |
236 | ||
237 | /* | |
238 | * Final mapping | |
239 | */ | |
240 | ||
6d0f6bcf JCPV |
241 | memctl->memc_or2 = ((-size) & 0xFFFF0000) | CONFIG_SYS_OR_TIMING_SDRAM; |
242 | memctl->memc_br2 = (CONFIG_SYS_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; | |
c609719b WD |
243 | |
244 | ||
245 | /* adjust refresh rate depending on SDRAM type, one bank */ | |
246 | reg = memctl->memc_mptpr; | |
6d0f6bcf | 247 | reg >>= 1; /* reduce to CONFIG_SYS_MPTPR_1BK_8K / _4K */ |
c609719b WD |
248 | memctl->memc_mptpr = reg; |
249 | ||
250 | can_driver_enable (); | |
251 | init_leds (); | |
252 | ||
253 | udelay(10000); | |
254 | ||
255 | return (size); | |
256 | } | |
257 | ||
258 | /* ------------------------------------------------------------------------- */ | |
259 | ||
260 | /* | |
261 | * Warning - both the PUMA load mode and the CAN driver use UPM B, | |
262 | * so make sure only one of both is active. | |
263 | */ | |
264 | void can_driver_enable (void) | |
265 | { | |
6d0f6bcf | 266 | volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; |
c609719b WD |
267 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
268 | ||
269 | /* Initialize MBMR */ | |
2535d602 | 270 | memctl->memc_mbmr = MBMR_GPL_B4DIS; /* GPL_B4 ouput line Disable */ |
c609719b WD |
271 | |
272 | /* Initialize UPMB for CAN: single read */ | |
273 | memctl->memc_mdr = 0xFFFFC004; | |
274 | memctl->memc_mcr = 0x0100 | UPMB; | |
275 | ||
276 | memctl->memc_mdr = 0x0FFFD004; | |
277 | memctl->memc_mcr = 0x0101 | UPMB; | |
278 | ||
279 | memctl->memc_mdr = 0x0FFFC000; | |
280 | memctl->memc_mcr = 0x0102 | UPMB; | |
281 | ||
282 | memctl->memc_mdr = 0x3FFFC004; | |
283 | memctl->memc_mcr = 0x0103 | UPMB; | |
284 | ||
285 | memctl->memc_mdr = 0xFFFFDC05; | |
286 | memctl->memc_mcr = 0x0104 | UPMB; | |
287 | ||
288 | /* Initialize UPMB for CAN: single write */ | |
289 | memctl->memc_mdr = 0xFFFCC004; | |
290 | memctl->memc_mcr = 0x0118 | UPMB; | |
291 | ||
292 | memctl->memc_mdr = 0xCFFCD004; | |
293 | memctl->memc_mcr = 0x0119 | UPMB; | |
294 | ||
295 | memctl->memc_mdr = 0x0FFCC000; | |
296 | memctl->memc_mcr = 0x011A | UPMB; | |
297 | ||
298 | memctl->memc_mdr = 0x7FFCC004; | |
299 | memctl->memc_mcr = 0x011B | UPMB; | |
300 | ||
301 | memctl->memc_mdr = 0xFFFDCC05; | |
302 | memctl->memc_mcr = 0x011C | UPMB; | |
303 | ||
304 | /* Initialize OR3 / BR3 for CAN Bus Controller */ | |
6d0f6bcf JCPV |
305 | memctl->memc_or3 = CONFIG_SYS_OR3_CAN; |
306 | memctl->memc_br3 = CONFIG_SYS_BR3_CAN; | |
c609719b WD |
307 | } |
308 | ||
309 | void can_driver_disable (void) | |
310 | { | |
6d0f6bcf | 311 | volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; |
c609719b WD |
312 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
313 | ||
314 | /* Reset OR3 / BR3 to disable CAN Bus Controller */ | |
315 | memctl->memc_br3 = 0; | |
316 | memctl->memc_or3 = 0; | |
317 | ||
318 | memctl->memc_mbmr = 0; | |
319 | } | |
320 | ||
321 | ||
322 | /* ------------------------------------------------------------------------- */ | |
323 | ||
324 | /* | |
325 | * Check memory range for valid RAM. A simple memory test determines | |
326 | * the actually available RAM size between addresses `base' and | |
327 | * `base + maxsize'. Some (not all) hardware errors are detected: | |
328 | * - short between address lines | |
329 | * - short between data lines | |
330 | */ | |
331 | ||
332 | static long int dram_size (long int mamr_value, long int *base, long int maxsize) | |
333 | { | |
6d0f6bcf | 334 | volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; |
c609719b | 335 | volatile memctl8xx_t *memctl = &immap->im_memctl; |
c609719b WD |
336 | |
337 | memctl->memc_mamr = mamr_value; | |
338 | ||
c83bf6a2 | 339 | return (get_ram_size(base, maxsize)); |
c609719b WD |
340 | } |
341 | ||
342 | /* ------------------------------------------------------------------------- */ | |
343 | ||
6d0f6bcf | 344 | #define ETH_CFG_BITS (CONFIG_SYS_PB_ETH_CFG1 | CONFIG_SYS_PB_ETH_CFG2 | CONFIG_SYS_PB_ETH_CFG3 ) |
c609719b | 345 | |
6d0f6bcf | 346 | #define ETH_ALL_BITS (ETH_CFG_BITS | CONFIG_SYS_PB_ETH_POWERDOWN) |
c609719b WD |
347 | |
348 | void reset_phy(void) | |
349 | { | |
6d0f6bcf | 350 | immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; |
c609719b WD |
351 | ulong value; |
352 | ||
353 | /* Configure all needed port pins for GPIO */ | |
6d0f6bcf JCPV |
354 | #ifdef CONFIG_SYS_ETH_MDDIS_VALUE |
355 | immr->im_ioport.iop_padat |= CONFIG_SYS_PA_ETH_MDDIS; | |
c609719b | 356 | #else |
6d0f6bcf | 357 | immr->im_ioport.iop_padat &= ~(CONFIG_SYS_PA_ETH_MDDIS | CONFIG_SYS_PA_ETH_RESET); /* Set low */ |
c609719b | 358 | #endif |
6d0f6bcf JCPV |
359 | immr->im_ioport.iop_papar &= ~(CONFIG_SYS_PA_ETH_MDDIS | CONFIG_SYS_PA_ETH_RESET); /* GPIO */ |
360 | immr->im_ioport.iop_paodr &= ~(CONFIG_SYS_PA_ETH_MDDIS | CONFIG_SYS_PA_ETH_RESET); /* active output */ | |
361 | immr->im_ioport.iop_padir |= CONFIG_SYS_PA_ETH_MDDIS | CONFIG_SYS_PA_ETH_RESET; /* output */ | |
c609719b WD |
362 | |
363 | immr->im_cpm.cp_pbpar &= ~(ETH_ALL_BITS); /* GPIO */ | |
364 | immr->im_cpm.cp_pbodr &= ~(ETH_ALL_BITS); /* active output */ | |
365 | ||
366 | value = immr->im_cpm.cp_pbdat; | |
367 | ||
368 | /* Assert Powerdown and Reset signals */ | |
6d0f6bcf | 369 | value |= CONFIG_SYS_PB_ETH_POWERDOWN; |
c609719b WD |
370 | |
371 | /* PHY configuration includes MDDIS and CFG1 ... CFG3 */ | |
6d0f6bcf JCPV |
372 | #ifdef CONFIG_SYS_ETH_CFG1_VALUE |
373 | value |= CONFIG_SYS_PB_ETH_CFG1; | |
c609719b | 374 | #else |
6d0f6bcf | 375 | value &= ~(CONFIG_SYS_PB_ETH_CFG1); |
c609719b | 376 | #endif |
6d0f6bcf JCPV |
377 | #ifdef CONFIG_SYS_ETH_CFG2_VALUE |
378 | value |= CONFIG_SYS_PB_ETH_CFG2; | |
c609719b | 379 | #else |
6d0f6bcf | 380 | value &= ~(CONFIG_SYS_PB_ETH_CFG2); |
c609719b | 381 | #endif |
6d0f6bcf JCPV |
382 | #ifdef CONFIG_SYS_ETH_CFG3_VALUE |
383 | value |= CONFIG_SYS_PB_ETH_CFG3; | |
c609719b | 384 | #else |
6d0f6bcf | 385 | value &= ~(CONFIG_SYS_PB_ETH_CFG3); |
c609719b WD |
386 | #endif |
387 | ||
388 | /* Drive output signals to initial state */ | |
389 | immr->im_cpm.cp_pbdat = value; | |
390 | immr->im_cpm.cp_pbdir |= ETH_ALL_BITS; | |
391 | udelay (10000); | |
392 | ||
393 | /* De-assert Ethernet Powerdown */ | |
6d0f6bcf | 394 | immr->im_cpm.cp_pbdat &= ~(CONFIG_SYS_PB_ETH_POWERDOWN); /* Enable PHY power */ |
c609719b WD |
395 | udelay (10000); |
396 | ||
397 | /* de-assert RESET signal of PHY */ | |
6d0f6bcf | 398 | immr->im_ioport.iop_padat |= CONFIG_SYS_PA_ETH_RESET; |
c609719b WD |
399 | udelay (1000); |
400 | } | |
401 | ||
402 | ||
403 | int misc_init_r (void) | |
404 | { | |
405 | fpga_init(); | |
406 | return (0); | |
407 | } | |
408 | /* ------------------------------------------------------------------------- */ |