]>
Commit | Line | Data |
---|---|---|
1eac2a71 SR |
1 | /* |
2 | * (C) Copyright 2001 | |
3 | * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. | |
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 | |
8d9a8610 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1eac2a71 SR |
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 | /************************************************************************* | |
25 | * adaption for the Marvell DB64460 Board | |
26 | * Ingo Assmus (ingo.assmus@keymile.com) | |
27 | *************************************************************************/ | |
28 | ||
29 | /* sdram_init.c - automatic memory sizing */ | |
30 | ||
31 | #include <common.h> | |
32 | #include <74xx_7xx.h> | |
33 | #include "../../Marvell/include/memory.h" | |
34 | #include "../../Marvell/include/pci.h" | |
35 | #include "../../Marvell/include/mv_gen_reg.h" | |
36 | #include <net.h> | |
37 | ||
38 | #include "eth.h" | |
39 | #include "mpsc.h" | |
40 | #include "../../Marvell/common/i2c.h" | |
41 | #include "64460.h" | |
42 | #include "mv_regs.h" | |
43 | ||
44 | DECLARE_GLOBAL_DATA_PTR; | |
45 | ||
46 | #undef DEBUG | |
8d9a8610 | 47 | #define MAP_PCI |
1eac2a71 SR |
48 | |
49 | #ifdef DEBUG | |
50 | #define DP(x) x | |
51 | #else | |
52 | #define DP(x) | |
53 | #endif | |
54 | ||
55 | int set_dfcdlInit (void); /* setup delay line of Mv64460 */ | |
56 | int mvDmaIsChannelActive (int); | |
57 | int mvDmaSetMemorySpace (ulong, ulong, ulong, ulong, ulong); | |
58 | int mvDmaTransfer (int, ulong, ulong, ulong, ulong); | |
59 | ||
60 | #define D_CACHE_FLUSH_LINE(addr, offset) \ | |
61 | { \ | |
62 | __asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \ | |
63 | } | |
64 | ||
65 | int memory_map_bank (unsigned int bankNo, | |
66 | unsigned int bankBase, unsigned int bankLength) | |
67 | { | |
0057d758 | 68 | #if defined (MAP_PCI) && defined (CONFIG_PCI) |
1eac2a71 SR |
69 | PCI_HOST host; |
70 | #endif | |
71 | ||
72 | #ifdef DEBUG | |
8d9a8610 | 73 | if (bankLength > 0) { |
1eac2a71 SR |
74 | printf ("mapping bank %d at %08x - %08x\n", |
75 | bankNo, bankBase, bankBase + bankLength - 1); | |
8d9a8610 | 76 | } else { |
1eac2a71 | 77 | printf ("unmapping bank %d\n", bankNo); |
8d9a8610 | 78 | } |
1eac2a71 SR |
79 | #endif |
80 | ||
81 | memoryMapBank (bankNo, bankBase, bankLength); | |
82 | ||
0057d758 | 83 | #if defined (MAP_PCI) && defined (CONFIG_PCI) |
1eac2a71 SR |
84 | for (host = PCI_HOST0; host <= PCI_HOST1; host++) { |
85 | const int features = | |
86 | PREFETCH_ENABLE | | |
87 | DELAYED_READ_ENABLE | | |
88 | AGGRESSIVE_PREFETCH | | |
89 | READ_LINE_AGGRESSIVE_PREFETCH | | |
90 | READ_MULTI_AGGRESSIVE_PREFETCH | | |
91 | MAX_BURST_4 | PCI_NO_SWAP; | |
92 | ||
93 | pciMapMemoryBank (host, bankNo, bankBase, bankLength); | |
94 | ||
95 | pciSetRegionSnoopMode (host, bankNo, PCI_SNOOP_WB, bankBase, | |
96 | bankLength); | |
97 | ||
98 | pciSetRegionFeatures (host, bankNo, features, bankBase, | |
99 | bankLength); | |
100 | } | |
101 | #endif | |
102 | ||
103 | return 0; | |
104 | } | |
105 | ||
106 | /* | |
107 | * Check memory range for valid RAM. A simple memory test determines | |
108 | * the actually available RAM size between addresses `base' and | |
109 | * `base + maxsize'. Some (not all) hardware errors are detected: | |
110 | * - short between address lines | |
111 | * - short between data lines | |
112 | */ | |
113 | long int dram_size (long int *base, long int maxsize) | |
114 | { | |
115 | volatile long int *addr, *b = base; | |
116 | long int cnt, val, save1, save2; | |
117 | ||
118 | #define STARTVAL (1<<20) /* start test at 1M */ | |
119 | for (cnt = STARTVAL / sizeof (long); cnt < maxsize / sizeof (long); | |
120 | cnt <<= 1) { | |
121 | addr = base + cnt; /* pointer arith! */ | |
122 | ||
123 | save1 = *addr; /* save contents of addr */ | |
124 | save2 = *b; /* save contents of base */ | |
125 | ||
126 | *addr = cnt; /* write cnt to addr */ | |
127 | *b = 0; /* put null at base */ | |
128 | ||
129 | /* check at base address */ | |
130 | if ((*b) != 0) { | |
131 | *addr = save1; /* restore *addr */ | |
132 | *b = save2; /* restore *b */ | |
133 | return (0); | |
134 | } | |
135 | val = *addr; /* read *addr */ | |
136 | val = *addr; /* read *addr */ | |
137 | ||
138 | *addr = save1; | |
139 | *b = save2; | |
140 | ||
141 | if (val != cnt) { | |
142 | DP (printf | |
143 | ("Found %08x at Address %08x (failure)\n", | |
144 | (unsigned int) val, (unsigned int) addr)); | |
145 | /* fix boundary condition.. STARTVAL means zero */ | |
146 | if (cnt == STARTVAL / sizeof (long)) | |
147 | cnt = 0; | |
148 | return (cnt * sizeof (long)); | |
149 | } | |
150 | } | |
151 | ||
152 | return maxsize; | |
153 | } | |
154 | ||
155 | #define SDRAM_NORMAL 0x0 | |
156 | #define SDRAM_PRECHARGE_ALL 0x1 | |
157 | #define SDRAM_REFRESH_ALL 0x2 | |
158 | #define SDRAM_MODE_REG_SETUP 0x3 | |
159 | #define SDRAM_XTEN_MODE_REG_SETUP 0x4 | |
160 | #define SDRAM_NOP 0x5 | |
161 | #define SDRAM_SELF_REFRESH 0x7 | |
162 | ||
9973e3c6 | 163 | phys_size_t initdram (int board_type) |
1eac2a71 SR |
164 | { |
165 | int tmp; | |
166 | int start; | |
167 | ulong size; | |
168 | ulong memSpaceAttr; | |
169 | ulong dest; | |
170 | ||
171 | /* first disable all banks */ | |
172 | memory_map_bank(0, 0, 0); | |
173 | memory_map_bank(1, 0, 0); | |
174 | memory_map_bank(2, 0, 0); | |
175 | memory_map_bank(3, 0, 0); | |
176 | ||
177 | /* calibrate delay lines */ | |
178 | set_dfcdlInit(); | |
179 | ||
8d9a8610 | 180 | GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP); /* 0x1418 */ |
1eac2a71 SR |
181 | do { |
182 | tmp = GTREGREAD(MV64460_SDRAM_OPERATION); | |
183 | } while(tmp != 0x0); | |
184 | ||
185 | /* SDRAM controller configuration */ | |
186 | #ifdef CONFIG_MV64460_ECC | |
187 | GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58201400); /* 0x1400 */ | |
188 | #else | |
189 | GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58200400); /* 0x1400 */ | |
190 | #endif | |
191 | GT_REG_WRITE(MV64460_D_UNIT_CONTROL_LOW, 0xC3000540); /* 0x1404 */ | |
192 | GT_REG_WRITE(MV64460_D_UNIT_CONTROL_HIGH, 0x0300F777); /* 0x1424 */ | |
193 | GT_REG_WRITE(MV64460_SDRAM_TIMING_CONTROL_LOW, 0x01712220); /* 0x1408 */ | |
194 | GT_REG_WRITE(MV64460_SDRAM_TIMING_CONTROL_HIGH, 0x0000005D); /* 0x140C */ | |
195 | GT_REG_WRITE(MV64460_SDRAM_ADDR_CONTROL, 0x00000012); /* 0x1410 */ | |
196 | GT_REG_WRITE(MV64460_SDRAM_OPEN_PAGES_CONTROL, 0x00000001); /* 0x1414 */ | |
197 | ||
198 | /* SDRAM drive strength */ | |
199 | GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000000); /* 0x14C0 */ | |
200 | GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000008); /* 0x14C0 */ | |
8d9a8610 WD |
201 | GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000000); /* 0x14C4 */ |
202 | GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000008); /* 0x14C4 */ | |
1eac2a71 SR |
203 | |
204 | /* setup SDRAM device registers */ | |
205 | ||
206 | /* precharge all */ | |
207 | GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */ | |
208 | do { | |
209 | tmp = GTREGREAD(MV64460_SDRAM_OPERATION); | |
210 | } while(tmp != 0x0); | |
211 | ||
212 | /* enable DLL */ | |
213 | GT_REG_WRITE(MV64460_EXTENDED_DRAM_MODE, 0x00000000); /* 0x1420 */ | |
214 | GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_XTEN_MODE_REG_SETUP); /* 0x1418 */ | |
215 | do { | |
216 | tmp = GTREGREAD(MV64460_SDRAM_OPERATION); | |
217 | } while(tmp != 0x0); | |
218 | ||
219 | /* reset DLL */ | |
220 | GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000132); /* 0x141C */ | |
221 | GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */ | |
222 | do { | |
223 | tmp = GTREGREAD(MV64460_SDRAM_OPERATION); | |
224 | } while(tmp != 0x0); | |
225 | ||
226 | /* precharge all */ | |
227 | GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */ | |
228 | do { | |
229 | tmp = GTREGREAD(MV64460_SDRAM_OPERATION); | |
230 | } while(tmp != 0x0); | |
231 | ||
232 | /* wait for 2 auto refresh commands */ | |
233 | udelay(20); | |
234 | ||
235 | /* un-reset DLL */ | |
236 | GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000032); /* 0x141C */ | |
237 | GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */ | |
238 | do { | |
239 | tmp = GTREGREAD(MV64460_SDRAM_OPERATION); | |
240 | } while(tmp != 0x0); | |
241 | ||
242 | /* wait 200 cycles */ | |
243 | udelay(2); /* FIXME make this dynamic for the system clock */ | |
244 | ||
245 | /* SDRAM init done */ | |
6d0f6bcf JCPV |
246 | memory_map_bank(0, CONFIG_SYS_SDRAM_BASE, (256 << 20)); |
247 | #ifdef CONFIG_SYS_SDRAM1_BASE | |
248 | memory_map_bank(1, CONFIG_SYS_SDRAM1_BASE, (256 << 20)); | |
1eac2a71 SR |
249 | #endif |
250 | ||
251 | /* DUNIT_MMASK: enable SnoopHitEn bit to avoid errata CPU-#4 | |
252 | */ | |
253 | tmp = GTREGREAD(MV64460_D_UNIT_MMASK); /* 0x14B0 */ | |
254 | GT_REG_WRITE(MV64460_D_UNIT_MMASK, tmp | 0x2); | |
255 | ||
256 | start = (0 << 20); | |
257 | #ifdef CONFIG_P3M750 | |
258 | size = (512 << 20); | |
259 | #elif defined (CONFIG_P3M7448) | |
260 | size = (128 << 20); | |
261 | #endif | |
262 | ||
263 | #ifdef CONFIG_MV64460_ECC | |
264 | memSpaceAttr = ((~(BIT0 << 0)) & 0xf) << 8; | |
265 | mvDmaSetMemorySpace (0, 0, memSpaceAttr, start, size); | |
266 | for (dest = start; dest < start + size; dest += _8M) { | |
267 | mvDmaTransfer (0, start, dest, _8M, | |
268 | BIT8 /*DMA_DTL_128BYTES */ | | |
269 | BIT3 /*DMA_HOLD_SOURCE_ADDR */ | | |
270 | BIT11 /*DMA_BLOCK_TRANSFER_MODE */ ); | |
271 | while (mvDmaIsChannelActive (0)); | |
272 | } | |
273 | #endif | |
274 | ||
275 | return (size); | |
276 | } | |
277 | ||
278 | void board_add_ram_info(int use_default) | |
279 | { | |
280 | u32 val; | |
281 | ||
282 | puts(" (CL="); | |
283 | switch ((GTREGREAD(MV64460_SDRAM_MODE) >> 4) & 0x7) { | |
284 | case 0x2: | |
285 | puts("2"); | |
286 | break; | |
287 | case 0x3: | |
288 | puts("3"); | |
289 | break; | |
290 | case 0x5: | |
291 | puts("1.5"); | |
292 | break; | |
293 | case 0x6: | |
294 | puts("2.5"); | |
295 | break; | |
296 | } | |
297 | ||
298 | val = GTREGREAD(MV64460_SDRAM_CONFIG); | |
299 | ||
300 | puts(", ECC "); | |
301 | if (val & 0x00001000) | |
302 | puts("enabled)"); | |
303 | else | |
304 | puts("not enabled)"); | |
305 | } | |
306 | ||
307 | /* | |
308 | * mvDmaIsChannelActive - Check if IDMA channel is active | |
309 | * | |
8d9a8610 | 310 | * channel = IDMA channel number from 0 to 7 |
1eac2a71 SR |
311 | */ |
312 | int mvDmaIsChannelActive (int channel) | |
313 | { | |
8d9a8610 | 314 | ulong data; |
1eac2a71 | 315 | |
8d9a8610 WD |
316 | data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel); |
317 | if (data & BIT14) /* activity status */ | |
318 | return 1; | |
1eac2a71 | 319 | |
8d9a8610 | 320 | return 0; |
1eac2a71 SR |
321 | } |
322 | ||
323 | /* | |
324 | * mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding | |
8d9a8610 | 325 | * map. |
1eac2a71 SR |
326 | * |
327 | * memSpace = IDMA memory window number from 0 to 7 | |
328 | * trg_if = Target interface: | |
329 | * 0x0 DRAM | |
330 | * 0x1 Device Bus | |
331 | * 0x2 Integrated SDRAM (or CPU bus 60x only) | |
332 | * 0x3 PCI0 | |
333 | * 0x4 PCI1 | |
334 | * attr = IDMA attributes (see MV datasheet) | |
335 | * base_addr = Sets up memory window for transfers | |
336 | * | |
337 | */ | |
338 | int mvDmaSetMemorySpace (ulong memSpace, | |
339 | ulong trg_if, | |
340 | ulong attr, ulong base_addr, ulong size) | |
341 | { | |
342 | ulong temp; | |
343 | ||
344 | /* The base address must be aligned to the size. */ | |
345 | if (base_addr % size != 0) | |
346 | return 0; | |
347 | ||
348 | if (size >= 0x10000) { /* 64K */ | |
349 | size &= 0xffff0000; | |
350 | base_addr = (base_addr & 0xffff0000); | |
351 | /* Set the new attributes */ | |
352 | GT_REG_WRITE (MV64460_DMA_BASE_ADDR_REG0 + memSpace * 8, | |
353 | (base_addr | trg_if | attr)); | |
354 | GT_REG_WRITE ((MV64460_DMA_SIZE_REG0 + memSpace * 8), | |
355 | (size - 1) & 0xffff0000); | |
356 | temp = GTREGREAD (MV64460_DMA_BASE_ADDR_ENABLE_REG); | |
357 | GT_REG_WRITE (DMA_BASE_ADDR_ENABLE_REG, | |
358 | (temp & ~(BIT0 << memSpace))); | |
359 | return 1; | |
360 | } | |
361 | ||
362 | return 0; | |
363 | } | |
364 | ||
365 | /* | |
366 | * mvDmaTransfer - Transfer data from src_addr to dst_addr on one of the 4 | |
8d9a8610 | 367 | * DMA channels. |
1eac2a71 | 368 | * |
8d9a8610 | 369 | * channel = IDMA channel number from 0 to 3 |
1eac2a71 SR |
370 | * destAddr = Destination address |
371 | * sourceAddr = Source address | |
372 | * size = Size in bytes | |
373 | * command = See MV datasheet | |
374 | * | |
375 | */ | |
376 | int mvDmaTransfer (int channel, ulong sourceAddr, | |
377 | ulong destAddr, ulong size, ulong command) | |
378 | { | |
379 | ulong engOffReg = 0; /* Engine Offset Register */ | |
380 | ||
381 | if (size > 0xffff) | |
382 | command = command | BIT31; /* DMA_16M_DESCRIPTOR_MODE */ | |
383 | command = command | ((command >> 6) & 0x7); | |
384 | engOffReg = channel * 4; | |
385 | GT_REG_WRITE (MV64460_DMA_CHANNEL0_BYTE_COUNT + engOffReg, size); | |
386 | GT_REG_WRITE (MV64460_DMA_CHANNEL0_SOURCE_ADDR + engOffReg, sourceAddr); | |
387 | GT_REG_WRITE (MV64460_DMA_CHANNEL0_DESTINATION_ADDR + engOffReg, destAddr); | |
388 | command = command | | |
8d9a8610 | 389 | BIT12 | /* DMA_CHANNEL_ENABLE */ |
1eac2a71 SR |
390 | BIT9; /* DMA_NON_CHAIN_MODE */ |
391 | /* Activate DMA channel By writting to mvDmaControlRegister */ | |
392 | GT_REG_WRITE (MV64460_DMA_CHANNEL0_CONTROL + engOffReg, command); | |
393 | return 1; | |
394 | } | |
395 | ||
396 | /**************************************************************************************** | |
397 | * SDRAM INIT * | |
398 | * This procedure detect all Sdram types: 64, 128, 256, 512 Mbit, 1Gbit and 2Gb * | |
399 | * This procedure fits only the Atlantis * | |
400 | * * | |
401 | ***************************************************************************************/ | |
402 | ||
403 | /**************************************************************************************** | |
404 | * DFCDL initialize MV643xx Design Considerations * | |
405 | * * | |
406 | ***************************************************************************************/ | |
407 | int set_dfcdlInit (void) | |
408 | { | |
409 | int i; | |
410 | ||
411 | /* Values from MV64460 User Manual */ | |
412 | unsigned int dfcdl_tbl[] = { 0x00000000, 0x00000001, 0x00000042, 0x00000083, | |
413 | 0x000000c4, 0x00000105, 0x00000146, 0x00000187, | |
414 | 0x000001c8, 0x00000209, 0x0000024a, 0x0000028b, | |
415 | 0x000002cc, 0x0000030d, 0x0000034e, 0x0000038f, | |
416 | 0x000003d0, 0x00000411, 0x00000452, 0x00000493, | |
417 | 0x000004d4, 0x00000515, 0x00000556, 0x00000597, | |
418 | 0x000005d8, 0x00000619, 0x0000065a, 0x0000069b, | |
419 | 0x000006dc, 0x0000071d, 0x0000075e, 0x0000079f, | |
420 | 0x000007e0, 0x00000821, 0x00000862, 0x000008a3, | |
421 | 0x000008e4, 0x00000925, 0x00000966, 0x000009a7, | |
422 | 0x000009e8, 0x00000a29, 0x00000a6a, 0x00000aab, | |
423 | 0x00000aec, 0x00000b2d, 0x00000b6e, 0x00000baf, | |
424 | 0x00000bf0, 0x00000c31, 0x00000c72, 0x00000cb3, | |
425 | 0x00000cf4, 0x00000d35, 0x00000d76, 0x00000db7, | |
426 | 0x00000df8, 0x00000e39, 0x00000e7a, 0x00000ebb, | |
427 | 0x00000efc, 0x00000f3d, 0x00000f7e, 0x00000fbf }; | |
428 | ||
429 | for (i = 0; i < 64; i++) | |
430 | GT_REG_WRITE (SRAM_DATA0, dfcdl_tbl[i]); | |
431 | GT_REG_WRITE (DFCDL_CONFIG0, 0x00300000); /* enable dynamic delay line updating */ | |
432 | ||
433 | return (0); | |
434 | } |