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)
74 printf ("mapping bank %d at %08x - %08x\n",
75 bankNo, bankBase, bankBase + bankLength - 1);
77 printf ("unmapping bank %d\n", bankNo);
80 memoryMapBank (bankNo, bankBase, bankLength);
83 for (host = PCI_HOST0; host <= PCI_HOST1; host++) {
88 READ_LINE_AGGRESSIVE_PREFETCH |
89 READ_MULTI_AGGRESSIVE_PREFETCH |
90 MAX_BURST_4 | PCI_NO_SWAP;
92 pciMapMemoryBank (host, bankNo, bankBase, bankLength);
94 pciSetRegionSnoopMode (host, bankNo, PCI_SNOOP_WB, bankBase,
97 pciSetRegionFeatures (host, bankNo, features, bankBase,
106 * Check memory range for valid RAM. A simple memory test determines
107 * the actually available RAM size between addresses `base' and
108 * `base + maxsize'. Some (not all) hardware errors are detected:
109 * - short between address lines
110 * - short between data lines
112 long int dram_size (long int *base, long int maxsize)
114 volatile long int *addr, *b = base;
115 long int cnt, val, save1, save2;
117 #define STARTVAL (1<<20) /* start test at 1M */
118 for (cnt = STARTVAL / sizeof (long); cnt < maxsize / sizeof (long);
120 addr = base + cnt; /* pointer arith! */
122 save1 = *addr; /* save contents of addr */
123 save2 = *b; /* save contents of base */
125 *addr = cnt; /* write cnt to addr */
126 *b = 0; /* put null at base */
128 /* check at base address */
130 *addr = save1; /* restore *addr */
131 *b = save2; /* restore *b */
134 val = *addr; /* read *addr */
135 val = *addr; /* read *addr */
142 ("Found %08x at Address %08x (failure)\n",
143 (unsigned int) val, (unsigned int) addr));
144 /* fix boundary condition.. STARTVAL means zero */
145 if (cnt == STARTVAL / sizeof (long))
147 return (cnt * sizeof (long));
154 #define SDRAM_NORMAL 0x0
155 #define SDRAM_PRECHARGE_ALL 0x1
156 #define SDRAM_REFRESH_ALL 0x2
157 #define SDRAM_MODE_REG_SETUP 0x3
158 #define SDRAM_XTEN_MODE_REG_SETUP 0x4
159 #define SDRAM_NOP 0x5
160 #define SDRAM_SELF_REFRESH 0x7
162 long int initdram (int board_type)
170 /* first disable all banks */
171 memory_map_bank(0, 0, 0);
172 memory_map_bank(1, 0, 0);
173 memory_map_bank(2, 0, 0);
174 memory_map_bank(3, 0, 0);
176 /* calibrate delay lines */
179 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP); /* 0x1418 */
181 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
184 /* SDRAM controller configuration */
185 #ifdef CONFIG_MV64460_ECC
186 GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58201400); /* 0x1400 */
188 GT_REG_WRITE(MV64460_SDRAM_CONFIG, 0x58200400); /* 0x1400 */
190 GT_REG_WRITE(MV64460_D_UNIT_CONTROL_LOW, 0xC3000540); /* 0x1404 */
191 GT_REG_WRITE(MV64460_D_UNIT_CONTROL_HIGH, 0x0300F777); /* 0x1424 */
192 GT_REG_WRITE(MV64460_SDRAM_TIMING_CONTROL_LOW, 0x01712220); /* 0x1408 */
193 GT_REG_WRITE(MV64460_SDRAM_TIMING_CONTROL_HIGH, 0x0000005D); /* 0x140C */
194 GT_REG_WRITE(MV64460_SDRAM_ADDR_CONTROL, 0x00000012); /* 0x1410 */
195 GT_REG_WRITE(MV64460_SDRAM_OPEN_PAGES_CONTROL, 0x00000001); /* 0x1414 */
197 /* SDRAM drive strength */
198 GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000000); /* 0x14C0 */
199 GT_REG_WRITE(MV64460_SDRAM_ADDR_CTRL_PADS_CALIBRATION, 0x80000008); /* 0x14C0 */
200 GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000000); /* 0x14C4 */
201 GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000008); /* 0x14C4 */
203 /* setup SDRAM device registers */
206 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */
208 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
212 GT_REG_WRITE(MV64460_EXTENDED_DRAM_MODE, 0x00000000); /* 0x1420 */
213 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_XTEN_MODE_REG_SETUP); /* 0x1418 */
215 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
219 GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000132); /* 0x141C */
220 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */
222 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
226 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL); /* 0x1418 */
228 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
231 /* wait for 2 auto refresh commands */
235 GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000032); /* 0x141C */
236 GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP); /* 0x1418 */
238 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
241 /* wait 200 cycles */
242 udelay(2); /* FIXME make this dynamic for the system clock */
244 /* SDRAM init done */
245 memory_map_bank(0, CFG_SDRAM_BASE, (256 << 20));
246 #ifdef CFG_SDRAM1_BASE
247 memory_map_bank(1, CFG_SDRAM1_BASE, (256 << 20));
250 /* DUNIT_MMASK: enable SnoopHitEn bit to avoid errata CPU-#4
252 tmp = GTREGREAD(MV64460_D_UNIT_MMASK); /* 0x14B0 */
253 GT_REG_WRITE(MV64460_D_UNIT_MMASK, tmp | 0x2);
258 #elif defined (CONFIG_P3M7448)
262 #ifdef CONFIG_MV64460_ECC
263 memSpaceAttr = ((~(BIT0 << 0)) & 0xf) << 8;
264 mvDmaSetMemorySpace (0, 0, memSpaceAttr, start, size);
265 for (dest = start; dest < start + size; dest += _8M) {
266 mvDmaTransfer (0, start, dest, _8M,
267 BIT8 /*DMA_DTL_128BYTES */ |
268 BIT3 /*DMA_HOLD_SOURCE_ADDR */ |
269 BIT11 /*DMA_BLOCK_TRANSFER_MODE */ );
270 while (mvDmaIsChannelActive (0));
277 void board_add_ram_info(int use_default)
282 switch ((GTREGREAD(MV64460_SDRAM_MODE) >> 4) & 0x7) {
297 val = GTREGREAD(MV64460_SDRAM_CONFIG);
300 if (val & 0x00001000)
303 puts("not enabled)");
307 * mvDmaIsChannelActive - Check if IDMA channel is active
309 * channel = IDMA channel number from 0 to 7
311 int mvDmaIsChannelActive (int channel)
315 data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel);
316 if (data & BIT14) /* activity status */
323 * mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding
326 * memSpace = IDMA memory window number from 0 to 7
327 * trg_if = Target interface:
330 * 0x2 Integrated SDRAM (or CPU bus 60x only)
333 * attr = IDMA attributes (see MV datasheet)
334 * base_addr = Sets up memory window for transfers
337 int mvDmaSetMemorySpace (ulong memSpace,
339 ulong attr, ulong base_addr, ulong size)
343 /* The base address must be aligned to the size. */
344 if (base_addr % size != 0)
347 if (size >= 0x10000) { /* 64K */
349 base_addr = (base_addr & 0xffff0000);
350 /* Set the new attributes */
351 GT_REG_WRITE (MV64460_DMA_BASE_ADDR_REG0 + memSpace * 8,
352 (base_addr | trg_if | attr));
353 GT_REG_WRITE ((MV64460_DMA_SIZE_REG0 + memSpace * 8),
354 (size - 1) & 0xffff0000);
355 temp = GTREGREAD (MV64460_DMA_BASE_ADDR_ENABLE_REG);
356 GT_REG_WRITE (DMA_BASE_ADDR_ENABLE_REG,
357 (temp & ~(BIT0 << memSpace)));
365 * mvDmaTransfer - Transfer data from src_addr to dst_addr on one of the 4
368 * channel = IDMA channel number from 0 to 3
369 * destAddr = Destination address
370 * sourceAddr = Source address
371 * size = Size in bytes
372 * command = See MV datasheet
375 int mvDmaTransfer (int channel, ulong sourceAddr,
376 ulong destAddr, ulong size, ulong command)
378 ulong engOffReg = 0; /* Engine Offset Register */
381 command = command | BIT31; /* DMA_16M_DESCRIPTOR_MODE */
382 command = command | ((command >> 6) & 0x7);
383 engOffReg = channel * 4;
384 GT_REG_WRITE (MV64460_DMA_CHANNEL0_BYTE_COUNT + engOffReg, size);
385 GT_REG_WRITE (MV64460_DMA_CHANNEL0_SOURCE_ADDR + engOffReg, sourceAddr);
386 GT_REG_WRITE (MV64460_DMA_CHANNEL0_DESTINATION_ADDR + engOffReg, destAddr);
388 BIT12 | /* DMA_CHANNEL_ENABLE */
389 BIT9; /* DMA_NON_CHAIN_MODE */
390 /* Activate DMA channel By writting to mvDmaControlRegister */
391 GT_REG_WRITE (MV64460_DMA_CHANNEL0_CONTROL + engOffReg, command);
395 /****************************************************************************************
397 * This procedure detect all Sdram types: 64, 128, 256, 512 Mbit, 1Gbit and 2Gb *
398 * This procedure fits only the Atlantis *
400 ***************************************************************************************/
402 /****************************************************************************************
403 * DFCDL initialize MV643xx Design Considerations *
405 ***************************************************************************************/
406 int set_dfcdlInit (void)
410 /* Values from MV64460 User Manual */
411 unsigned int dfcdl_tbl[] = { 0x00000000, 0x00000001, 0x00000042, 0x00000083,
412 0x000000c4, 0x00000105, 0x00000146, 0x00000187,
413 0x000001c8, 0x00000209, 0x0000024a, 0x0000028b,
414 0x000002cc, 0x0000030d, 0x0000034e, 0x0000038f,
415 0x000003d0, 0x00000411, 0x00000452, 0x00000493,
416 0x000004d4, 0x00000515, 0x00000556, 0x00000597,
417 0x000005d8, 0x00000619, 0x0000065a, 0x0000069b,
418 0x000006dc, 0x0000071d, 0x0000075e, 0x0000079f,
419 0x000007e0, 0x00000821, 0x00000862, 0x000008a3,
420 0x000008e4, 0x00000925, 0x00000966, 0x000009a7,
421 0x000009e8, 0x00000a29, 0x00000a6a, 0x00000aab,
422 0x00000aec, 0x00000b2d, 0x00000b6e, 0x00000baf,
423 0x00000bf0, 0x00000c31, 0x00000c72, 0x00000cb3,
424 0x00000cf4, 0x00000d35, 0x00000d76, 0x00000db7,
425 0x00000df8, 0x00000e39, 0x00000e7a, 0x00000ebb,
426 0x00000efc, 0x00000f3d, 0x00000f7e, 0x00000fbf };
428 for (i = 0; i < 64; i++)
429 GT_REG_WRITE (SRAM_DATA0, dfcdl_tbl[i]);
430 GT_REG_WRITE (DFCDL_CONFIG0, 0x00300000); /* enable dynamic delay line updating */