3 * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
5 * See file CREDITS for list of people who contributed to this
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.
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.
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,
24 /*************************************************************************
25 * adaption for the Marvell DB64460 Board
26 * Ingo Assmus (ingo.assmus@keymile.com)
27 *************************************************************************/
29 /* sdram_init.c - automatic memory sizing */
33 #include "../../Marvell/include/memory.h"
34 #include "../../Marvell/include/pci.h"
35 #include "../../Marvell/include/mv_gen_reg.h"
40 #include "../../Marvell/common/i2c.h"
44 DECLARE_GLOBAL_DATA_PTR;
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);
60 #define D_CACHE_FLUSH_LINE(addr, offset) \
62 __asm__ __volatile__ ("dcbf %0,%1" : : "r" (addr), "r" (offset)); \
65 int memory_map_bank (unsigned int bankNo,
66 unsigned int bankBase, unsigned int bankLength)
68 #if defined (MAP_PCI) && defined (CONFIG_PCI)
74 printf ("mapping bank %d at %08x - %08x\n",
75 bankNo, bankBase, bankBase + bankLength - 1);
77 printf ("unmapping bank %d\n", bankNo);
81 memoryMapBank (bankNo, bankBase, bankLength);
83 #if defined (MAP_PCI) && defined (CONFIG_PCI)
84 for (host = PCI_HOST0; host <= PCI_HOST1; host++) {
89 READ_LINE_AGGRESSIVE_PREFETCH |
90 READ_MULTI_AGGRESSIVE_PREFETCH |
91 MAX_BURST_4 | PCI_NO_SWAP;
93 pciMapMemoryBank (host, bankNo, bankBase, bankLength);
95 pciSetRegionSnoopMode (host, bankNo, PCI_SNOOP_WB, bankBase,
98 pciSetRegionFeatures (host, bankNo, features, bankBase,
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
113 long int dram_size (long int *base, long int maxsize)
115 volatile long int *addr, *b = base;
116 long int cnt, val, save1, save2;
118 #define STARTVAL (1<<20) /* start test at 1M */
119 for (cnt = STARTVAL / sizeof (long); cnt < maxsize / sizeof (long);
121 addr = base + cnt; /* pointer arith! */
123 save1 = *addr; /* save contents of addr */
124 save2 = *b; /* save contents of base */
126 *addr = cnt; /* write cnt to addr */
127 *b = 0; /* put null at base */
129 /* check at base address */
131 *addr = save1; /* restore *addr */
132 *b = save2; /* restore *b */
135 val = *addr; /* read *addr */
136 val = *addr; /* read *addr */
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))
148 return (cnt * sizeof (long));
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
163 long int initdram (int board_type)
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);
177 /* calibrate delay lines */
180 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP); /* 0x1418 */
182 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
185 /* SDRAM controller configuration */
186 #ifdef CONFIG_MV64460_ECC
187 GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58201400); /* 0x1400 */
189 GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58200400); /* 0x1400 */
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 */
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 */
201 GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000000); /* 0x14C4 */
202 GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000008); /* 0x14C4 */
204 /* setup SDRAM device registers */
207 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */
209 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
213 GT_REG_WRITE(MV64460_EXTENDED_DRAM_MODE, 0x00000000); /* 0x1420 */
214 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_XTEN_MODE_REG_SETUP); /* 0x1418 */
216 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
220 GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000132); /* 0x141C */
221 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */
223 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
227 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */
229 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
232 /* wait for 2 auto refresh commands */
236 GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000032); /* 0x141C */
237 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */
239 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
242 /* wait 200 cycles */
243 udelay(2); /* FIXME make this dynamic for the system clock */
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));
251 /* DUNIT_MMASK: enable SnoopHitEn bit to avoid errata CPU-#4
253 tmp = GTREGREAD(MV64460_D_UNIT_MMASK); /* 0x14B0 */
254 GT_REG_WRITE(MV64460_D_UNIT_MMASK, tmp | 0x2);
259 #elif defined (CONFIG_P3M7448)
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));
278 void board_add_ram_info(int use_default)
283 switch ((GTREGREAD(MV64460_SDRAM_MODE) >> 4) & 0x7) {
298 val = GTREGREAD(MV64460_SDRAM_CONFIG);
301 if (val & 0x00001000)
304 puts("not enabled)");
308 * mvDmaIsChannelActive - Check if IDMA channel is active
310 * channel = IDMA channel number from 0 to 7
312 int mvDmaIsChannelActive (int channel)
316 data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel);
317 if (data & BIT14) /* activity status */
324 * mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding
327 * memSpace = IDMA memory window number from 0 to 7
328 * trg_if = Target interface:
331 * 0x2 Integrated SDRAM (or CPU bus 60x only)
334 * attr = IDMA attributes (see MV datasheet)
335 * base_addr = Sets up memory window for transfers
338 int mvDmaSetMemorySpace (ulong memSpace,
340 ulong attr, ulong base_addr, ulong size)
344 /* The base address must be aligned to the size. */
345 if (base_addr % size != 0)
348 if (size >= 0x10000) { /* 64K */
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)));
366 * mvDmaTransfer - Transfer data from src_addr to dst_addr on one of the 4
369 * channel = IDMA channel number from 0 to 3
370 * destAddr = Destination address
371 * sourceAddr = Source address
372 * size = Size in bytes
373 * command = See MV datasheet
376 int mvDmaTransfer (int channel, ulong sourceAddr,
377 ulong destAddr, ulong size, ulong command)
379 ulong engOffReg = 0; /* Engine Offset Register */
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);
389 BIT12 | /* DMA_CHANNEL_ENABLE */
390 BIT9; /* DMA_NON_CHAIN_MODE */
391 /* Activate DMA channel By writting to mvDmaControlRegister */
392 GT_REG_WRITE (MV64460_DMA_CHANNEL0_CONTROL + engOffReg, command);
396 /****************************************************************************************
398 * This procedure detect all Sdram types: 64, 128, 256, 512 Mbit, 1Gbit and 2Gb *
399 * This procedure fits only the Atlantis *
401 ***************************************************************************************/
403 /****************************************************************************************
404 * DFCDL initialize MV643xx Design Considerations *
406 ***************************************************************************************/
407 int set_dfcdlInit (void)
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 };
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 */