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