]>
Commit | Line | Data |
---|---|---|
1eac2a71 SR |
1 | /* |
2 | * (C) Copyright 2006 | |
3 | * Stefan Roese, DENX Software Engineering, sr@denx.de. | |
4 | * | |
5 | * Based on original work by | |
6 | * Roel Loeffen, (C) Copyright 2006 Prodrive B.V. | |
7 | * Josh Huber, (C) Copyright 2001 Mission Critical Linux, Inc. | |
8 | * | |
9 | * See file CREDITS for list of people who contributed to this | |
10 | * project. | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or | |
13 | * modify it under the terms of the GNU General Public License as | |
14 | * published by the Free Software Foundation; either version 2 of | |
15 | * the License, or (at your option) any later version. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License | |
23 | * along with this program; if not, write to the Free Software | |
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
25 | * MA 02111-1307 USA | |
26 | * | |
27 | * modifications for the DB64360 eval board based by Ingo.Assmus@keymile.com | |
28 | * modifications for the cpci750 by reinhard.arlt@esd-electronics.com | |
29 | * modifications for the P3M750 by roel.loeffen@prodrive.nl | |
30 | */ | |
31 | ||
32 | /* | |
33 | * p3m750.c - main board support/init for the Prodrive p3m750/p3m7448. | |
34 | */ | |
35 | ||
36 | #include <common.h> | |
37 | #include <74xx_7xx.h> | |
38 | #include "../../Marvell/include/memory.h" | |
39 | #include "../../Marvell/include/pci.h" | |
40 | #include "../../Marvell/include/mv_gen_reg.h" | |
41 | #include <net.h> | |
42 | #include <i2c.h> | |
43 | ||
44 | #include "eth.h" | |
45 | #include "mpsc.h" | |
46 | #include "64460.h" | |
47 | #include "mv_regs.h" | |
0057d758 | 48 | #include "p3mx.h" |
1eac2a71 SR |
49 | |
50 | DECLARE_GLOBAL_DATA_PTR; | |
51 | ||
52 | #undef DEBUG | |
53 | /*#define DEBUG */ | |
54 | ||
55 | #ifdef CONFIG_PCI | |
56 | #define MAP_PCI | |
57 | #endif /* of CONFIG_PCI */ | |
58 | ||
59 | #ifdef DEBUG | |
60 | #define DP(x) x | |
61 | #else | |
62 | #define DP(x) | |
63 | #endif | |
64 | ||
1eac2a71 SR |
65 | extern flash_info_t flash_info[]; |
66 | ||
67 | /* ------------------------------------------------------------------------- */ | |
68 | ||
69 | /* this is the current GT register space location */ | |
6d0f6bcf | 70 | /* it starts at CONFIG_SYS_DFL_GT_REGS but moves later to CONFIG_SYS_GT_REGS */ |
1eac2a71 SR |
71 | |
72 | /* Unfortunately, we cant change it while we are in flash, so we initialize it | |
73 | * to the "final" value. This means that any debug_led calls before | |
74 | * board_early_init_f wont work right (like in cpu_init_f). | |
75 | * See also my_remap_gt_regs below. (NTL) | |
76 | */ | |
77 | ||
78 | void board_prebootm_init (void); | |
6d0f6bcf | 79 | unsigned int INTERNAL_REG_BASE_ADDR = CONFIG_SYS_GT_REGS; |
1eac2a71 | 80 | int display_mem_map (void); |
0057d758 | 81 | void set_led(int); |
1eac2a71 SR |
82 | |
83 | /* ------------------------------------------------------------------------- */ | |
84 | ||
85 | /* | |
86 | * This is a version of the GT register space remapping function that | |
87 | * doesn't touch globals (meaning, it's ok to run from flash.) | |
88 | * | |
89 | * Unfortunately, this has the side effect that a writable | |
90 | * INTERNAL_REG_BASE_ADDR is impossible. Oh well. | |
91 | */ | |
92 | ||
93 | void my_remap_gt_regs (u32 cur_loc, u32 new_loc) | |
94 | { | |
95 | u32 temp; | |
96 | ||
97 | /* check and see if it's already moved */ | |
98 | temp = in_le32 ((u32 *) (new_loc + INTERNAL_SPACE_DECODE)); | |
99 | if ((temp & 0xffff) == new_loc >> 16) | |
100 | return; | |
101 | ||
102 | temp = (in_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE)) & | |
103 | 0xffff0000) | (new_loc >> 16); | |
104 | ||
105 | out_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE), temp); | |
106 | ||
107 | while (GTREGREAD (INTERNAL_SPACE_DECODE) != temp); | |
108 | } | |
109 | ||
110 | #ifdef CONFIG_PCI | |
111 | ||
112 | static void gt_pci_config (void) | |
113 | { | |
114 | unsigned int stat; | |
115 | unsigned int val = 0x00fff864; /* DINK32: BusNum 23:16, DevNum 15:11, */ | |
116 | /* FuncNum 10:8, RegNum 7:2 */ | |
117 | ||
118 | /* | |
119 | * In PCIX mode devices provide their own bus and device numbers. | |
120 | * We query the Discovery II's | |
121 | * config registers by writing ones to the bus and device. | |
122 | * We then update the Virtual register with the correct value for the | |
123 | * bus and device. | |
124 | */ | |
125 | if ((GTREGREAD (PCI_0_MODE) & (BIT4 | BIT5)) != 0) { /* if PCI-X */ | |
126 | GT_REG_WRITE (PCI_0_CONFIG_ADDR, BIT31 | val); | |
127 | ||
128 | GT_REG_READ (PCI_0_CONFIG_DATA_VIRTUAL_REG, &stat); | |
129 | ||
130 | GT_REG_WRITE (PCI_0_CONFIG_ADDR, BIT31 | val); | |
131 | GT_REG_WRITE (PCI_0_CONFIG_DATA_VIRTUAL_REG, | |
6d0f6bcf | 132 | (stat & 0xffff0000) | CONFIG_SYS_PCI_IDSEL); |
1eac2a71 SR |
133 | |
134 | } | |
135 | if ((GTREGREAD (PCI_1_MODE) & (BIT4 | BIT5)) != 0) { /* if PCI-X */ | |
136 | GT_REG_WRITE (PCI_1_CONFIG_ADDR, BIT31 | val); | |
137 | GT_REG_READ (PCI_1_CONFIG_DATA_VIRTUAL_REG, &stat); | |
138 | ||
139 | GT_REG_WRITE (PCI_1_CONFIG_ADDR, BIT31 | val); | |
140 | GT_REG_WRITE (PCI_1_CONFIG_DATA_VIRTUAL_REG, | |
6d0f6bcf | 141 | (stat & 0xffff0000) | CONFIG_SYS_PCI_IDSEL); |
1eac2a71 SR |
142 | } |
143 | ||
144 | /* Enable master */ | |
145 | PCI_MASTER_ENABLE (0, SELF); | |
146 | PCI_MASTER_ENABLE (1, SELF); | |
147 | ||
148 | /* Enable PCI0/1 Mem0 and IO 0 disable all others */ | |
149 | GT_REG_READ (BASE_ADDR_ENABLE, &stat); | |
150 | stat |= (1 << 11) | (1 << 12) | (1 << 13) | (1 << 16) | (1 << 17) | | |
151 | (1 << 18); | |
152 | stat &= ~((1 << 9) | (1 << 10) | (1 << 14) | (1 << 15)); | |
153 | GT_REG_WRITE (BASE_ADDR_ENABLE, stat); | |
154 | ||
155 | /* ronen: | |
156 | * add write to pci remap registers for 64460. | |
157 | * in 64360 when writing to pci base go and overide remap automaticaly, | |
158 | * in 64460 it doesn't | |
159 | */ | |
6d0f6bcf JCPV |
160 | GT_REG_WRITE (PCI_0_IO_BASE_ADDR, CONFIG_SYS_PCI0_IO_SPACE >> 16); |
161 | GT_REG_WRITE (PCI_0I_O_ADDRESS_REMAP, CONFIG_SYS_PCI0_IO_SPACE_PCI >> 16); | |
162 | GT_REG_WRITE (PCI_0_IO_SIZE, (CONFIG_SYS_PCI0_IO_SIZE - 1) >> 16); | |
1eac2a71 | 163 | |
6d0f6bcf JCPV |
164 | GT_REG_WRITE (PCI_0_MEMORY0_BASE_ADDR, CONFIG_SYS_PCI0_MEM_BASE >> 16); |
165 | GT_REG_WRITE (PCI_0MEMORY0_ADDRESS_REMAP, CONFIG_SYS_PCI0_MEM_BASE >> 16); | |
166 | GT_REG_WRITE (PCI_0_MEMORY0_SIZE, (CONFIG_SYS_PCI0_MEM_SIZE - 1) >> 16); | |
1eac2a71 | 167 | |
6d0f6bcf JCPV |
168 | GT_REG_WRITE (PCI_1_IO_BASE_ADDR, CONFIG_SYS_PCI1_IO_SPACE >> 16); |
169 | GT_REG_WRITE (PCI_1I_O_ADDRESS_REMAP, CONFIG_SYS_PCI1_IO_SPACE_PCI >> 16); | |
170 | GT_REG_WRITE (PCI_1_IO_SIZE, (CONFIG_SYS_PCI1_IO_SIZE - 1) >> 16); | |
1eac2a71 | 171 | |
6d0f6bcf JCPV |
172 | GT_REG_WRITE (PCI_1_MEMORY0_BASE_ADDR, CONFIG_SYS_PCI1_MEM_BASE >> 16); |
173 | GT_REG_WRITE (PCI_1MEMORY0_ADDRESS_REMAP, CONFIG_SYS_PCI1_MEM_BASE >> 16); | |
174 | GT_REG_WRITE (PCI_1_MEMORY0_SIZE, (CONFIG_SYS_PCI1_MEM_SIZE - 1) >> 16); | |
1eac2a71 SR |
175 | |
176 | /* PCI interface settings */ | |
177 | /* Timeout set to retry forever */ | |
178 | GT_REG_WRITE (PCI_0TIMEOUT_RETRY, 0x0); | |
179 | GT_REG_WRITE (PCI_1TIMEOUT_RETRY, 0x0); | |
180 | ||
181 | /* ronen - enable only CS0 and Internal reg!! */ | |
182 | GT_REG_WRITE (PCI_0BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe); | |
183 | GT_REG_WRITE (PCI_1BASE_ADDRESS_REGISTERS_ENABLE, 0xfffffdfe); | |
184 | ||
185 | /* ronen: | |
186 | * update the pci internal registers base address. | |
187 | */ | |
188 | #ifdef MAP_PCI | |
189 | for (stat = 0; stat <= PCI_HOST1; stat++) | |
190 | pciWriteConfigReg (stat, | |
191 | PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS, | |
6d0f6bcf | 192 | SELF, CONFIG_SYS_GT_REGS); |
1eac2a71 SR |
193 | #endif |
194 | ||
195 | } | |
196 | #endif | |
197 | ||
198 | /* Setup CPU interface paramaters */ | |
199 | static void gt_cpu_config (void) | |
200 | { | |
201 | cpu_t cpu = get_cpu_type (); | |
202 | ulong tmp; | |
203 | ||
204 | /* cpu configuration register */ | |
205 | tmp = GTREGREAD (CPU_CONFIGURATION); | |
206 | /* set the SINGLE_CPU bit see MV64460 */ | |
6d0f6bcf | 207 | #ifndef CONFIG_SYS_GT_DUAL_CPU /* SINGLE_CPU seems to cause JTAG problems */ |
1eac2a71 SR |
208 | tmp |= CPU_CONF_SINGLE_CPU; |
209 | #endif | |
210 | tmp &= ~CPU_CONF_AACK_DELAY_2; | |
211 | tmp |= CPU_CONF_DP_VALID; | |
212 | tmp |= CPU_CONF_AP_VALID; | |
213 | tmp |= CPU_CONF_PIPELINE; | |
214 | GT_REG_WRITE (CPU_CONFIGURATION, tmp); /* Marvell (VXWorks) writes 0x20220FF */ | |
215 | ||
216 | /* CPU master control register */ | |
217 | tmp = GTREGREAD (CPU_MASTER_CONTROL); | |
218 | tmp |= CPU_MAST_CTL_ARB_EN; | |
219 | ||
220 | if ((cpu == CPU_7400) || | |
221 | (cpu == CPU_7410) || (cpu == CPU_7455) || (cpu == CPU_7450)) { | |
222 | ||
223 | tmp |= CPU_MAST_CTL_CLEAN_BLK; | |
224 | tmp |= CPU_MAST_CTL_FLUSH_BLK; | |
225 | ||
226 | } else { | |
227 | /* cleanblock must be cleared for CPUs | |
228 | * that do not support this command (603e, 750) | |
229 | * see Res#1 */ | |
230 | tmp &= ~CPU_MAST_CTL_CLEAN_BLK; | |
231 | tmp &= ~CPU_MAST_CTL_FLUSH_BLK; | |
232 | } | |
233 | GT_REG_WRITE (CPU_MASTER_CONTROL, tmp); | |
234 | } | |
235 | ||
236 | /* | |
237 | * board_early_init_f. | |
238 | * | |
239 | * set up gal. device mappings, etc. | |
240 | */ | |
241 | int board_early_init_f (void) | |
242 | { | |
243 | /* set up the GT the way the kernel wants it | |
244 | * the call to move the GT register space will obviously | |
245 | * fail if it has already been done, but we're going to assume | |
246 | * that if it's not at the power-on location, it's where we put | |
247 | * it last time. (huber) | |
248 | */ | |
6d0f6bcf | 249 | my_remap_gt_regs (CONFIG_SYS_DFL_GT_REGS, CONFIG_SYS_GT_REGS); |
1eac2a71 SR |
250 | |
251 | #ifdef CONFIG_PCI | |
252 | gt_pci_config (); | |
253 | #endif | |
254 | /* mask all external interrupt sources */ | |
255 | GT_REG_WRITE (CPU_INTERRUPT_MASK_REGISTER_LOW, 0); | |
256 | GT_REG_WRITE (CPU_INTERRUPT_MASK_REGISTER_HIGH, 0); | |
257 | /* new in >MV6436x */ | |
258 | GT_REG_WRITE (CPU_INTERRUPT_1_MASK_REGISTER_LOW, 0); | |
259 | GT_REG_WRITE (CPU_INTERRUPT_1_MASK_REGISTER_HIGH, 0); | |
260 | /* --------------------- */ | |
261 | GT_REG_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0); | |
262 | GT_REG_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0); | |
263 | GT_REG_WRITE (PCI_1INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0); | |
264 | GT_REG_WRITE (PCI_1INTERRUPT_CAUSE_MASK_REGISTER_HIGH, 0); | |
265 | ||
266 | /* Device and Boot bus settings | |
267 | */ | |
268 | memoryMapDeviceSpace(DEVICE0, 0, 0); | |
269 | GT_REG_WRITE(DEVICE_BANK0PARAMETERS, 0); | |
270 | memoryMapDeviceSpace(DEVICE1, 0, 0); | |
271 | GT_REG_WRITE(DEVICE_BANK1PARAMETERS, 0); | |
272 | memoryMapDeviceSpace(DEVICE2, 0, 0); | |
273 | GT_REG_WRITE(DEVICE_BANK2PARAMETERS, 0); | |
274 | memoryMapDeviceSpace(DEVICE3, 0, 0); | |
275 | GT_REG_WRITE(DEVICE_BANK3PARAMETERS, 0); | |
276 | ||
6d0f6bcf | 277 | GT_REG_WRITE(DEVICE_BOOT_BANK_PARAMETERS, CONFIG_SYS_BOOT_PAR); |
1eac2a71 SR |
278 | |
279 | gt_cpu_config(); | |
280 | ||
281 | /* MPP setup */ | |
6d0f6bcf JCPV |
282 | GT_REG_WRITE (MPP_CONTROL0, CONFIG_SYS_MPP_CONTROL_0); |
283 | GT_REG_WRITE (MPP_CONTROL1, CONFIG_SYS_MPP_CONTROL_1); | |
284 | GT_REG_WRITE (MPP_CONTROL2, CONFIG_SYS_MPP_CONTROL_2); | |
285 | GT_REG_WRITE (MPP_CONTROL3, CONFIG_SYS_MPP_CONTROL_3); | |
1eac2a71 | 286 | |
6d0f6bcf | 287 | GT_REG_WRITE (GPP_LEVEL_CONTROL, CONFIG_SYS_GPP_LEVEL_CONTROL); |
1eac2a71 | 288 | |
0057d758 SR |
289 | set_led(LED_RED); |
290 | ||
1eac2a71 SR |
291 | return 0; |
292 | } | |
293 | ||
294 | /* various things to do after relocation */ | |
295 | ||
296 | int misc_init_r () | |
297 | { | |
298 | u8 val; | |
299 | ||
300 | icache_enable (); | |
6d0f6bcf | 301 | #ifdef CONFIG_SYS_L2 |
1eac2a71 SR |
302 | l2cache_enable (); |
303 | #endif | |
304 | #ifdef CONFIG_MPSC | |
305 | mpsc_sdma_init (); | |
306 | mpsc_init2 (); | |
307 | #endif | |
308 | ||
309 | /* | |
310 | * Enable trickle changing in RTC upon powerup | |
311 | * No diode, 250 ohm series resistor | |
312 | */ | |
313 | val = 0xa5; | |
6d0f6bcf | 314 | i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 8, 1, &val, 1); |
1eac2a71 SR |
315 | |
316 | return 0; | |
317 | } | |
318 | ||
319 | int board_early_init_r(void) | |
320 | { | |
321 | /* now relocate the debug serial driver */ | |
322 | mpsc_putchar += gd->reloc_off; | |
323 | mpsc_getchar += gd->reloc_off; | |
324 | mpsc_test_char += gd->reloc_off; | |
325 | ||
326 | return 0; | |
327 | } | |
328 | ||
329 | void after_reloc (ulong dest_addr, gd_t * gd) | |
330 | { | |
6d0f6bcf | 331 | memoryMapDeviceSpace (BOOT_DEVICE, CONFIG_SYS_BOOT_SPACE, CONFIG_SYS_BOOT_SIZE); |
1eac2a71 SR |
332 | |
333 | /* display_mem_map(); */ | |
334 | ||
335 | /* now, jump to the main U-Boot board init code */ | |
0057d758 | 336 | set_led(LED_GREEN); |
1eac2a71 SR |
337 | board_init_r (gd, dest_addr); |
338 | /* NOTREACHED */ | |
339 | } | |
340 | ||
341 | /* | |
342 | * Check Board Identity: | |
343 | * right now, assume borad type. (there is just one...after all) | |
344 | */ | |
345 | ||
346 | int checkboard (void) | |
347 | { | |
348 | char *s = getenv("serial#"); | |
349 | ||
6d0f6bcf | 350 | printf("Board: %s", CONFIG_SYS_BOARD_NAME); |
1eac2a71 SR |
351 | |
352 | if (s != NULL) { | |
353 | puts(", serial# "); | |
354 | puts(s); | |
355 | } | |
356 | putc('\n'); | |
357 | ||
358 | return (0); | |
359 | } | |
360 | ||
0057d758 | 361 | void set_led(int col) |
1eac2a71 | 362 | { |
0057d758 SR |
363 | int tmp; |
364 | int on_pin; | |
365 | int off_pin; | |
366 | ||
367 | /* Program Mpp[22] as Gpp[22] | |
368 | * Program Mpp[23] as Gpp[23] | |
369 | */ | |
370 | tmp = GTREGREAD(MPP_CONTROL2); | |
371 | tmp &= 0x00ffffff; | |
372 | GT_REG_WRITE(MPP_CONTROL2,tmp); | |
373 | ||
374 | /* Program Gpp[22] and Gpp[23] as output | |
375 | */ | |
376 | tmp = GTREGREAD(GPP_IO_CONTROL); | |
377 | tmp |= 0x00C00000; | |
378 | GT_REG_WRITE(GPP_IO_CONTROL, tmp); | |
379 | ||
380 | /* Program Gpp[22] and Gpp[23] as active high | |
381 | */ | |
382 | tmp = GTREGREAD(GPP_LEVEL_CONTROL); | |
383 | tmp &= 0xff3fffff; | |
384 | GT_REG_WRITE(GPP_LEVEL_CONTROL, tmp); | |
385 | ||
386 | switch(col) { | |
387 | default: | |
388 | case LED_OFF : | |
389 | on_pin = 0; | |
390 | off_pin = ((1 << 23) | (1 << 22)); | |
391 | break; | |
392 | case LED_RED : | |
393 | on_pin = (1 << 23); | |
394 | off_pin = (1 << 22); | |
395 | break; | |
396 | case LED_GREEN : | |
397 | on_pin = (1 << 22); | |
398 | off_pin = (1 << 23); | |
399 | break; | |
400 | case LED_ORANGE : | |
401 | on_pin = ((1 << 23) | (1 << 22)); | |
402 | off_pin = 0; | |
403 | break; | |
404 | } | |
405 | ||
406 | /* Set output Gpp[22] and Gpp[23] | |
407 | */ | |
408 | tmp = GTREGREAD(GPP_VALUE); | |
409 | tmp |= on_pin; | |
410 | tmp &= ~off_pin; | |
411 | GT_REG_WRITE(GPP_VALUE, tmp); | |
1eac2a71 SR |
412 | } |
413 | ||
414 | int display_mem_map (void) | |
415 | { | |
0057d758 | 416 | int i; |
1eac2a71 | 417 | unsigned int base, size, width; |
0057d758 SR |
418 | #ifdef CONFIG_PCI |
419 | int j; | |
420 | #endif | |
1eac2a71 SR |
421 | |
422 | /* SDRAM */ | |
423 | printf ("SD (DDR) RAM\n"); | |
424 | for (i = 0; i <= BANK3; i++) { | |
425 | base = memoryGetBankBaseAddress (i); | |
426 | size = memoryGetBankSize (i); | |
427 | if (size != 0) | |
428 | printf ("BANK%d: base - 0x%08x\tsize - %dM bytes\n", | |
429 | i, base, size >> 20); | |
430 | } | |
431 | #ifdef CONFIG_PCI | |
432 | /* CPU's PCI windows */ | |
433 | for (i = 0; i <= PCI_HOST1; i++) { | |
434 | printf ("\nCPU's PCI %d windows\n", i); | |
435 | base = pciGetSpaceBase (i, PCI_IO); | |
436 | size = pciGetSpaceSize (i, PCI_IO); | |
437 | printf (" IO: base - 0x%08x\tsize - %dM bytes\n", base, | |
438 | size >> 20); | |
439 | /* ronen currently only first PCI MEM is used 3 */ | |
440 | for (j = 0; j <= PCI_REGION0; j++) { | |
441 | base = pciGetSpaceBase (i, j); | |
442 | size = pciGetSpaceSize (i, j); | |
443 | printf ("MEMORY %d: base - 0x%08x\tsize - %dM bytes\n", | |
444 | j, base, size >> 20); | |
445 | } | |
446 | } | |
447 | #endif /* of CONFIG_PCI */ | |
448 | ||
449 | /* Bootrom */ | |
450 | base = memoryGetDeviceBaseAddress (BOOT_DEVICE); /* Boot */ | |
451 | size = memoryGetDeviceSize (BOOT_DEVICE); | |
452 | width = memoryGetDeviceWidth (BOOT_DEVICE) * 8; | |
453 | printf (" BOOT: base - 0x%08x size - %dM bytes\twidth - %d bits\t- FLASH\n", | |
454 | base, size >> 20, width); | |
455 | ||
456 | return (0); | |
457 | } | |
458 | ||
459 | /* DRAM check routines copied from gw8260 */ | |
460 | ||
6d0f6bcf | 461 | #if defined (CONFIG_SYS_DRAM_TEST) |
1eac2a71 SR |
462 | |
463 | /*********************************************************************/ | |
464 | /* NAME: move64() - moves a double word (64-bit) */ | |
465 | /* */ | |
466 | /* DESCRIPTION: */ | |
467 | /* this function performs a double word move from the data at */ | |
468 | /* the source pointer to the location at the destination pointer. */ | |
469 | /* */ | |
470 | /* INPUTS: */ | |
471 | /* unsigned long long *src - pointer to data to move */ | |
472 | /* */ | |
473 | /* OUTPUTS: */ | |
474 | /* unsigned long long *dest - pointer to locate to move data */ | |
475 | /* */ | |
476 | /* RETURNS: */ | |
477 | /* None */ | |
478 | /* */ | |
479 | /* RESTRICTIONS/LIMITATIONS: */ | |
480 | /* May cloober fr0. */ | |
481 | /* */ | |
482 | /*********************************************************************/ | |
483 | static void move64 (unsigned long long *src, unsigned long long *dest) | |
484 | { | |
485 | asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ | |
486 | "stfd 0, 0(4)" /* *dest = fpr0 */ | |
487 | : : : "fr0"); /* Clobbers fr0 */ | |
488 | return; | |
489 | } | |
490 | ||
491 | ||
6d0f6bcf | 492 | #if defined (CONFIG_SYS_DRAM_TEST_DATA) |
1eac2a71 SR |
493 | |
494 | unsigned long long pattern[] = { | |
495 | 0xaaaaaaaaaaaaaaaaULL, | |
496 | 0xccccccccccccccccULL, | |
497 | 0xf0f0f0f0f0f0f0f0ULL, | |
498 | 0xff00ff00ff00ff00ULL, | |
499 | 0xffff0000ffff0000ULL, | |
500 | 0xffffffff00000000ULL, | |
501 | 0x00000000ffffffffULL, | |
502 | 0x0000ffff0000ffffULL, | |
503 | 0x00ff00ff00ff00ffULL, | |
504 | 0x0f0f0f0f0f0f0f0fULL, | |
505 | 0x3333333333333333ULL, | |
506 | 0x5555555555555555ULL | |
507 | }; | |
508 | ||
509 | /*********************************************************************/ | |
510 | /* NAME: mem_test_data() - test data lines for shorts and opens */ | |
511 | /* */ | |
512 | /* DESCRIPTION: */ | |
513 | /* Tests data lines for shorts and opens by forcing adjacent data */ | |
514 | /* to opposite states. Because the data lines could be routed in */ | |
515 | /* an arbitrary manner the must ensure test patterns ensure that */ | |
516 | /* every case is tested. By using the following series of binary */ | |
517 | /* patterns every combination of adjacent bits is test regardless */ | |
518 | /* of routing. */ | |
519 | /* */ | |
520 | /* ...101010101010101010101010 */ | |
521 | /* ...110011001100110011001100 */ | |
522 | /* ...111100001111000011110000 */ | |
523 | /* ...111111110000000011111111 */ | |
524 | /* */ | |
525 | /* Carrying this out, gives us six hex patterns as follows: */ | |
526 | /* */ | |
527 | /* 0xaaaaaaaaaaaaaaaa */ | |
528 | /* 0xcccccccccccccccc */ | |
529 | /* 0xf0f0f0f0f0f0f0f0 */ | |
530 | /* 0xff00ff00ff00ff00 */ | |
531 | /* 0xffff0000ffff0000 */ | |
532 | /* 0xffffffff00000000 */ | |
533 | /* */ | |
534 | /* The number test patterns will always be given by: */ | |
535 | /* */ | |
536 | /* log(base 2)(number data bits) = log2 (64) = 6 */ | |
537 | /* */ | |
538 | /* To test for short and opens to other signals on our boards. we */ | |
539 | /* simply */ | |
540 | /* test with the 1's complemnt of the paterns as well. */ | |
541 | /* */ | |
542 | /* OUTPUTS: */ | |
543 | /* Displays failing test pattern */ | |
544 | /* */ | |
545 | /* RETURNS: */ | |
546 | /* 0 - Passed test */ | |
547 | /* 1 - Failed test */ | |
548 | /* */ | |
549 | /* RESTRICTIONS/LIMITATIONS: */ | |
550 | /* Assumes only one one SDRAM bank */ | |
551 | /* */ | |
552 | /*********************************************************************/ | |
553 | int mem_test_data (void) | |
554 | { | |
6d0f6bcf | 555 | unsigned long long *pmem = (unsigned long long *) CONFIG_SYS_MEMTEST_START; |
1eac2a71 SR |
556 | unsigned long long temp64 = 0; |
557 | int num_patterns = sizeof (pattern) / sizeof (pattern[0]); | |
558 | int i; | |
559 | unsigned int hi, lo; | |
560 | ||
561 | for (i = 0; i < num_patterns; i++) { | |
562 | move64 (&(pattern[i]), pmem); | |
563 | move64 (pmem, &temp64); | |
564 | ||
565 | /* hi = (temp64>>32) & 0xffffffff; */ | |
566 | /* lo = temp64 & 0xffffffff; */ | |
567 | /* printf("\ntemp64 = 0x%08x%08x", hi, lo); */ | |
568 | ||
569 | hi = (pattern[i] >> 32) & 0xffffffff; | |
570 | lo = pattern[i] & 0xffffffff; | |
571 | /* printf("\npattern[%d] = 0x%08x%08x", i, hi, lo); */ | |
572 | ||
573 | if (temp64 != pattern[i]) { | |
574 | printf ("\n Data Test Failed, pattern 0x%08x%08x", | |
575 | hi, lo); | |
576 | return 1; | |
577 | } | |
578 | } | |
579 | ||
580 | return 0; | |
581 | } | |
6d0f6bcf | 582 | #endif /* CONFIG_SYS_DRAM_TEST_DATA */ |
1eac2a71 | 583 | |
6d0f6bcf | 584 | #if defined (CONFIG_SYS_DRAM_TEST_ADDRESS) |
1eac2a71 SR |
585 | /*********************************************************************/ |
586 | /* NAME: mem_test_address() - test address lines */ | |
587 | /* */ | |
588 | /* DESCRIPTION: */ | |
589 | /* This function performs a test to verify that each word im */ | |
590 | /* memory is uniquly addressable. The test sequence is as follows: */ | |
591 | /* */ | |
592 | /* 1) write the address of each word to each word. */ | |
593 | /* 2) verify that each location equals its address */ | |
594 | /* */ | |
595 | /* OUTPUTS: */ | |
596 | /* Displays failing test pattern and address */ | |
597 | /* */ | |
598 | /* RETURNS: */ | |
599 | /* 0 - Passed test */ | |
600 | /* 1 - Failed test */ | |
601 | /* */ | |
602 | /* RESTRICTIONS/LIMITATIONS: */ | |
603 | /* */ | |
604 | /* */ | |
605 | /*********************************************************************/ | |
606 | int mem_test_address (void) | |
607 | { | |
608 | volatile unsigned int *pmem = | |
6d0f6bcf JCPV |
609 | (volatile unsigned int *) CONFIG_SYS_MEMTEST_START; |
610 | const unsigned int size = (CONFIG_SYS_MEMTEST_END - CONFIG_SYS_MEMTEST_START) / 4; | |
1eac2a71 SR |
611 | unsigned int i; |
612 | ||
613 | /* write address to each location */ | |
614 | for (i = 0; i < size; i++) | |
615 | pmem[i] = i; | |
616 | ||
617 | /* verify each loaction */ | |
618 | for (i = 0; i < size; i++) { | |
619 | if (pmem[i] != i) { | |
620 | printf ("\n Address Test Failed at 0x%x", i); | |
621 | return 1; | |
622 | } | |
623 | } | |
624 | return 0; | |
625 | } | |
6d0f6bcf | 626 | #endif /* CONFIG_SYS_DRAM_TEST_ADDRESS */ |
1eac2a71 | 627 | |
6d0f6bcf | 628 | #if defined (CONFIG_SYS_DRAM_TEST_WALK) |
1eac2a71 SR |
629 | /*********************************************************************/ |
630 | /* NAME: mem_march() - memory march */ | |
631 | /* */ | |
632 | /* DESCRIPTION: */ | |
633 | /* Marches up through memory. At each location verifies rmask if */ | |
634 | /* read = 1. At each location write wmask if write = 1. Displays */ | |
635 | /* failing address and pattern. */ | |
636 | /* */ | |
637 | /* INPUTS: */ | |
638 | /* volatile unsigned long long * base - start address of test */ | |
639 | /* unsigned int size - number of dwords(64-bit) to test */ | |
640 | /* unsigned long long rmask - read verify mask */ | |
641 | /* unsigned long long wmask - wrtie verify mask */ | |
642 | /* short read - verifies rmask if read = 1 */ | |
643 | /* short write - writes wmask if write = 1 */ | |
644 | /* */ | |
645 | /* OUTPUTS: */ | |
646 | /* Displays failing test pattern and address */ | |
647 | /* */ | |
648 | /* RETURNS: */ | |
649 | /* 0 - Passed test */ | |
650 | /* 1 - Failed test */ | |
651 | /* */ | |
652 | /* RESTRICTIONS/LIMITATIONS: */ | |
653 | /* */ | |
654 | /* */ | |
655 | /*********************************************************************/ | |
656 | int mem_march (volatile unsigned long long *base, | |
657 | unsigned int size, | |
658 | unsigned long long rmask, | |
659 | unsigned long long wmask, short read, short write) | |
660 | { | |
661 | unsigned int i; | |
662 | unsigned long long temp = 0; | |
663 | unsigned int hitemp, lotemp, himask, lomask; | |
664 | ||
665 | for (i = 0; i < size; i++) { | |
666 | if (read != 0) { | |
667 | /* temp = base[i]; */ | |
668 | move64 ((unsigned long long *) &(base[i]), &temp); | |
669 | if (rmask != temp) { | |
670 | hitemp = (temp >> 32) & 0xffffffff; | |
671 | lotemp = temp & 0xffffffff; | |
672 | himask = (rmask >> 32) & 0xffffffff; | |
673 | lomask = rmask & 0xffffffff; | |
674 | ||
675 | printf ("\n Walking one's test failed: address = 0x%08x," "\n\texpected 0x%08x%08x, found 0x%08x%08x", i << 3, himask, lomask, hitemp, lotemp); | |
676 | return 1; | |
677 | } | |
678 | } | |
679 | if (write != 0) { | |
680 | /* base[i] = wmask; */ | |
681 | move64 (&wmask, (unsigned long long *) &(base[i])); | |
682 | } | |
683 | } | |
684 | return 0; | |
685 | } | |
6d0f6bcf | 686 | #endif /* CONFIG_SYS_DRAM_TEST_WALK */ |
1eac2a71 SR |
687 | |
688 | /*********************************************************************/ | |
689 | /* NAME: mem_test_walk() - a simple walking ones test */ | |
690 | /* */ | |
691 | /* DESCRIPTION: */ | |
692 | /* Performs a walking ones through entire physical memory. The */ | |
693 | /* test uses as series of memory marches, mem_march(), to verify */ | |
694 | /* and write the test patterns to memory. The test sequence is as */ | |
695 | /* follows: */ | |
696 | /* 1) march writing 0000...0001 */ | |
697 | /* 2) march verifying 0000...0001 , writing 0000...0010 */ | |
698 | /* 3) repeat step 2 shifting masks left 1 bit each time unitl */ | |
699 | /* the write mask equals 1000...0000 */ | |
700 | /* 4) march verifying 1000...0000 */ | |
701 | /* The test fails if any of the memory marches return a failure. */ | |
702 | /* */ | |
703 | /* OUTPUTS: */ | |
704 | /* Displays which pass on the memory test is executing */ | |
705 | /* */ | |
706 | /* RETURNS: */ | |
707 | /* 0 - Passed test */ | |
708 | /* 1 - Failed test */ | |
709 | /* */ | |
710 | /* RESTRICTIONS/LIMITATIONS: */ | |
711 | /* */ | |
712 | /* */ | |
713 | /*********************************************************************/ | |
714 | int mem_test_walk (void) | |
715 | { | |
716 | unsigned long long mask; | |
717 | volatile unsigned long long *pmem = | |
6d0f6bcf JCPV |
718 | (volatile unsigned long long *) CONFIG_SYS_MEMTEST_START; |
719 | const unsigned long size = (CONFIG_SYS_MEMTEST_END - CONFIG_SYS_MEMTEST_START) / 8; | |
1eac2a71 SR |
720 | |
721 | unsigned int i; | |
722 | ||
723 | mask = 0x01; | |
724 | ||
725 | printf ("Initial Pass"); | |
726 | mem_march (pmem, size, 0x0, 0x1, 0, 1); | |
727 | ||
728 | printf ("\b\b\b\b\b\b\b\b\b\b\b\b"); | |
729 | printf (" "); | |
730 | printf (" "); | |
731 | printf ("\b\b\b\b\b\b\b\b\b\b\b\b"); | |
732 | ||
733 | for (i = 0; i < 63; i++) { | |
734 | printf ("Pass %2d", i + 2); | |
735 | if (mem_march (pmem, size, mask, mask << 1, 1, 1) != 0) { | |
736 | /*printf("mask: 0x%x, pass: %d, ", mask, i); */ | |
737 | return 1; | |
738 | } | |
739 | mask = mask << 1; | |
740 | printf ("\b\b\b\b\b\b\b"); | |
741 | } | |
742 | ||
743 | printf ("Last Pass"); | |
744 | if (mem_march (pmem, size, 0, mask, 0, 1) != 0) { | |
745 | /* printf("mask: 0x%x", mask); */ | |
746 | return 1; | |
747 | } | |
748 | printf ("\b\b\b\b\b\b\b\b\b"); | |
749 | printf (" "); | |
750 | printf ("\b\b\b\b\b\b\b\b\b"); | |
751 | ||
752 | return 0; | |
753 | } | |
754 | ||
755 | /*********************************************************************/ | |
756 | /* NAME: testdram() - calls any enabled memory tests */ | |
757 | /* */ | |
758 | /* DESCRIPTION: */ | |
759 | /* Runs memory tests if the environment test variables are set to */ | |
760 | /* 'y'. */ | |
761 | /* */ | |
762 | /* INPUTS: */ | |
763 | /* testdramdata - If set to 'y', data test is run. */ | |
764 | /* testdramaddress - If set to 'y', address test is run. */ | |
765 | /* testdramwalk - If set to 'y', walking ones test is run */ | |
766 | /* */ | |
767 | /* OUTPUTS: */ | |
768 | /* None */ | |
769 | /* */ | |
770 | /* RETURNS: */ | |
771 | /* 0 - Passed test */ | |
772 | /* 1 - Failed test */ | |
773 | /* */ | |
774 | /* RESTRICTIONS/LIMITATIONS: */ | |
775 | /* */ | |
776 | /* */ | |
777 | /*********************************************************************/ | |
778 | int testdram (void) | |
779 | { | |
780 | char *s; | |
781 | int rundata = 0; | |
782 | int runaddress = 0; | |
783 | int runwalk = 0; | |
784 | ||
6d0f6bcf | 785 | #ifdef CONFIG_SYS_DRAM_TEST_DATA |
1eac2a71 SR |
786 | s = getenv ("testdramdata"); |
787 | rundata = (s && (*s == 'y')) ? 1 : 0; | |
788 | #endif | |
6d0f6bcf | 789 | #ifdef CONFIG_SYS_DRAM_TEST_ADDRESS |
1eac2a71 SR |
790 | s = getenv ("testdramaddress"); |
791 | runaddress = (s && (*s == 'y')) ? 1 : 0; | |
792 | #endif | |
6d0f6bcf | 793 | #ifdef CONFIG_SYS_DRAM_TEST_WALK |
1eac2a71 SR |
794 | s = getenv ("testdramwalk"); |
795 | runwalk = (s && (*s == 'y')) ? 1 : 0; | |
796 | #endif | |
797 | ||
798 | if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) | |
799 | printf ("Testing RAM from 0x%08x to 0x%08x ... " | |
800 | "(don't panic... that will take a moment !!!!)\n", | |
6d0f6bcf JCPV |
801 | CONFIG_SYS_MEMTEST_START, CONFIG_SYS_MEMTEST_END); |
802 | #ifdef CONFIG_SYS_DRAM_TEST_DATA | |
1eac2a71 SR |
803 | if (rundata == 1) { |
804 | printf ("Test DATA ... "); | |
805 | if (mem_test_data () == 1) { | |
806 | printf ("failed \n"); | |
807 | return 1; | |
808 | } else | |
809 | printf ("ok \n"); | |
810 | } | |
811 | #endif | |
6d0f6bcf | 812 | #ifdef CONFIG_SYS_DRAM_TEST_ADDRESS |
1eac2a71 SR |
813 | if (runaddress == 1) { |
814 | printf ("Test ADDRESS ... "); | |
815 | if (mem_test_address () == 1) { | |
816 | printf ("failed \n"); | |
817 | return 1; | |
818 | } else | |
819 | printf ("ok \n"); | |
820 | } | |
821 | #endif | |
6d0f6bcf | 822 | #ifdef CONFIG_SYS_DRAM_TEST_WALK |
1eac2a71 SR |
823 | if (runwalk == 1) { |
824 | printf ("Test WALKING ONEs ... "); | |
825 | if (mem_test_walk () == 1) { | |
826 | printf ("failed \n"); | |
827 | return 1; | |
828 | } else | |
829 | printf ("ok \n"); | |
830 | } | |
831 | #endif | |
832 | if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) | |
833 | printf ("passed\n"); | |
834 | return 0; | |
835 | ||
836 | } | |
6d0f6bcf | 837 | #endif /* CONFIG_SYS_DRAM_TEST */ |
1eac2a71 SR |
838 | |
839 | /* ronen - the below functions are used by the bootm function */ | |
840 | /* - we map the base register to fbe00000 (same mapping as in the LSP) */ | |
841 | /* - we turn off the RX gig dmas - to prevent the dma from overunning */ | |
842 | /* the kernel data areas. */ | |
843 | /* - we diable and invalidate the icache and dcache. */ | |
844 | void my_remap_gt_regs_bootm (u32 cur_loc, u32 new_loc) | |
845 | { | |
846 | u32 temp; | |
847 | ||
848 | temp = in_le32 ((u32 *) (new_loc + INTERNAL_SPACE_DECODE)); | |
849 | if ((temp & 0xffff) == new_loc >> 16) | |
850 | return; | |
851 | ||
852 | temp = (in_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE)) & | |
853 | 0xffff0000) | (new_loc >> 16); | |
854 | ||
855 | out_le32 ((u32 *) (cur_loc + INTERNAL_SPACE_DECODE), temp); | |
856 | ||
857 | while ((WORD_SWAP (*((volatile unsigned int *) (NONE_CACHEABLE | | |
858 | new_loc | | |
859 | (INTERNAL_SPACE_DECODE))))) | |
860 | != temp); | |
861 | ||
862 | } |