uboot/board/prodrive/p3mx/sdram_init.c
<<
>>
Prefs
   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
  44DECLARE_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
  55int set_dfcdlInit (void);       /* setup delay line of Mv64460 */
  56int mvDmaIsChannelActive (int);
  57int mvDmaSetMemorySpace (ulong, ulong, ulong, ulong, ulong);
  58int 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
  65int 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 */
 113long 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
 163phys_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
 278void 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 */
 312int 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 */
 338int 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 */
 376int 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 ***************************************************************************************/
 407int 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}
 435