]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/prodrive/p3mx/sdram_init.c
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.git] / 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 #if defined (MAP_PCI) && defined (CONFIG_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         }
79 #endif
80
81         memoryMapBank (bankNo, bankBase, bankLength);
82
83 #if defined (MAP_PCI) && defined (CONFIG_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  */
113 long 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
163 phys_size_t 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
180         GT_REG_WRITE(MV64460_SDRAM_OPERATION, SDRAM_NOP);               /* 0x1418 */
181         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 */
201         GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000000);      /* 0x14C4 */
202         GT_REG_WRITE(MV64460_SDRAM_DATA_PADS_CALIBRATION, 0x80000008);      /* 0x14C4 */
203
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, CONFIG_SYS_SDRAM_BASE,  (256 << 20));
247 #ifdef CONFIG_SYS_SDRAM1_BASE
248         memory_map_bank(1, CONFIG_SYS_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
278 void 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  *
310  * channel      = IDMA channel number from 0 to 7
311  */
312 int mvDmaIsChannelActive (int channel)
313 {
314         ulong data;
315
316         data = GTREGREAD (MV64460_DMA_CHANNEL0_CONTROL + 4 * channel);
317         if (data & BIT14)       /* activity status */
318                 return 1;
319
320         return 0;
321 }
322
323 /*
324  * mvDmaSetMemorySpace - Set a DMA memory window for the DMA's address decoding
325  *                       map.
326  *
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  */
338 int 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
367  *                 DMA channels.
368  *
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
374  *
375  */
376 int 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 |
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);
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  ***************************************************************************************/
407 int 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 }