Merge branch 'master' of git://www.denx.de/git/u-boot-video
[oweals/u-boot.git] / cpu / mpc85xx / spd_sdram.c
index af99282dd94bbfae4083ec0d5b83efed562adc37..435458a18930b482394c79b458a397ef974c3dcd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004 Freescale Semiconductor.
+ * Copyright 2004, 2007 Freescale Semiconductor.
  * (C) Copyright 2003 Motorola Inc.
  * Xianghua Xiao (X.Xiao@motorola.com)
  *
@@ -27,6 +27,7 @@
 #include <i2c.h>
 #include <spd.h>
 #include <asm/mmu.h>
+#include <asm/fsl_law.h>
 
 
 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
@@ -53,8 +54,8 @@ picos_to_clk(int picos)
 {
        int clks;
 
-       clks = picos / (2000000000 / (get_bus_freq(0) / 1000));
-       if (picos % (2000000000 / (get_bus_freq(0) / 1000)) != 0) {
+       clks = picos / (2000000000 / (get_ddr_freq(0) / 1000));
+       if (picos % (2000000000 / (get_ddr_freq(0) / 1000)) != 0) {
                clks++;
        }
 
@@ -131,8 +132,8 @@ convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
                800,
                900,
                250,
-               330,    /* FIXME: Is 333 better/valid? */
-               660,    /* FIXME: Is 667 better/valid? */
+               330,
+               660,
                750,
                0,      /* undefined */
                0       /* undefined */
@@ -146,24 +147,48 @@ convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
 }
 
 
+/*
+ * Determine Refresh Rate.  Ignore self refresh bit on DDR I.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
+ */
+unsigned int determine_refresh_rate(unsigned int spd_refresh)
+{
+       unsigned int refresh_time_ns[8] = {
+               15625000,       /* 0 Normal    1.00x */
+               3900000,        /* 1 Reduced    .25x */
+               7800000,        /* 2 Extended   .50x */
+               31300000,       /* 3 Extended  2.00x */
+               62500000,       /* 4 Extended  4.00x */
+               125000000,      /* 5 Extended  8.00x */
+               15625000,       /* 6 Normal    1.00x  filler */
+               15625000,       /* 7 Normal    1.00x  filler */
+       };
+
+       return picos_to_clk(refresh_time_ns[spd_refresh & 0x7]);
+}
+
+
 long int
 spd_sdram(void)
 {
-       volatile immap_t *immap = (immap_t *)CFG_IMMR;
-       volatile ccsr_ddr_t *ddr = &immap->im_ddr;
-       volatile ccsr_gur_t *gur = &immap->im_gur;
+       volatile ccsr_ddr_t *ddr = (void *)(CFG_MPC85xx_DDR_ADDR);
        spd_eeprom_t spd;
        unsigned int n_ranks;
        unsigned int rank_density;
-       unsigned int odt_rd_cfg, odt_wr_cfg;
+       unsigned int odt_rd_cfg, odt_wr_cfg, ba_bits;
        unsigned int odt_cfg, mode_odt_enable;
+       unsigned int refresh_clk;
+#ifdef MPC85xx_DDR_SDRAM_CLK_CNTL
+       unsigned char clk_adjust;
+#endif
        unsigned int dqs_cfg;
        unsigned char twr_clk, twtr_clk, twr_auto_clk;
        unsigned int tCKmin_ps, tCKmax_ps;
        unsigned int max_data_rate, effective_data_rate;
        unsigned int busfreq;
        unsigned sdram_cfg;
-       unsigned int memsize;
+       unsigned int memsize = 0;
        unsigned char caslat, caslat_ctrl;
        unsigned int trfc, trfc_clk, trfc_low, trfc_high;
        unsigned int trcd_clk;
@@ -178,6 +203,46 @@ spd_sdram(void)
        unsigned int mode_caslat;
        unsigned char sdram_type;
        unsigned char d_init;
+       unsigned int bnds;
+
+       /*
+        * Skip configuration if already configured.
+        * memsize is determined from last configured chip select.
+        */
+       if (ddr->cs0_config & 0x80000000) {
+               debug(" cs0 already configured, bnds=%x\n",ddr->cs0_bnds);
+               bnds = 0xfff & ddr->cs0_bnds;
+               if (bnds < 0xff) { /* do not add if at top of 4G */
+                       memsize = (bnds + 1) << 4;
+               }
+       }
+       if (ddr->cs1_config & 0x80000000) {
+               debug(" cs1 already configured, bnds=%x\n",ddr->cs1_bnds);
+               bnds = 0xfff & ddr->cs1_bnds;
+               if (bnds < 0xff) { /* do not add if at top of 4G */
+                       memsize = (bnds + 1) << 4; /* assume ordered bnds */
+               }
+       }
+       if (ddr->cs2_config & 0x80000000) {
+               debug(" cs2 already configured, bnds=%x\n",ddr->cs2_bnds);
+               bnds = 0xfff & ddr->cs2_bnds;
+               if (bnds < 0xff) { /* do not add if at top of 4G */
+                       memsize = (bnds + 1) << 4;
+               }
+       }
+       if (ddr->cs3_config & 0x80000000) {
+               debug(" cs3 already configured, bnds=%x\n",ddr->cs3_bnds);
+               bnds = 0xfff & ddr->cs3_bnds;
+               if (bnds < 0xff) { /* do not add if at top of 4G */
+                       memsize = (bnds + 1) << 4;
+               }
+       }
+
+       if (memsize) {
+               printf("       Reusing current %dMB configuration\n",memsize);
+               memsize = setup_laws_and_tlbs(memsize);
+               return memsize << 20;
+       }
 
        /*
         * Read SPD information.
@@ -236,15 +301,19 @@ spd_sdram(void)
                return 0;
        }
 
+#ifdef CONFIG_MPC8548
        /*
-        * Adjust DDR II IO voltage biasing.  It just makes it work.
+        * Adjust DDR II IO voltage biasing.
+        * Only 8548 rev 1 needs the fix
         */
-       if (spd.mem_type == SPD_MEMTYPE_DDR2) {
-               gur->ddrioovcr = (0
-                                 | 0x80000000          /* Enable */
-                                 | 0x10000000          /* VSEL to 1.8V */
-                                 );
+       if ((SVR_SOC_VER(get_svr()) == SVR_8548_E) &&
+                       (SVR_MJREV(get_svr()) == 1) &&
+                       (spd.mem_type == SPD_MEMTYPE_DDR2)) {
+               volatile ccsr_gur_t *gur = (void *)(CFG_MPC85xx_GUTS_ADDR);
+               gur->ddrioovcr = (0x80000000    /* Enable */
+                                 | 0x10000000);/* VSEL to 1.8V */
        }
+#endif
 
        /*
         * Determine the size of each Rank in bytes.
@@ -272,9 +341,14 @@ spd_sdram(void)
 #endif
        }
 
+       ba_bits = 0;
+       if (spd.nbanks == 0x8)
+               ba_bits = 1;
+
        ddr->cs0_config = ( 1 << 31
                            | (odt_rd_cfg << 20)
                            | (odt_wr_cfg << 16)
+                           | (ba_bits << 14)
                            | (spd.nrow_addr - 12) << 8
                            | (spd.ncol_addr - 8) );
        debug("\n");
@@ -348,7 +422,7 @@ spd_sdram(void)
         * Adjust the CAS Latency to allow for bus speeds that
         * are slower than the DDR module.
         */
-       busfreq = get_bus_freq(0) / 1000000;    /* MHz */
+       busfreq = get_ddr_freq(0) / 1000000;    /* MHz */
 
        effective_data_rate = max_data_rate;
        if (busfreq < 90) {
@@ -618,13 +692,10 @@ spd_sdram(void)
         */
        cpo = 0;
        if (spd.mem_type == SPD_MEMTYPE_DDR2) {
-               if (effective_data_rate == 266 || effective_data_rate == 333) {
+               if (effective_data_rate <= 333) {
                        cpo = 0x7;              /* READ_LAT + 5/4 */
-               } else if (effective_data_rate == 400) {
-                       cpo = 0x9;              /* READ_LAT + 7/4 */
                } else {
-                       /* Pure speculation */
-                       cpo = 0xb;
+                       cpo = 0x9;              /* READ_LAT + 7/4 */
                }
        }
 
@@ -740,51 +811,37 @@ spd_sdram(void)
        ddr->sdram_mode_2 = 0;
        debug("DDR: sdram_mode_2 = 0x%08x\n", ddr->sdram_mode_2);
 
-
        /*
-        * Determine Refresh Rate.  Ignore self refresh bit on DDR I.
-        * Table from SPD Spec, Byte 12, converted to picoseconds and
-        * filled in with "default" normal values.
+        * Determine Refresh Rate.
         */
-       {
-               unsigned int refresh_clk;
-               unsigned int refresh_time_ns[8] = {
-                       15625000,       /* 0 Normal    1.00x */
-                       3900000,        /* 1 Reduced    .25x */
-                       7800000,        /* 2 Extended   .50x */
-                       31300000,       /* 3 Extended  2.00x */
-                       62500000,       /* 4 Extended  4.00x */
-                       125000000,      /* 5 Extended  8.00x */
-                       15625000,       /* 6 Normal    1.00x  filler */
-                       15625000,       /* 7 Normal    1.00x  filler */
-               };
+       refresh_clk = determine_refresh_rate(spd.refresh & 0x7);
 
-               refresh_clk = picos_to_clk(refresh_time_ns[spd.refresh & 0x7]);
-
-               /*
-                * Set BSTOPRE to 0x100 for page mode
-                * If auto-charge is used, set BSTOPRE = 0
-                */
-               ddr->sdram_interval =
-                       (0
-                        | (refresh_clk & 0x3fff) << 16
-                        | 0x100
-                        );
-               debug("DDR: sdram_interval = 0x%08x\n", ddr->sdram_interval);
-       }
+       /*
+        * Set BSTOPRE to 0x100 for page mode
+        * If auto-charge is used, set BSTOPRE = 0
+        */
+       ddr->sdram_interval =
+           (0
+            | (refresh_clk & 0x3fff) << 16
+            | 0x100
+            );
+       debug("DDR: sdram_interval = 0x%08x\n", ddr->sdram_interval);
 
        /*
         * Is this an ECC DDR chip?
         * But don't mess with it if the DDR controller will init mem.
         */
-#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+#ifdef CONFIG_DDR_ECC
        if (spd.config == 0x02) {
+#ifndef CONFIG_ECC_INIT_VIA_DDRCONTROLLER
                ddr->err_disable = 0x0000000d;
+#endif
                ddr->err_sbe = 0x00ff0000;
        }
+
        debug("DDR: err_disable = 0x%08x\n", ddr->err_disable);
        debug("DDR: err_sbe = 0x%08x\n", ddr->err_sbe);
-#endif
+#endif /* CONFIG_DDR_ECC */
 
        asm("sync;isync;msync");
        udelay(500);
@@ -835,28 +892,28 @@ spd_sdram(void)
 
 
 #ifdef MPC85xx_DDR_SDRAM_CLK_CNTL
-       {
-               unsigned char clk_adjust;
-
-               /*
-                * Setup the clock control.
-                * SDRAM_CLK_CNTL[0] = Source synchronous enable == 1
-                * SDRAM_CLK_CNTL[5-7] = Clock Adjust
-                *      0110    3/4 cycle late
-                *      0111    7/8 cycle late
-                */
-               if (spd.mem_type == SPD_MEMTYPE_DDR) {
-                       clk_adjust = 0x6;
-               } else {
-                       clk_adjust = 0x7;
-               }
+       /*
+        * Setup the clock control.
+        * SDRAM_CLK_CNTL[0] = Source synchronous enable == 1
+        * SDRAM_CLK_CNTL[5-7] = Clock Adjust
+        *      0110    3/4 cycle late
+        *      0111    7/8 cycle late
+        */
+       if (spd.mem_type == SPD_MEMTYPE_DDR)
+               clk_adjust = 0x6;
+       else
+#ifdef CONFIG_MPC8568
+               /* Empirally setting clk_adjust */
+               clk_adjust = 0x6;
+#else
+               clk_adjust = 0x7;
+#endif
 
-               ddr->sdram_clk_cntl = (0
+       ddr->sdram_clk_cntl = (0
                               | 0x80000000
                               | (clk_adjust << 23)
                               );
-               debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr->sdram_clk_cntl);
-       }
+       debug("DDR: sdram_clk_cntl = 0x%08x\n", ddr->sdram_clk_cntl);
 #endif
 
        /*
@@ -966,8 +1023,6 @@ spd_sdram(void)
 static unsigned int
 setup_laws_and_tlbs(unsigned int memsize)
 {
-       volatile immap_t *immap = (immap_t *)CFG_IMMR;
-       volatile ccsr_local_ecm_t *ecm = &immap->im_local_ecm;
        unsigned int tlb_size;
        unsigned int law_size;
        unsigned int ram_tlb_index;
@@ -987,17 +1042,24 @@ setup_laws_and_tlbs(unsigned int memsize)
                break;
        case 256:
        case 512:
+               tlb_size = BOOKE_PAGESZ_256M;
+               break;
        case 1024:
        case 2048:
-               tlb_size = BOOKE_PAGESZ_256M;
+               if (PVR_VER(get_pvr()) > PVR_VER(PVR_85xx))
+                       tlb_size = BOOKE_PAGESZ_1G;
+               else
+                       tlb_size = BOOKE_PAGESZ_256M;
                break;
        default:
                puts("DDR: only 16M,32M,64M,128M,256M,512M,1G and 2G are supported.\n");
 
                /*
                 * The memory was not able to be mapped.
+                * Default to a small size.
                 */
-               return 0;
+               tlb_size = BOOKE_PAGESZ_64M;
+               memsize=64;
                break;
        }
 
@@ -1009,22 +1071,9 @@ setup_laws_and_tlbs(unsigned int memsize)
        ram_tlb_address = (unsigned int)CFG_DDR_SDRAM_BASE;
        while (ram_tlb_address < (memsize * 1024 * 1024)
              && ram_tlb_index < 16) {
-               mtspr(MAS0, TLB1_MAS0(1, ram_tlb_index, 0));
-               mtspr(MAS1, TLB1_MAS1(1, 1, 0, 0, tlb_size));
-               mtspr(MAS2, TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),
-                                     0, 0, 0, 0, 0, 0, 0, 0));
-               mtspr(MAS3, TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),
-                                     0, 0, 0, 0, 0, 1, 0, 1, 0, 1));
-               asm volatile("isync;msync;tlbwe;isync");
-
-               debug("DDR: MAS0=0x%08x\n", TLB1_MAS0(1, ram_tlb_index, 0));
-               debug("DDR: MAS1=0x%08x\n", TLB1_MAS1(1, 1, 0, 0, tlb_size));
-               debug("DDR: MAS2=0x%08x\n",
-                     TLB1_MAS2(E500_TLB_EPN(ram_tlb_address),
-                               0, 0, 0, 0, 0, 0, 0, 0));
-               debug("DDR: MAS3=0x%08x\n",
-                     TLB1_MAS3(E500_TLB_RPN(ram_tlb_address),
-                               0, 0, 0, 0, 0, 1, 0, 1, 0, 1));
+               set_tlb(1, ram_tlb_address, ram_tlb_address,
+                       MAS3_SX|MAS3_SW|MAS3_SR, 0,
+                       0, ram_tlb_index, tlb_size, 1);
 
                ram_tlb_address += (0x1000 << ((tlb_size - 1) * 2));
                ram_tlb_index++;
@@ -1039,12 +1088,10 @@ setup_laws_and_tlbs(unsigned int memsize)
        /*
         * Set up LAWBAR for all of DDR.
         */
-       ecm->lawbar1 = ((CFG_DDR_SDRAM_BASE >> 12) & 0xfffff);
-       ecm->lawar1 = (LAWAR_EN
-                      | LAWAR_TRGT_IF_DDR
-                      | (LAWAR_SIZE & law_size));
-       debug("DDR: LAWBAR1=0x%08x\n", ecm->lawbar1);
-       debug("DDR: LARAR1=0x%08x\n", ecm->lawar1);
+
+#ifdef CONFIG_FSL_LAW
+       set_law(1, CFG_DDR_SDRAM_BASE, law_size, LAW_TRGT_IF_DDR);
+#endif
 
        /*
         * Confirm that the requested amount of memory was mapped.
@@ -1066,8 +1113,7 @@ ddr_enable_ecc(unsigned int dram_size)
 {
        uint *p = 0;
        uint i = 0;
-       volatile immap_t *immap = (immap_t *)CFG_IMMR;
-       volatile ccsr_ddr_t *ddr= &immap->im_ddr;
+       volatile ccsr_ddr_t *ddr= (void *)(CFG_MPC85xx_DDR_ADDR);
 
        dma_init();
 
@@ -1081,26 +1127,16 @@ ddr_enable_ecc(unsigned int dram_size)
                }
        }
 
-       /* 8K */
-       dma_xfer((uint *)0x2000, 0x2000, (uint *)0);
-       /* 16K */
-       dma_xfer((uint *)0x4000, 0x4000, (uint *)0);
-       /* 32K */
-       dma_xfer((uint *)0x8000, 0x8000, (uint *)0);
-       /* 64K */
-       dma_xfer((uint *)0x10000, 0x10000, (uint *)0);
-       /* 128k */
-       dma_xfer((uint *)0x20000, 0x20000, (uint *)0);
-       /* 256k */
-       dma_xfer((uint *)0x40000, 0x40000, (uint *)0);
-       /* 512k */
-       dma_xfer((uint *)0x80000, 0x80000, (uint *)0);
-       /* 1M */
-       dma_xfer((uint *)0x100000, 0x100000, (uint *)0);
-       /* 2M */
-       dma_xfer((uint *)0x200000, 0x200000, (uint *)0);
-       /* 4M */
-       dma_xfer((uint *)0x400000, 0x400000, (uint *)0);
+       dma_xfer((uint *)0x002000, 0x002000, (uint *)0); /* 8K */
+       dma_xfer((uint *)0x004000, 0x004000, (uint *)0); /* 16K */
+       dma_xfer((uint *)0x008000, 0x008000, (uint *)0); /* 32K */
+       dma_xfer((uint *)0x010000, 0x010000, (uint *)0); /* 64K */
+       dma_xfer((uint *)0x020000, 0x020000, (uint *)0); /* 128k */
+       dma_xfer((uint *)0x040000, 0x040000, (uint *)0); /* 256k */
+       dma_xfer((uint *)0x080000, 0x080000, (uint *)0); /* 512k */
+       dma_xfer((uint *)0x100000, 0x100000, (uint *)0); /* 1M */
+       dma_xfer((uint *)0x200000, 0x200000, (uint *)0); /* 2M */
+       dma_xfer((uint *)0x400000, 0x400000, (uint *)0); /* 4M */
 
        for (i = 1; i < dram_size / 0x800000; i++) {
                dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0);