blob: 176252efee5ff0986cf02a9c13f735d7d39b7bb6 [file] [log] [blame]
Stefan Roese45993ea2006-11-29 15:42:37 +01001/*
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
Wolfgang Denkdd314e02006-11-30 01:54:07 +010015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Stefan Roese45993ea2006-11-29 15:42:37 +010016 * 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
44DECLARE_GLOBAL_DATA_PTR;
45
46#undef DEBUG
Wolfgang Denkdd314e02006-11-30 01:54:07 +010047#define MAP_PCI
Stefan Roese45993ea2006-11-29 15:42:37 +010048
49#ifdef DEBUG
50#define DP(x) x
51#else
52#define DP(x)
53#endif
54
55int set_dfcdlInit (void); /* setup delay line of Mv64460 */
56int mvDmaIsChannelActive (int);
57int mvDmaSetMemorySpace (ulong, ulong, ulong, ulong, ulong);
58int 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
65int memory_map_bank (unsigned int bankNo,
66 unsigned int bankBase, unsigned int bankLength)
67{
68#ifdef MAP_PCI
69 PCI_HOST host;
70#endif
71
72#ifdef DEBUG
Wolfgang Denkdd314e02006-11-30 01:54:07 +010073 if (bankLength > 0) {
Stefan Roese45993ea2006-11-29 15:42:37 +010074 printf ("mapping bank %d at %08x - %08x\n",
75 bankNo, bankBase, bankBase + bankLength - 1);
Wolfgang Denkdd314e02006-11-30 01:54:07 +010076 } else {
Stefan Roese45993ea2006-11-29 15:42:37 +010077 printf ("unmapping bank %d\n", bankNo);
Wolfgang Denkdd314e02006-11-30 01:54:07 +010078 }
Stefan Roese45993ea2006-11-29 15:42:37 +010079#endif
80
81 memoryMapBank (bankNo, bankBase, bankLength);
82
83#ifdef MAP_PCI
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 */
113long 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
163long int initdram (int board_type)
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
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100180 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP); /* 0x1418 */
Stefan Roese45993ea2006-11-29 15:42:37 +0100181 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 */
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100201 GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000000); /* 0x14C4 */
202 GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000008); /* 0x14C4 */
Stefan Roese45993ea2006-11-29 15:42:37 +0100203
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 */
246 memory_map_bank(0, CFG_SDRAM_BASE, (256 << 20));
247#ifdef CFG_SDRAM1_BASE
248 memory_map_bank(1, CFG_SDRAM1_BASE, (256 << 20));
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
278void 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 *
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100310 * channel = IDMA channel number from 0 to 7
Stefan Roese45993ea2006-11-29 15:42:37 +0100311 */
312int mvDmaIsChannelActive (int channel)
313{
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100314 ulong data;
Stefan Roese45993ea2006-11-29 15:42:37 +0100315
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100316 data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel);
317 if (data & BIT14) /* activity status */
318 return 1;
Stefan Roese45993ea2006-11-29 15:42:37 +0100319
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100320 return 0;
Stefan Roese45993ea2006-11-29 15:42:37 +0100321}
322
323/*
324 * mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100325 * map.
Stefan Roese45993ea2006-11-29 15:42:37 +0100326 *
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 */
338int 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
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100367 * DMA channels.
Stefan Roese45993ea2006-11-29 15:42:37 +0100368 *
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100369 * channel = IDMA channel number from 0 to 3
Stefan Roese45993ea2006-11-29 15:42:37 +0100370 * destAddr = Destination address
371 * sourceAddr = Source address
372 * size = Size in bytes
373 * command = See MV datasheet
374 *
375 */
376int 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 |
Wolfgang Denkdd314e02006-11-30 01:54:07 +0100389 BIT12 | /* DMA_CHANNEL_ENABLE */
Stefan Roese45993ea2006-11-29 15:42:37 +0100390 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 ***************************************************************************************/
407int 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}