]> git.sur5r.net Git - u-boot/blob - board/prodrive/p3mx/sdram_init.c
b4556debff85857d752f4beec1bec439d68931ec
[u-boot] / board / prodrive / p3mx / sdram_init.c
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
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
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
47 #define MAP_PCI
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 {
68 #ifdef MAP_PCI
69         PCI_HOST host;
70 #endif
71
72 #ifdef DEBUG
73         if (bankLength > 0)
74                 printf ("mapping bank %d at %08x - %08x\n",
75                         bankNo, bankBase, bankBase + bankLength - 1);
76         else
77                 printf ("unmapping bank %d\n", bankNo);
78 #endif
79
80         memoryMapBank (bankNo, bankBase, bankLength);
81
82 #ifdef MAP_PCI
83         for (host = PCI_HOST0; host <= PCI_HOST1; host++) {
84                 const int features =
85                         PREFETCH_ENABLE |
86                         DELAYED_READ_ENABLE |
87                         AGGRESSIVE_PREFETCH |
88                         READ_LINE_AGGRESSIVE_PREFETCH |
89                         READ_MULTI_AGGRESSIVE_PREFETCH |
90                         MAX_BURST_4 | PCI_NO_SWAP;
91
92                 pciMapMemoryBank (host, bankNo, bankBase, bankLength);
93
94                 pciSetRegionSnoopMode (host, bankNo, PCI_SNOOP_WB, bankBase,
95                                        bankLength);
96
97                 pciSetRegionFeatures (host, bankNo, features, bankBase,
98                                       bankLength);
99         }
100 #endif
101
102         return 0;
103 }
104
105 /*
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
111  */
112 long int dram_size (long int *base, long int maxsize)
113 {
114         volatile long int *addr, *b = base;
115         long int cnt, val, save1, save2;
116
117 #define STARTVAL (1<<20)        /* start test at 1M */
118         for (cnt = STARTVAL / sizeof (long); cnt < maxsize / sizeof (long);
119              cnt <<= 1) {
120                 addr = base + cnt;      /* pointer arith! */
121
122                 save1 = *addr;  /* save contents of addr */
123                 save2 = *b;     /* save contents of base */
124
125                 *addr = cnt;    /* write cnt to addr */
126                 *b = 0;         /* put null at base */
127
128                 /* check at base address */
129                 if ((*b) != 0) {
130                         *addr = save1;  /* restore *addr */
131                         *b = save2;     /* restore *b */
132                         return (0);
133                 }
134                 val = *addr;    /* read *addr */
135                 val = *addr;    /* read *addr */
136
137                 *addr = save1;
138                 *b = save2;
139
140                 if (val != cnt) {
141                         DP (printf
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))
146                                 cnt = 0;
147                         return (cnt * sizeof (long));
148                 }
149         }
150
151         return maxsize;
152 }
153
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
161
162 long int initdram (int board_type)
163 {
164         int tmp;
165         int start;
166         ulong size;
167         ulong memSpaceAttr;
168         ulong dest;
169
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);
175
176         /* calibrate delay lines */
177         set_dfcdlInit();
178
179         GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP);               /* 0x1418 */
180         do {
181                 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
182         } while(tmp != 0x0);
183
184         /* SDRAM controller configuration */
185 #ifdef CONFIG_MV64460_ECC
186         GT_REG_WRITE(MV64460_SDRAM_CONFIG,              0x58201400);    /* 0x1400 */
187 #else
188         GT_REG_WRITE(MV64460_SDRAM_CONFIG,              0x58200400);    /* 0x1400 */
189 #endif
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 */
196
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 */
202
203         /* setup SDRAM device registers */
204
205         /* precharge all */
206         GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL);     /* 0x1418 */
207         do {
208                 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
209         } while(tmp != 0x0);
210
211         /* enable DLL */
212         GT_REG_WRITE(MV64460_EXTENDED_DRAM_MODE, 0x00000000);                   /* 0x1420 */
213         GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_XTEN_MODE_REG_SETUP);       /* 0x1418 */
214         do {
215                 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
216         } while(tmp != 0x0);
217
218         /* reset DLL */
219         GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000132);   /* 0x141C */
220         GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP);    /* 0x1418 */
221         do {
222                 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
223         } while(tmp != 0x0);
224
225         /* precharge all */
226         GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_PRECHARGE_ALL);     /* 0x1418 */
227         do {
228                 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
229         } while(tmp != 0x0);
230
231         /* wait for 2 auto refresh commands */
232         udelay(20);
233
234         /* un-reset DLL */
235         GT_REG_WRITE(MV64460_SDRAM_MODE, 0x00000032);   /* 0x141C */
236         GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_MODE_REG_SETUP);    /* 0x1418 */
237         do {
238                 tmp = GTREGREAD(MV64460_SDRAM_OPERATION);
239         } while(tmp != 0x0);
240
241         /* wait 200 cycles */
242         udelay(2);  /* FIXME  make this dynamic for the system clock */
243
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));
248 #endif
249
250         /* DUNIT_MMASK: enable SnoopHitEn bit to avoid errata CPU-#4
251          */
252         tmp = GTREGREAD(MV64460_D_UNIT_MMASK);                          /* 0x14B0 */
253         GT_REG_WRITE(MV64460_D_UNIT_MMASK, tmp | 0x2);
254
255         start = (0 << 20);
256 #ifdef CONFIG_P3M750
257         size = (512 << 20);
258 #elif defined (CONFIG_P3M7448)
259         size = (128 << 20);
260 #endif
261
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));
271         }
272 #endif
273
274         return (size);
275 }
276
277 void board_add_ram_info(int use_default)
278 {
279         u32 val;
280
281         puts(" (CL=");
282         switch ((GTREGREAD(MV64460_SDRAM_MODE) >> 4) & 0x7) {
283         case 0x2:
284                 puts("2");
285                 break;
286         case 0x3:
287                 puts("3");
288                 break;
289         case 0x5:
290                 puts("1.5");
291                 break;
292         case 0x6:
293                 puts("2.5");
294                 break;
295         }
296
297         val = GTREGREAD(MV64460_SDRAM_CONFIG);
298
299         puts(", ECC ");
300         if (val & 0x00001000)
301                 puts("enabled)");
302         else
303                 puts("not enabled)");
304 }
305
306 /*
307  * mvDmaIsChannelActive - Check if IDMA channel is active
308  *
309  * channel      = IDMA channel number from 0 to 7
310  */
311 int mvDmaIsChannelActive (int channel)
312 {
313         ulong data;
314
315         data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel);
316         if (data & BIT14)       /* activity status */
317                 return 1;
318
319         return 0;
320 }
321
322 /*
323  * mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding
324  *                       map.
325  *
326  * memSpace     = IDMA memory window number from 0 to 7
327  * trg_if       = Target interface:
328  *                0x0 DRAM
329  *                0x1 Device Bus
330  *                0x2 Integrated SDRAM (or CPU bus 60x only)
331  *                0x3 PCI0
332  *                0x4 PCI1
333  * attr         = IDMA attributes (see MV datasheet)
334  * base_addr    = Sets up memory window for transfers
335  *
336  */
337 int mvDmaSetMemorySpace (ulong memSpace,
338                          ulong trg_if,
339                          ulong attr, ulong base_addr, ulong size)
340 {
341         ulong temp;
342
343         /* The base address must be aligned to the size.  */
344         if (base_addr % size != 0)
345                 return 0;
346
347         if (size >= 0x10000) {   /* 64K */
348                 size &= 0xffff0000;
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)));
358                 return 1;
359         }
360
361         return 0;
362 }
363
364 /*
365  * mvDmaTransfer - Transfer data from src_addr to dst_addr on one of the 4
366  *                 DMA channels.
367  *
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
373  *
374  */
375 int mvDmaTransfer (int channel, ulong sourceAddr,
376                    ulong destAddr, ulong size, ulong command)
377 {
378         ulong engOffReg = 0;    /* Engine Offset Register */
379
380         if (size > 0xffff)
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);
387         command = command |
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);
392         return 1;
393 }
394
395 /****************************************************************************************
396  *                             SDRAM INIT                                               *
397  *  This procedure detect all Sdram types: 64, 128, 256, 512 Mbit, 1Gbit and 2Gb        *
398  *               This procedure fits only the Atlantis                                  *
399  *                                                                                      *
400  ***************************************************************************************/
401
402 /****************************************************************************************
403  *                             DFCDL initialize MV643xx Design Considerations           *
404  *                                                                                      *
405  ***************************************************************************************/
406 int set_dfcdlInit (void)
407 {
408         int i;
409
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 };
427
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 */
431
432         return (0);
433 }