Merge branch 'master' of git://www.denx.de/git/u-boot-fdt
[oweals/u-boot.git] / cpu / ppc4xx / 44x_spd_ddr2.c
index 3ac2cdcf7f469f7126309f4105c6fc3b88adf776..521491820d7a89e616352a3421397fb7f875719b 100644 (file)
@@ -1,8 +1,14 @@
 /*
  * cpu/ppc4xx/44x_spd_ddr2.c
  * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
- * DDR2 controller (non Denali Core). Those are 440SP/SPe.
+ * DDR2 controller (non Denali Core). Those currently are:
  *
+ * 405:                405EX(r)
+ * 440/460:    440SP/440SPe/460EX/460GT
+ *
+ * Copyright (c) 2008 Nuovation System Designs, LLC
+ *   Grant Erickson <gerickson@nuovations.com>
+
  * (C) Copyright 2007-2008
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
+#include <asm/cache.h>
+
+#include "ecc.h"
 
 #if defined(CONFIG_SPD_EEPROM) &&                              \
-       (defined(CONFIG_440SP) || defined(CONFIG_440SPE))
+       (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+        defined(CONFIG_460EX) || defined(CONFIG_460GT))
 
 /*-----------------------------------------------------------------------------+
  * Defines
@@ -236,7 +246,6 @@ static void DQS_calibration_process(void);
 static void ppc440sp_sdram_register_dump(void);
 int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
 void dcbz_area(u32 start_address, u32 num_bytes);
-void dflush(void);
 
 static u32 mfdcr_any(u32 dcr)
 {
@@ -387,9 +396,9 @@ long int initdram(int board_type)
        unsigned char spd1[MAX_SPD_BYTES];
        unsigned char *dimm_spd[MAXDIMMS];
        unsigned long dimm_populated[MAXDIMMS];
-       unsigned long num_dimm_banks;               /* on board dimm banks */
+       unsigned long num_dimm_banks;           /* on board dimm banks */
        unsigned long val;
-       ddr_cas_id_t  selected_cas;
+       ddr_cas_id_t selected_cas = DDR_CAS_5;  /* preset to silence compiler */
        int write_recovery;
        unsigned long dram_size = 0;
 
@@ -579,6 +588,13 @@ long int initdram(int board_type)
 
        ppc440sp_sdram_register_dump();
 
+       /*
+        * Clear potential errors resulting from auto-calibration.
+        * If not done, then we could get an interrupt later on when
+        * exceptions are enabled.
+        */
+       set_mcsr(get_mcsr());
+
        return dram_size;
 }
 
@@ -2070,7 +2086,7 @@ static void program_bxcf(unsigned long *dimm_populated,
                                if (num_banks == 4)
                                        ind = 0;
                                else
-                                       ind = 5;
+                                       ind = 5 << 8;
                                switch (num_col_addr) {
                                case 0x08:
                                        mode |= (SDRAM_BXCF_M_AM_0 + ind);
@@ -2125,6 +2141,7 @@ static void program_memory_queue(unsigned long *dimm_populated,
        unsigned long baseadd_size;
        unsigned long i;
        unsigned long bank_0_populated = 0;
+       unsigned long total_size = 0;
 
        /*------------------------------------------------------------------
         * Reset the rank_base_address.
@@ -2147,28 +2164,38 @@ static void program_memory_queue(unsigned long *dimm_populated,
                         * Set the sizes
                         *-----------------------------------------------------------------*/
                        baseadd_size = 0;
-                       rank_size_bytes = 4 * 1024 * 1024 * rank_size_id;
                        switch (rank_size_id) {
+                       case 0x01:
+                               baseadd_size |= SDRAM_RXBAS_SDSZ_1024;
+                               total_size = 1024;
+                               break;
                        case 0x02:
-                               baseadd_size |= SDRAM_RXBAS_SDSZ_8;
+                               baseadd_size |= SDRAM_RXBAS_SDSZ_2048;
+                               total_size = 2048;
                                break;
                        case 0x04:
-                               baseadd_size |= SDRAM_RXBAS_SDSZ_16;
+                               baseadd_size |= SDRAM_RXBAS_SDSZ_4096;
+                               total_size = 4096;
                                break;
                        case 0x08:
                                baseadd_size |= SDRAM_RXBAS_SDSZ_32;
+                               total_size = 32;
                                break;
                        case 0x10:
                                baseadd_size |= SDRAM_RXBAS_SDSZ_64;
+                               total_size = 64;
                                break;
                        case 0x20:
                                baseadd_size |= SDRAM_RXBAS_SDSZ_128;
+                               total_size = 128;
                                break;
                        case 0x40:
                                baseadd_size |= SDRAM_RXBAS_SDSZ_256;
+                               total_size = 256;
                                break;
                        case 0x80:
                                baseadd_size |= SDRAM_RXBAS_SDSZ_512;
+                               total_size = 512;
                                break;
                        default:
                                printf("DDR-SDRAM: DIMM %d memory queue configuration.\n",
@@ -2178,6 +2205,7 @@ static void program_memory_queue(unsigned long *dimm_populated,
                                printf("Replace the DIMM module with a supported DIMM.\n\n");
                                spd_ddr_init_hang ();
                        }
+                       rank_size_bytes = total_size << 20;
 
                        if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1))
                                bank_0_populated = 1;
@@ -2190,6 +2218,19 @@ static void program_memory_queue(unsigned long *dimm_populated,
                        }
                }
        }
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+       /*
+        * Enable high bandwidth access on 460EX/GT.
+        * This should/could probably be done on other
+        * PPC's too, like 440SPe.
+        * This is currently not used, but with this setup
+        * it is possible to use it later on in e.g. the Linux
+        * EMAC driver for performance gain.
+        */
+       mtdcr(SDRAM_PLBADDULL, 0x00000000); /* MQ0_BAUL */
+       mtdcr(SDRAM_PLBADDUHB, 0x00000008); /* MQ0_BAUH */
+#endif
 }
 
 /*-----------------------------------------------------------------------------+
@@ -2322,7 +2363,8 @@ static void program_ecc_addr(unsigned long start_address,
                } else {
                        /* ECC bit set method for cached memory */
                        dcbz_area(start_address, num_bytes);
-                       dflush();
+                       /* Write modified dcache lines back to memory */
+                       clean_dcache_range(start_address, start_address + num_bytes);
                }
 
                blank_string(strlen(str));
@@ -3027,9 +3069,127 @@ static void ppc440sp_sdram_register_dump(void)
        dcr_data = mfdcr(SDRAM_R3BAS);
        printf("        MQ3_B0BAS       = 0x%08X\n", dcr_data);
 }
-#else
+#else /* !defined(DEBUG) */
 static void ppc440sp_sdram_register_dump(void)
 {
 }
-#endif
-#endif /* CONFIG_SPD_EEPROM */
+#endif /* defined(DEBUG) */
+#elif defined(CONFIG_405EX)
+/*-----------------------------------------------------------------------------
+ * Function:   initdram
+ * Description: Configures the PPC405EX(r) DDR1/DDR2 SDRAM memory
+ *             banks. The configuration is performed using static, compile-
+ *             time parameters.
+ *---------------------------------------------------------------------------*/
+long initdram(int board_type)
+{
+       /*
+        * Only run this SDRAM init code once. For NAND booting
+        * targets like Kilauea, we call initdram() early from the
+        * 4k NAND booting image (CONFIG_NAND_SPL) from nand_boot().
+        * Later on the NAND U-Boot image runs (CONFIG_NAND_U_BOOT)
+        * which calls initdram() again. This time the controller
+        * mustn't be reconfigured again since we're already running
+        * from SDRAM.
+        */
+#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
+       unsigned long val;
+
+       /* Set Memory Bank Configuration Registers */
+
+       mtsdram(SDRAM_MB0CF, CFG_SDRAM0_MB0CF);
+       mtsdram(SDRAM_MB1CF, CFG_SDRAM0_MB1CF);
+       mtsdram(SDRAM_MB2CF, CFG_SDRAM0_MB2CF);
+       mtsdram(SDRAM_MB3CF, CFG_SDRAM0_MB3CF);
+
+       /* Set Memory Clock Timing Register */
+
+       mtsdram(SDRAM_CLKTR, CFG_SDRAM0_CLKTR);
+
+       /* Set Refresh Time Register */
+
+       mtsdram(SDRAM_RTR, CFG_SDRAM0_RTR);
+
+       /* Set SDRAM Timing Registers */
+
+       mtsdram(SDRAM_SDTR1, CFG_SDRAM0_SDTR1);
+       mtsdram(SDRAM_SDTR2, CFG_SDRAM0_SDTR2);
+       mtsdram(SDRAM_SDTR3, CFG_SDRAM0_SDTR3);
+
+       /* Set Mode and Extended Mode Registers */
+
+       mtsdram(SDRAM_MMODE, CFG_SDRAM0_MMODE);
+       mtsdram(SDRAM_MEMODE, CFG_SDRAM0_MEMODE);
+
+       /* Set Memory Controller Options 1 Register */
+
+       mtsdram(SDRAM_MCOPT1, CFG_SDRAM0_MCOPT1);
+
+       /* Set Manual Initialization Control Registers */
+
+       mtsdram(SDRAM_INITPLR0, CFG_SDRAM0_INITPLR0);
+       mtsdram(SDRAM_INITPLR1, CFG_SDRAM0_INITPLR1);
+       mtsdram(SDRAM_INITPLR2, CFG_SDRAM0_INITPLR2);
+       mtsdram(SDRAM_INITPLR3, CFG_SDRAM0_INITPLR3);
+       mtsdram(SDRAM_INITPLR4, CFG_SDRAM0_INITPLR4);
+       mtsdram(SDRAM_INITPLR5, CFG_SDRAM0_INITPLR5);
+       mtsdram(SDRAM_INITPLR6, CFG_SDRAM0_INITPLR6);
+       mtsdram(SDRAM_INITPLR7, CFG_SDRAM0_INITPLR7);
+       mtsdram(SDRAM_INITPLR8, CFG_SDRAM0_INITPLR8);
+       mtsdram(SDRAM_INITPLR9, CFG_SDRAM0_INITPLR9);
+       mtsdram(SDRAM_INITPLR10, CFG_SDRAM0_INITPLR10);
+       mtsdram(SDRAM_INITPLR11, CFG_SDRAM0_INITPLR11);
+       mtsdram(SDRAM_INITPLR12, CFG_SDRAM0_INITPLR12);
+       mtsdram(SDRAM_INITPLR13, CFG_SDRAM0_INITPLR13);
+       mtsdram(SDRAM_INITPLR14, CFG_SDRAM0_INITPLR14);
+       mtsdram(SDRAM_INITPLR15, CFG_SDRAM0_INITPLR15);
+
+       /* Set On-Die Termination Registers */
+
+       mtsdram(SDRAM_CODT, CFG_SDRAM0_CODT);
+       mtsdram(SDRAM_MODT0, CFG_SDRAM0_MODT0);
+       mtsdram(SDRAM_MODT1, CFG_SDRAM0_MODT1);
+
+       /* Set Write Timing Register */
+
+       mtsdram(SDRAM_WRDTR, CFG_SDRAM0_WRDTR);
+
+       /*
+        * Start Initialization by SDRAM0_MCOPT2[SREN] = 0 and
+        * SDRAM0_MCOPT2[IPTR] = 1
+        */
+
+       mtsdram(SDRAM_MCOPT2, (SDRAM_MCOPT2_SREN_EXIT |
+                              SDRAM_MCOPT2_IPTR_EXECUTE));
+
+       /*
+        * Poll SDRAM0_MCSTAT[MIC] for assertion to indicate the
+        * completion of initialization.
+        */
+
+       do {
+               mfsdram(SDRAM_MCSTAT, val);
+       } while ((val & SDRAM_MCSTAT_MIC_MASK) != SDRAM_MCSTAT_MIC_COMP);
+
+       /* Set Delay Control Registers */
+
+       mtsdram(SDRAM_DLCR, CFG_SDRAM0_DLCR);
+       mtsdram(SDRAM_RDCC, CFG_SDRAM0_RDCC);
+       mtsdram(SDRAM_RQDC, CFG_SDRAM0_RQDC);
+       mtsdram(SDRAM_RFDC, CFG_SDRAM0_RFDC);
+
+       /*
+        * Enable Controller by SDRAM0_MCOPT2[DCEN] = 1:
+        */
+
+       mfsdram(SDRAM_MCOPT2, val);
+       mtsdram(SDRAM_MCOPT2, val | SDRAM_MCOPT2_DCEN_ENABLE);
+
+#if defined(CONFIG_DDR_ECC)
+       ecc_init(CFG_SDRAM_BASE, CFG_MBYTES_SDRAM << 20);
+#endif /* defined(CONFIG_DDR_ECC) */
+#endif /* !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
+
+       return (CFG_MBYTES_SDRAM << 20);
+}
+#endif /* defined(CONFIG_SPD_EEPROM) && defined(CONFIG_440SP) || ... */