powerpc/mpc8xxx: Enable 3-way and 4-way DDR interleaving
authorYork Sun <yorksun@freescale.com>
Fri, 17 Aug 2012 08:22:39 +0000 (08:22 +0000)
committerAndy Fleming <afleming@freescale.com>
Thu, 23 Aug 2012 17:16:55 +0000 (12:16 -0500)
Restructure DDR interleaving option to support 3 and 4 DDR controllers
for 2-, 3- and 4-way interleaving.

Signed-off-by: York Sun <yorksun@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
arch/powerpc/cpu/mpc85xx/cpu.c
arch/powerpc/cpu/mpc85xx/ddr-gen3.c
arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
arch/powerpc/cpu/mpc8xxx/ddr/main.c
arch/powerpc/cpu/mpc8xxx/ddr/options.c
arch/powerpc/cpu/mpc8xxx/ddr/util.c
arch/powerpc/include/asm/fsl_ddr_sdram.h
arch/powerpc/include/asm/fsl_law.h
arch/powerpc/include/asm/immap_85xx.h
doc/README.fsl-ddr

index 8d2ef9ffc72369666c747c385a88d6c7aa503cc1..5ddb29435c139a7f0541a59e4a859b83919408df 100644 (file)
@@ -430,10 +430,20 @@ static void dump_spd_ddr_reg(void)
                case 0:
                        ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
                        break;
-#ifdef CONFIG_SYS_MPC85xx_DDR2_ADDR
+#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
                case 1:
                        ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
                        break;
+#endif
+#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
+               case 2:
+                       ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
+                       break;
+#endif
+#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
+               case 3:
+                       ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR;
+                       break;
 #endif
                default:
                        printf("%s unexpected controller number = %u\n",
index 0761d70080ae613a6a8fcd570f057cc28ab0ccdb..ca4ed6264573cfd78d51ba066e1c6b87c41d1eb7 100644 (file)
@@ -32,9 +32,21 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
        case 0:
                ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
                break;
+#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
        case 1:
                ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
                break;
+#endif
+#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
+       case 2:
+               ddr = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
+               break;
+#endif
+#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
+       case 3:
+               ddr = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR;
+               break;
+#endif
        default:
                printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
                return;
index a8b2132f9032481fd76bfa4eba6203824a02089c..5938c44cec1c5f5ff38aaf3d77f1a9feaa651055 100644 (file)
@@ -151,8 +151,19 @@ static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
                if (dimm_params[dimm_number].n_ranks > 0) {
                        go_config = 1;
                        /* These fields only available in CS0_CONFIG */
-                       intlv_en = popts->memctl_interleaving;
-                       intlv_ctl = popts->memctl_interleaving_mode;
+                       if (!popts->memctl_interleaving)
+                               break;
+                       switch (popts->memctl_interleaving_mode) {
+                       case FSL_DDR_CACHE_LINE_INTERLEAVING:
+                       case FSL_DDR_PAGE_INTERLEAVING:
+                       case FSL_DDR_BANK_INTERLEAVING:
+                       case FSL_DDR_SUPERBANK_INTERLEAVING:
+                               intlv_en = popts->memctl_interleaving;
+                               intlv_ctl = popts->memctl_interleaving_mode;
+                               break;
+                       default:
+                               break;
+                       }
                }
                break;
        case 1:
@@ -1413,73 +1424,37 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 
        /* Chip Select Memory Bounds (CSn_BNDS) */
        for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
-               unsigned long long ea = 0, sa = 0;
+               unsigned long long ea, sa;
                unsigned int cs_per_dimm
                        = CONFIG_CHIP_SELECTS_PER_CTRL / CONFIG_DIMM_SLOTS_PER_CTLR;
                unsigned int dimm_number
                        = i / cs_per_dimm;
                unsigned long long rank_density
-                       = dimm_params[dimm_number].rank_density;
+                       = dimm_params[dimm_number].rank_density >> dbw_cap_adj;
 
-               if (((i == 1) && (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1)) ||
-                       ((i == 2) && (popts->ba_intlv_ctl & 0x04)) ||
-                       ((i == 3) && (popts->ba_intlv_ctl & FSL_DDR_CS2_CS3))) {
-                       /*
-                        * Don't set up boundaries for unused CS
-                        * cs1 for cs0_cs1, cs0_cs1_and_cs2_cs3, cs0_cs1_cs2_cs3
-                        * cs2 for cs0_cs1_cs2_cs3
-                        * cs3 for cs2_cs3, cs0_cs1_and_cs2_cs3, cs0_cs1_cs2_cs3
-                        * But we need to set the ODT_RD_CFG and
-                        * ODT_WR_CFG for CS1_CONFIG here.
-                        */
-                       set_csn_config(dimm_number, i, ddr, popts, dimm_params);
-                       continue;
-               }
                if (dimm_params[dimm_number].n_ranks == 0) {
                        debug("Skipping setup of CS%u "
                                "because n_ranks on DIMM %u is 0\n", i, dimm_number);
                        continue;
                }
-               if (popts->memctl_interleaving && popts->ba_intlv_ctl) {
-                       /*
-                        * This works superbank 2CS
-                        * There are 2 or more memory controllers configured
-                        * identically, memory is interleaved between them,
-                        * and each controller uses rank interleaving within
-                        * itself. Therefore the starting and ending address
-                        * on each controller is twice the amount present on
-                        * each controller. If any CS is not included in the
-                        * interleaving, the memory on that CS is not accssible
-                        * and the total memory size is reduced. The CS is also
-                        * disabled.
-                        */
-                       unsigned long long ctlr_density = 0;
+               if (popts->memctl_interleaving) {
                        switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
+                       case FSL_DDR_CS0_CS1_CS2_CS3:
+                               break;
                        case FSL_DDR_CS0_CS1:
                        case FSL_DDR_CS0_CS1_AND_CS2_CS3:
-                               ctlr_density = dimm_params[0].rank_density * 2;
                                if (i > 1)
                                        cs_en = 0;
                                break;
                        case FSL_DDR_CS2_CS3:
-                               ctlr_density = dimm_params[0].rank_density;
+                       default:
                                if (i > 0)
                                        cs_en = 0;
                                break;
-                       case FSL_DDR_CS0_CS1_CS2_CS3:
-                               /*
-                                * The four CS interleaving should have been verified by
-                                * populate_memctl_options()
-                                */
-                               ctlr_density = dimm_params[0].rank_density * 4;
-                               break;
-                       default:
-                               break;
                        }
-                       ea = (CONFIG_NUM_DDR_CONTROLLERS *
-                               (ctlr_density >> dbw_cap_adj)) - 1;
-               }
-               else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) {
+                       sa = common_dimm->base_address;
+                       ea = common_dimm->total_mem - 1;
+               } else if (!popts->memctl_interleaving) {
                        /*
                         * If memory interleaving between controllers is NOT
                         * enabled, the starting address for each memory
@@ -1491,49 +1466,40 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
                         */
                        switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
                        case FSL_DDR_CS0_CS1_CS2_CS3:
-                               /* CS0+CS1+CS2+CS3 interleaving, only CS0_CNDS
-                                * needs to be set.
-                                */
                                sa = common_dimm->base_address;
-                               ea = sa + (4 * (rank_density >> dbw_cap_adj))-1;
+                               ea = common_dimm->total_mem - 1;
                                break;
                        case FSL_DDR_CS0_CS1_AND_CS2_CS3:
-                               /* CS0+CS1 and CS2+CS3 interleaving, CS0_CNDS
-                                * and CS2_CNDS need to be set.
-                                */
-                               if ((i == 2) && (dimm_number == 0)) {
+                               if ((i >= 2) && (dimm_number == 0)) {
                                        sa = dimm_params[dimm_number].base_address +
-                                             2 * (rank_density >> dbw_cap_adj);
-                                       ea = sa + 2 * (rank_density >> dbw_cap_adj) - 1;
+                                             2 * rank_density;
+                                       ea = sa + 2 * rank_density - 1;
                                } else {
                                        sa = dimm_params[dimm_number].base_address;
-                                       ea = sa + (2 * (rank_density >>
-                                               dbw_cap_adj)) - 1;
+                                       ea = sa + 2 * rank_density - 1;
                                }
                                break;
                        case FSL_DDR_CS0_CS1:
-                               /* CS0+CS1 interleaving, CS0_CNDS needs
-                                * to be set
-                                */
                                if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
                                        sa = dimm_params[dimm_number].base_address;
-                                       ea = sa + (rank_density >> dbw_cap_adj) - 1;
-                                       sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
-                                       ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
+                                       ea = sa + rank_density - 1;
+                                       if (i != 1)
+                                               sa += (i % cs_per_dimm) * rank_density;
+                                       ea += (i % cs_per_dimm) * rank_density;
                                } else {
                                        sa = 0;
                                        ea = 0;
                                }
                                if (i == 0)
-                                       ea += (rank_density >> dbw_cap_adj);
+                                       ea += rank_density;
                                break;
                        case FSL_DDR_CS2_CS3:
-                               /* CS2+CS3 interleaving*/
                                if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
                                        sa = dimm_params[dimm_number].base_address;
-                                       ea = sa + (rank_density >> dbw_cap_adj) - 1;
-                                       sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
-                                       ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
+                                       ea = sa + rank_density - 1;
+                                       if (i != 3)
+                                               sa += (i % cs_per_dimm) * rank_density;
+                                       ea += (i % cs_per_dimm) * rank_density;
                                } else {
                                        sa = 0;
                                        ea = 0;
@@ -1542,38 +1508,18 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
                                        ea += (rank_density >> dbw_cap_adj);
                                break;
                        default:  /* No bank(chip-select) interleaving */
+                               sa = dimm_params[dimm_number].base_address;
+                               ea = sa + rank_density - 1;
+                               if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
+                                       sa += (i % cs_per_dimm) * rank_density;
+                                       ea += (i % cs_per_dimm) * rank_density;
+                               } else {
+                                       sa = 0;
+                                       ea = 0;
+                               }
                                break;
                        }
                }
-               else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) {
-                       /*
-                        * Only the rank on CS0 of each memory controller may
-                        * be used if memory controller interleaving is used
-                        * without rank interleaving within each memory
-                        * controller.  However, the ending address programmed
-                        * into each CS0 must be the sum of the amount of
-                        * memory in the two CS0 ranks.
-                        */
-                       if (i == 0) {
-                               ea = (2 * (rank_density >> dbw_cap_adj)) - 1;
-                       }
-
-               }
-               else if (!popts->memctl_interleaving && !popts->ba_intlv_ctl) {
-                       /*
-                        * No rank interleaving and no memory controller
-                        * interleaving.
-                        */
-                       sa = dimm_params[dimm_number].base_address;
-                       ea = sa + (rank_density >> dbw_cap_adj) - 1;
-                       if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
-                               sa += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
-                               ea += (i % cs_per_dimm) * (rank_density >> dbw_cap_adj);
-                       } else {
-                               sa = 0;
-                               ea = 0;
-                       }
-               }
 
                sa >>= 24;
                ea >>= 24;
index c2a03e334cfa50db43970aef9440de3601695565..4fd4f8fc33067ed8152498738739257866fd02b0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #include <common.h>
 #include <i2c.h>
 #include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_law.h>
 
 #include "ddr.h"
 
-extern void fsl_ddr_set_lawbar(
+void fsl_ddr_set_lawbar(
                const common_timing_params_t *memctl_common_params,
                unsigned int memctl_interleaved,
                unsigned int ctrl_num);
+void fsl_ddr_set_intl3r(const unsigned int granule_size);
 
 /* processor specific function */
 extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
@@ -51,6 +53,22 @@ u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
        [1][0] = SPD_EEPROM_ADDRESS3,   /* controller 2 */
        [1][1] = SPD_EEPROM_ADDRESS4,   /* controller 2 */
 };
+#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
+       [0][0] = SPD_EEPROM_ADDRESS1,   /* controller 1 */
+       [1][0] = SPD_EEPROM_ADDRESS2,   /* controller 2 */
+       [2][0] = SPD_EEPROM_ADDRESS3,   /* controller 3 */
+};
+#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
+       [0][0] = SPD_EEPROM_ADDRESS1,   /* controller 1 */
+       [0][1] = SPD_EEPROM_ADDRESS2,   /* controller 1 */
+       [1][0] = SPD_EEPROM_ADDRESS3,   /* controller 2 */
+       [1][1] = SPD_EEPROM_ADDRESS4,   /* controller 2 */
+       [2][0] = SPD_EEPROM_ADDRESS5,   /* controller 3 */
+       [2][1] = SPD_EEPROM_ADDRESS6,   /* controller 3 */
+};
+
 #endif
 
 static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
@@ -156,12 +174,12 @@ const char * step_to_string(unsigned int step) {
        return step_string_tbl[s];
 }
 
-int step_assign_addresses(fsl_ddr_info_t *pinfo,
-                         unsigned int dbw_cap_adj[],
-                         unsigned int *all_memctl_interleaving,
-                         unsigned int *all_ctlr_rank_interleaving)
+unsigned long long step_assign_addresses(fsl_ddr_info_t *pinfo,
+                         unsigned int dbw_cap_adj[])
 {
        int i, j;
+       unsigned long long total_mem, current_mem_base, total_ctlr_mem;
+       unsigned long long rank_density, ctlr_density = 0;
 
        /*
         * If a reduced data width is requested, but the SPD
@@ -220,86 +238,108 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,
                                "specified controller %u\n", i);
                        return 1;
                }
+               debug("dbw_cap_adj[%d]=%d\n", i, dbw_cap_adj[i]);
        }
 
-       j = 0;
-       for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
-               if (pinfo->memctl_opts[i].memctl_interleaving)
-                       j++;
-       /*
-        * Not support less than all memory controllers interleaving
-        * if more than two controllers
-        */
-       if (j == CONFIG_NUM_DDR_CONTROLLERS)
-               *all_memctl_interleaving = 1;
-
-       /* Check that all controllers are rank interleaving. */
-       j = 0;
-       for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
-               if (pinfo->memctl_opts[i].ba_intlv_ctl)
-                       j++;
-       /*
-        * All memory controllers must be populated to qualify for
-        * all controller rank interleaving
-        */
-        if (j == CONFIG_NUM_DDR_CONTROLLERS)
-               *all_ctlr_rank_interleaving = 1;
-
-       if (*all_memctl_interleaving) {
-               unsigned long long addr, total_mem_per_ctlr = 0;
-               /*
-                * If interleaving between memory controllers,
-                * make each controller start at a base address
-                * of 0.
-                *
-                * Also, if bank interleaving (chip select
-                * interleaving) is enabled on each memory
-                * controller, CS0 needs to be programmed to
-                * cover the entire memory range on that memory
-                * controller
-                *
-                * Bank interleaving also implies that each
-                * addressed chip select is identical in size.
-                */
-
+       current_mem_base = 0ull;
+       total_mem = 0;
+       if (pinfo->memctl_opts[0].memctl_interleaving) {
+               rank_density = pinfo->dimm_params[0][0].rank_density >>
+                                       dbw_cap_adj[0];
+               switch (pinfo->memctl_opts[0].ba_intlv_ctl &
+                                       FSL_DDR_CS0_CS1_CS2_CS3) {
+               case FSL_DDR_CS0_CS1_CS2_CS3:
+                       ctlr_density = 4 * rank_density;
+                       break;
+               case FSL_DDR_CS0_CS1:
+               case FSL_DDR_CS0_CS1_AND_CS2_CS3:
+                       ctlr_density = 2 * rank_density;
+                       break;
+               case FSL_DDR_CS2_CS3:
+               default:
+                       ctlr_density = rank_density;
+                       break;
+               }
+               debug("rank density is 0x%llx, ctlr density is 0x%llx\n",
+                       rank_density, ctlr_density);
                for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
-                       addr = 0;
-                       pinfo->common_timing_params[i].base_address = 0ull;
-                       for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
-                               unsigned long long cap
-                                       = pinfo->dimm_params[i][j].capacity;
-
-                               pinfo->dimm_params[i][j].base_address = addr;
-                               addr += cap >> dbw_cap_adj[i];
-                               total_mem_per_ctlr += cap >> dbw_cap_adj[i];
+                       if (pinfo->memctl_opts[i].memctl_interleaving) {
+                               switch (pinfo->memctl_opts[i].memctl_interleaving_mode) {
+                               case FSL_DDR_CACHE_LINE_INTERLEAVING:
+                               case FSL_DDR_PAGE_INTERLEAVING:
+                               case FSL_DDR_BANK_INTERLEAVING:
+                               case FSL_DDR_SUPERBANK_INTERLEAVING:
+                                       total_ctlr_mem = 2 * ctlr_density;
+                                       break;
+                               case FSL_DDR_3WAY_1KB_INTERLEAVING:
+                               case FSL_DDR_3WAY_4KB_INTERLEAVING:
+                               case FSL_DDR_3WAY_8KB_INTERLEAVING:
+                                       total_ctlr_mem = 3 * ctlr_density;
+                                       break;
+                               case FSL_DDR_4WAY_1KB_INTERLEAVING:
+                               case FSL_DDR_4WAY_4KB_INTERLEAVING:
+                               case FSL_DDR_4WAY_8KB_INTERLEAVING:
+                                       total_ctlr_mem = 4 * ctlr_density;
+                                       break;
+                               default:
+                                       panic("Unknown interleaving mode");
+                               }
+                               pinfo->common_timing_params[i].base_address =
+                                                       current_mem_base;
+                               pinfo->common_timing_params[i].total_mem =
+                                                       total_ctlr_mem;
+                               total_mem = current_mem_base + total_ctlr_mem;
+                               debug("ctrl %d base 0x%llx\n", i, current_mem_base);
+                               debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem);
+                       } else {
+                               /* when 3rd controller not interleaved */
+                               current_mem_base = total_mem;
+                               total_ctlr_mem = 0;
+                               pinfo->common_timing_params[i].base_address =
+                                                       current_mem_base;
+                               for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+                                       unsigned long long cap =
+                                               pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i];
+                                       pinfo->dimm_params[i][j].base_address =
+                                               current_mem_base;
+                                       debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base);
+                                       current_mem_base += cap;
+                                       total_ctlr_mem += cap;
+                               }
+                               debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem);
+                               pinfo->common_timing_params[i].total_mem =
+                                                       total_ctlr_mem;
+                               total_mem += total_ctlr_mem;
                        }
                }
-               pinfo->common_timing_params[0].total_mem = total_mem_per_ctlr;
        } else {
                /*
                 * Simple linear assignment if memory
                 * controllers are not interleaved.
                 */
-               unsigned long long cur_memsize = 0;
                for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
-                       u64 total_mem_per_ctlr = 0;
+                       total_ctlr_mem = 0;
                        pinfo->common_timing_params[i].base_address =
-                                               cur_memsize;
+                                               current_mem_base;
                        for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
                                /* Compute DIMM base addresses. */
                                unsigned long long cap =
-                                       pinfo->dimm_params[i][j].capacity;
+                                       pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i];
                                pinfo->dimm_params[i][j].base_address =
-                                       cur_memsize;
-                               cur_memsize += cap >> dbw_cap_adj[i];
-                               total_mem_per_ctlr += cap >> dbw_cap_adj[i];
+                                       current_mem_base;
+                               debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base);
+                               current_mem_base += cap;
+                               total_ctlr_mem += cap;
                        }
+                       debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem);
                        pinfo->common_timing_params[i].total_mem =
-                                                       total_mem_per_ctlr;
+                                                       total_ctlr_mem;
+                       total_mem += total_ctlr_mem;
                }
        }
+       debug("Total mem by %s is 0x%llx\n", __func__, total_mem);
 
-       return 0;
+       return total_mem;
 }
 
 unsigned long long
@@ -307,8 +347,6 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
                                       unsigned int size_only)
 {
        unsigned int i, j;
-       unsigned int all_controllers_memctl_interleaving = 0;
-       unsigned int all_controllers_rank_interleaving = 0;
        unsigned long long total_mem = 0;
 
        fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg;
@@ -346,8 +384,9 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
                                retval = compute_dimm_parameters(spd, pdimm, i);
 #ifdef CONFIG_SYS_DDR_RAW_TIMING
                                if (retval != 0) {
-                                       printf("SPD error! Trying fallback to "
-                                       "raw timing calculation\n");
+                                       printf("SPD error on controller %d! "
+                                       "Trying fallback to raw timing "
+                                       "calculation\n", i);
                                        fsl_ddr_get_dimm_params(pdimm, i, j);
                                }
 #else
@@ -407,17 +446,14 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
                                        &pinfo->memctl_opts[i],
                                        pinfo->dimm_params[i], i);
                }
-               check_interleaving_options(pinfo);
        case STEP_ASSIGN_ADDRESSES:
                /* STEP 5:  Assign addresses to chip selects */
-               step_assign_addresses(pinfo,
-                               dbw_capacity_adjust,
-                               &all_controllers_memctl_interleaving,
-                               &all_controllers_rank_interleaving);
+               check_interleaving_options(pinfo);
+               total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust);
 
        case STEP_COMPUTE_REGS:
                /* STEP 6:  compute controller register values */
-               debug("FSL Memory ctrl cg register computation\n");
+               debug("FSL Memory ctrl register computation\n");
                for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
                        if (timing_params[i].ndimms_present == 0) {
                                memset(&ddr_reg[i], 0,
@@ -437,21 +473,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
                break;
        }
 
-       /* Compute the total amount of memory. */
-
-       /*
-        * If bank interleaving but NOT memory controller interleaving
-        * CS_BNDS describe the quantity of memory on each memory
-        * controller, so the total is the sum across.
-        */
-       if (!all_controllers_memctl_interleaving
-           && all_controllers_rank_interleaving) {
-               total_mem = 0;
-               for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
-                       total_mem += timing_params[i].total_mem;
-               }
-
-       } else {
+       {
                /*
                 * Compute the amount of memory available just by
                 * looking for the highest valid CSn_BNDS value.
@@ -489,7 +511,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
 phys_size_t fsl_ddr_sdram(void)
 {
        unsigned int i;
-       unsigned int memctl_interleaved;
+       unsigned int law_memctl = LAW_TRGT_IF_DDR_1;
        unsigned long long total_memory;
        fsl_ddr_info_t info;
 
@@ -504,34 +526,6 @@ phys_size_t fsl_ddr_sdram(void)
 #endif
                total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0);
 
-       /* Check for memory controller interleaving. */
-       memctl_interleaved = 0;
-       for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
-               memctl_interleaved +=
-                       info.memctl_opts[i].memctl_interleaving;
-       }
-
-       if (memctl_interleaved) {
-               if (memctl_interleaved == CONFIG_NUM_DDR_CONTROLLERS) {
-                       debug("memctl interleaving\n");
-                       /*
-                        * Change the meaning of memctl_interleaved
-                        * to be "boolean".
-                        */
-                       memctl_interleaved = 1;
-               } else {
-                       printf("Warning: memctl interleaving not "
-                               "properly configured on all controllers\n");
-                       memctl_interleaved = 0;
-                       for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
-                               info.memctl_opts[i].memctl_interleaving = 0;
-                       debug("Recomputing with memctl_interleaving off.\n");
-                       total_memory = fsl_ddr_compute(&info,
-                                                      STEP_ASSIGN_ADDRESSES,
-                                                      0);
-               }
-       }
-
        /* Program configuration registers. */
        for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
                debug("Programming controller %u\n", i);
@@ -544,24 +538,69 @@ phys_size_t fsl_ddr_sdram(void)
                fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i);
        }
 
-       if (memctl_interleaved) {
-               const unsigned int ctrl_num = 0;
-
-               /* Only set LAWBAR1 if memory controller interleaving is on. */
-               fsl_ddr_set_lawbar(&info.common_timing_params[0],
-                                        memctl_interleaved, ctrl_num);
-       } else {
-               /*
-                * Memory controller interleaving is NOT on;
-                * set each lawbar individually.
-                */
-               for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+       /* program LAWs */
+       for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+               if (info.memctl_opts[i].memctl_interleaving) {
+                       switch (info.memctl_opts[i].memctl_interleaving_mode) {
+                       case FSL_DDR_CACHE_LINE_INTERLEAVING:
+                       case FSL_DDR_PAGE_INTERLEAVING:
+                       case FSL_DDR_BANK_INTERLEAVING:
+                       case FSL_DDR_SUPERBANK_INTERLEAVING:
+                               if (i == 0) {
+                                       law_memctl = LAW_TRGT_IF_DDR_INTRLV;
+                                       fsl_ddr_set_lawbar(&info.common_timing_params[i],
+                                               law_memctl, i);
+                               } else if (i == 2) {
+                                       law_memctl = LAW_TRGT_IF_DDR_INTLV_34;
+                                       fsl_ddr_set_lawbar(&info.common_timing_params[i],
+                                               law_memctl, i);
+                               }
+                               break;
+                       case FSL_DDR_3WAY_1KB_INTERLEAVING:
+                       case FSL_DDR_3WAY_4KB_INTERLEAVING:
+                       case FSL_DDR_3WAY_8KB_INTERLEAVING:
+                               law_memctl = LAW_TRGT_IF_DDR_INTLV_123;
+                               if (i == 0) {
+                                       fsl_ddr_set_intl3r(info.memctl_opts[i].memctl_interleaving_mode);
+                                       fsl_ddr_set_lawbar(&info.common_timing_params[i],
+                                               law_memctl, i);
+                               }
+                               break;
+                       case FSL_DDR_4WAY_1KB_INTERLEAVING:
+                       case FSL_DDR_4WAY_4KB_INTERLEAVING:
+                       case FSL_DDR_4WAY_8KB_INTERLEAVING:
+                               law_memctl = LAW_TRGT_IF_DDR_INTLV_1234;
+                               if (i == 0)
+                                       fsl_ddr_set_lawbar(&info.common_timing_params[i],
+                                               law_memctl, i);
+                               /* place holder for future 4-way interleaving */
+                               break;
+                       default:
+                               break;
+                       }
+               } else {
+                       switch (i) {
+                       case 0:
+                               law_memctl = LAW_TRGT_IF_DDR_1;
+                               break;
+                       case 1:
+                               law_memctl = LAW_TRGT_IF_DDR_2;
+                               break;
+                       case 2:
+                               law_memctl = LAW_TRGT_IF_DDR_3;
+                               break;
+                       case 3:
+                               law_memctl = LAW_TRGT_IF_DDR_4;
+                               break;
+                       default:
+                               break;
+                       }
                        fsl_ddr_set_lawbar(&info.common_timing_params[i],
-                                                0, i);
+                                       law_memctl, i);
                }
        }
 
-       debug("total_memory = %llu\n", total_memory);
+       debug("total_memory by %s = %llu\n", __func__, total_memory);
 
 #if !defined(CONFIG_PHYS_64BIT)
        /* Check for 4G or more.  Bad. */
index 00ec57be1fffdf4bad574dd7f343b536a0e34467..2923456ebe90715cb0b735758e4beb6e381c8aee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008, 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -790,46 +790,97 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
         * should be a subset of the requested configuration.
         */
 #if (CONFIG_NUM_DDR_CONTROLLERS > 1)
-       if (hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) {
-               if (pdimm[0].n_ranks == 0) {
-                       printf("There is no rank on CS0 for controller %d. Because only"
-                               " rank on CS0 and ranks chip-select interleaved with CS0"
-                               " are controller interleaved, force non memory "
-                               "controller interleaving\n", ctrl_num);
-                       popts->memctl_interleaving = 0;
-               } else {
-                       popts->memctl_interleaving = 1;
-                       /*
-                        * test null first. if CONFIG_HWCONFIG is not defined
-                        * hwconfig_arg_cmp returns non-zero
-                        */
-                       if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
-                                                   "null", buf)) {
-                               popts->memctl_interleaving = 0;
-                               debug("memory controller interleaving disabled.\n");
-                       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
-                                                        "ctlr_intlv",
-                                                        "cacheline", buf))
-                               popts->memctl_interleaving_mode =
-                                       FSL_DDR_CACHE_LINE_INTERLEAVING;
-                       else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
-                                                      "page", buf))
-                               popts->memctl_interleaving_mode =
-                                       FSL_DDR_PAGE_INTERLEAVING;
-                       else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
-                                                      "bank", buf))
-                               popts->memctl_interleaving_mode =
-                                       FSL_DDR_BANK_INTERLEAVING;
-                       else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
-                                                      "superbank", buf))
-                               popts->memctl_interleaving_mode =
-                                       FSL_DDR_SUPERBANK_INTERLEAVING;
-                       else {
-                               popts->memctl_interleaving = 0;
-                               printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
-                       }
-               }
+       if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf))
+               goto done;
+
+       if (pdimm[0].n_ranks == 0) {
+               printf("There is no rank on CS0 for controller %d.\n", ctrl_num);
+               popts->memctl_interleaving = 0;
+               goto done;
+       }
+       popts->memctl_interleaving = 1;
+       /*
+        * test null first. if CONFIG_HWCONFIG is not defined
+        * hwconfig_arg_cmp returns non-zero
+        */
+       if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
+                                   "null", buf)) {
+               popts->memctl_interleaving = 0;
+               debug("memory controller interleaving disabled.\n");
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "cacheline", buf)) {
+               popts->memctl_interleaving_mode =
+                       ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+                       0 : FSL_DDR_CACHE_LINE_INTERLEAVING;
+               popts->memctl_interleaving =
+                       ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+                       0 : 1;
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "page", buf)) {
+               popts->memctl_interleaving_mode =
+                       ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+                       0 : FSL_DDR_PAGE_INTERLEAVING;
+               popts->memctl_interleaving =
+                       ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+                       0 : 1;
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "bank", buf)) {
+               popts->memctl_interleaving_mode =
+                       ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+                       0 : FSL_DDR_BANK_INTERLEAVING;
+               popts->memctl_interleaving =
+                       ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+                       0 : 1;
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "superbank", buf)) {
+               popts->memctl_interleaving_mode =
+                       ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+                       0 : FSL_DDR_SUPERBANK_INTERLEAVING;
+               popts->memctl_interleaving =
+                       ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+                       0 : 1;
+#if (CONFIG_NUM_DDR_CONTROLLERS == 3)
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "3way_1KB", buf)) {
+               popts->memctl_interleaving_mode =
+                       FSL_DDR_3WAY_1KB_INTERLEAVING;
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "3way_4KB", buf)) {
+               popts->memctl_interleaving_mode =
+                       FSL_DDR_3WAY_4KB_INTERLEAVING;
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "3way_8KB", buf)) {
+               popts->memctl_interleaving_mode =
+                       FSL_DDR_3WAY_8KB_INTERLEAVING;
+#elif (CONFIG_NUM_DDR_CONTROLLERS == 4)
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "4way_1KB", buf)) {
+               popts->memctl_interleaving_mode =
+                       FSL_DDR_4WAY_1KB_INTERLEAVING;
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "4way_4KB", buf)) {
+               popts->memctl_interleaving_mode =
+                       FSL_DDR_4WAY_4KB_INTERLEAVING;
+       } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+                                       "ctlr_intlv",
+                                       "4way_8KB", buf)) {
+               popts->memctl_interleaving_mode =
+                       FSL_DDR_4WAY_8KB_INTERLEAVING;
+#endif
+       } else {
+               popts->memctl_interleaving = 0;
+               printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
        }
+done:
 #endif
        if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&
                (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
@@ -859,20 +910,20 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
                                popts->ba_intlv_ctl = 0;
                                printf("Not enough bank(chip-select) for "
                                        "CS0+CS1+CS2+CS3 on controller %d, "
-                                       "force non-interleaving!\n", ctrl_num);
+                                       "interleaving disabled!\n", ctrl_num);
                        }
 #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
                        if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) {
                                popts->ba_intlv_ctl = 0;
                                printf("Not enough bank(chip-select) for "
                                        "CS0+CS1+CS2+CS3 on controller %d, "
-                                       "force non-interleaving!\n", ctrl_num);
+                                       "interleaving disabled!\n", ctrl_num);
                        }
                        if (pdimm[0].capacity != pdimm[1].capacity) {
                                popts->ba_intlv_ctl = 0;
                                printf("Not identical DIMM size for "
                                        "CS0+CS1+CS2+CS3 on controller %d, "
-                                       "force non-interleaving!\n", ctrl_num);
+                                       "interleaving disabled!\n", ctrl_num);
                        }
 #endif
                        break;
@@ -881,7 +932,7 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
                                popts->ba_intlv_ctl = 0;
                                printf("Not enough bank(chip-select) for "
                                        "CS0+CS1 on controller %d, "
-                                       "force non-interleaving!\n", ctrl_num);
+                                       "interleaving disabled!\n", ctrl_num);
                        }
                        break;
                case FSL_DDR_CS2_CS3:
@@ -889,13 +940,13 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
                        if (pdimm[0].n_ranks < 4) {
                                popts->ba_intlv_ctl = 0;
                                printf("Not enough bank(chip-select) for CS2+CS3 "
-                                       "on controller %d, force non-interleaving!\n", ctrl_num);
+                                       "on controller %d, interleaving disabled!\n", ctrl_num);
                        }
 #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
                        if (pdimm[1].n_ranks < 2) {
                                popts->ba_intlv_ctl = 0;
                                printf("Not enough bank(chip-select) for CS2+CS3 "
-                                       "on controller %d, force non-interleaving!\n", ctrl_num);
+                                       "on controller %d, interleaving disabled!\n", ctrl_num);
                        }
 #endif
                        break;
@@ -905,14 +956,14 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
                                popts->ba_intlv_ctl = 0;
                                printf("Not enough bank(CS) for CS0+CS1 and "
                                        "CS2+CS3 on controller %d, "
-                                       "force non-interleaving!\n", ctrl_num);
+                                       "interleaving disabled!\n", ctrl_num);
                        }
 #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
                        if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) {
                                popts->ba_intlv_ctl = 0;
                                printf("Not enough bank(CS) for CS0+CS1 and "
                                        "CS2+CS3 on controller %d, "
-                                       "force non-interleaving!\n", ctrl_num);
+                                       "interleaving disabled!\n", ctrl_num);
                        }
 #endif
                        break;
@@ -954,33 +1005,73 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 
 void check_interleaving_options(fsl_ddr_info_t *pinfo)
 {
-       int i, j, check_n_ranks, intlv_fixed = 0;
+       int i, j, k, check_n_ranks, intlv_invalid = 0;
+       unsigned int check_intlv, check_n_row_addr, check_n_col_addr;
        unsigned long long check_rank_density;
+       struct dimm_params_s *dimm;
        /*
         * Check if all controllers are configured for memory
         * controller interleaving. Identical dimms are recommended. At least
-        * the size should be checked.
+        * the size, row and col address should be checked.
         */
        j = 0;
        check_n_ranks = pinfo->dimm_params[0][0].n_ranks;
        check_rank_density = pinfo->dimm_params[0][0].rank_density;
+       check_n_row_addr =  pinfo->dimm_params[0][0].n_row_addr;
+       check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr;
+       check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode;
        for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
-               if ((pinfo->memctl_opts[i].memctl_interleaving) && \
-                   (check_rank_density == pinfo->dimm_params[i][0].rank_density) && \
-                   (check_n_ranks == pinfo->dimm_params[i][0].n_ranks)) {
+               dimm = &pinfo->dimm_params[i][0];
+               if (!pinfo->memctl_opts[i].memctl_interleaving) {
+                       continue;
+               } else if (((check_rank_density != dimm->rank_density) ||
+                    (check_n_ranks != dimm->n_ranks) ||
+                    (check_n_row_addr != dimm->n_row_addr) ||
+                    (check_n_col_addr != dimm->n_col_addr) ||
+                    (check_intlv !=
+                       pinfo->memctl_opts[i].memctl_interleaving_mode))){
+                       intlv_invalid = 1;
+                       break;
+               } else {
                        j++;
                }
+
        }
-       if (j != CONFIG_NUM_DDR_CONTROLLERS) {
+       if (intlv_invalid) {
                for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
-                       if (pinfo->memctl_opts[i].memctl_interleaving) {
+                       pinfo->memctl_opts[i].memctl_interleaving = 0;
+               printf("Not all DIMMs are identical. "
+                       "Memory controller interleaving disabled.\n");
+       } else {
+               switch (check_intlv) {
+               case FSL_DDR_CACHE_LINE_INTERLEAVING:
+               case FSL_DDR_PAGE_INTERLEAVING:
+               case FSL_DDR_BANK_INTERLEAVING:
+               case FSL_DDR_SUPERBANK_INTERLEAVING:
+                       if (3 == CONFIG_NUM_DDR_CONTROLLERS)
+                               k = 2;
+                       else
+                               k = CONFIG_NUM_DDR_CONTROLLERS;
+                       break;
+               case FSL_DDR_3WAY_1KB_INTERLEAVING:
+               case FSL_DDR_3WAY_4KB_INTERLEAVING:
+               case FSL_DDR_3WAY_8KB_INTERLEAVING:
+               case FSL_DDR_4WAY_1KB_INTERLEAVING:
+               case FSL_DDR_4WAY_4KB_INTERLEAVING:
+               case FSL_DDR_4WAY_8KB_INTERLEAVING:
+               default:
+                       k = CONFIG_NUM_DDR_CONTROLLERS;
+                       break;
+               }
+               debug("%d of %d controllers are interleaving.\n", j, k);
+               if (j != k) {
+                       for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
                                pinfo->memctl_opts[i].memctl_interleaving = 0;
-                               intlv_fixed = 1;
-                       }
-               if (intlv_fixed)
-                       printf("Not all DIMMs are identical in size. "
-                               "Memory controller interleaving disabled.\n");
+                       printf("Not all controllers have compatible "
+                               "interleaving mode. All disabled.\n");
+               }
        }
+       debug("Checking interleaving options completed\n");
 }
 
 int fsl_use_spd(void)
index eb6a17a8503de6732db1e3489eabd1adbd5215a4..664ad09298f1ae5836afc7bfb7ef8fdac68fc419 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -79,7 +79,7 @@ unsigned int mclk_to_picos(unsigned int mclk)
 
 void
 __fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
-                          unsigned int memctl_interleaved,
+                          unsigned int law_memctl,
                           unsigned int ctrl_num)
 {
        unsigned long long base = memctl_common_params->base_address;
@@ -98,28 +98,13 @@ __fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
        if ((base + size) >= CONFIG_MAX_MEM_MAPPED)
                size = CONFIG_MAX_MEM_MAPPED - base;
 #endif
-
-       if (ctrl_num == 0) {
-               /*
-                * Set up LAW for DDR controller 1 space.
-                */
-               unsigned int lawbar1_target_id = memctl_interleaved
-                       ? LAW_TRGT_IF_DDR_INTRLV : LAW_TRGT_IF_DDR_1;
-
-               if (set_ddr_laws(base, size, lawbar1_target_id) < 0) {
-                       printf("%s: ERROR (ctrl #0, intrlv=%d)\n", __func__,
-                               memctl_interleaved);
-                       return ;
-               }
-       } else if (ctrl_num == 1) {
-               if (set_ddr_laws(base, size, LAW_TRGT_IF_DDR_2) < 0) {
-                       printf("%s: ERROR (ctrl #1)\n", __func__);
-                       return ;
-               }
-       } else {
-               printf("%s: unexpected DDR controller number (%u)\n", __func__,
-                       ctrl_num);
+       if (set_ddr_laws(base, size, law_memctl) < 0) {
+               printf("%s: ERROR (ctrl #%d, TRGT ID=%x)\n", __func__, ctrl_num,
+                       law_memctl);
+               return ;
        }
+       debug("setup ddr law base = 0x%llx, size 0x%llx, TRGT_ID 0x%x\n",
+               base, size, law_memctl);
 }
 
 __attribute__((weak, alias("__fsl_ddr_set_lawbar"))) void
@@ -127,6 +112,15 @@ fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
                         unsigned int memctl_interleaved,
                         unsigned int ctrl_num);
 
+void fsl_ddr_set_intl3r(const unsigned int granule_size)
+{
+#ifdef CONFIG_E6500
+       u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004);
+       *mcintl3r = 0x80000000 | (granule_size & 0x1f);
+       debug("Enable MCINTL3R with granule size 0x%x\n", granule_size);
+#endif
+}
+
 void board_add_ram_info(int use_default)
 {
 #if defined(CONFIG_MPC83xx)
@@ -137,6 +131,9 @@ void board_add_ram_info(int use_default)
 #elif defined(CONFIG_MPC86xx)
        ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC86xx_DDR_ADDR);
 #endif
+#if    defined(CONFIG_E6500) && (CONFIG_NUM_DDR_CONTROLLERS == 3)
+       u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004);
+#endif
 #if (CONFIG_NUM_DDR_CONTROLLERS > 1)
        uint32_t cs0_config = in_be32(&ddr->cs0_config);
 #endif
@@ -180,7 +177,29 @@ void board_add_ram_info(int use_default)
        else
                puts(", ECC off)");
 
-#if (CONFIG_NUM_DDR_CONTROLLERS > 1)
+#if (CONFIG_NUM_DDR_CONTROLLERS == 3)
+#ifdef CONFIG_E6500
+       if (*mcintl3r & 0x80000000) {
+               puts("\n");
+               puts("       DDR Controller Interleaving Mode: ");
+               switch (*mcintl3r & 0x1f) {
+               case FSL_DDR_3WAY_1KB_INTERLEAVING:
+                       puts("3-way 1KB");
+                       break;
+               case FSL_DDR_3WAY_4KB_INTERLEAVING:
+                       puts("3-way 4KB");
+                       break;
+               case FSL_DDR_3WAY_8KB_INTERLEAVING:
+                       puts("3-way 8KB");
+                       break;
+               default:
+                       puts("3-way UNKNOWN");
+                       break;
+               }
+       }
+#endif
+#endif
+#if (CONFIG_NUM_DDR_CONTROLLERS >= 2)
        if (cs0_config & 0x20000000) {
                puts("\n");
                puts("       DDR Controller Interleaving Mode: ");
index 157ae246354a312f5c9e45a86645664216a16c2e..e271342f089289d0b2f9fe98d7799451597de45c 100644 (file)
@@ -76,6 +76,13 @@ typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #define FSL_DDR_PAGE_INTERLEAVING      0x1
 #define FSL_DDR_BANK_INTERLEAVING      0x2
 #define FSL_DDR_SUPERBANK_INTERLEAVING 0x3
+#define FSL_DDR_3WAY_1KB_INTERLEAVING  0xA
+#define FSL_DDR_3WAY_4KB_INTERLEAVING  0xC
+#define FSL_DDR_3WAY_8KB_INTERLEAVING  0xD
+/* placeholder for 4-way interleaving */
+#define FSL_DDR_4WAY_1KB_INTERLEAVING  0x1A
+#define FSL_DDR_4WAY_4KB_INTERLEAVING  0x1C
+#define FSL_DDR_4WAY_8KB_INTERLEAVING  0x1D
 
 /* DDR_SDRAM_CFG - DDR SDRAM Control Configuration
  */
index dc3985e9cca71de2dbd235d522a66b5e841b50b8..f9cec8ea441a298abe04ed47615e453b392cd328 100644 (file)
@@ -60,8 +60,12 @@ enum law_trgt_if {
 
        LAW_TRGT_IF_DDR_1 = 0x10,
        LAW_TRGT_IF_DDR_2 = 0x11,       /* 2nd controller */
+       LAW_TRGT_IF_DDR_3 = 0x12,
+       LAW_TRGT_IF_DDR_4 = 0x13,
        LAW_TRGT_IF_DDR_INTRLV = 0x14,
-
+       LAW_TRGT_IF_DDR_INTLV_34 = 0x15,
+       LAW_TRGT_IF_DDR_INTLV_123 = 0x17,
+       LAW_TRGT_IF_DDR_INTLV_1234 = 0x16,
        LAW_TRGT_IF_BMAN = 0x18,
        LAW_TRGT_IF_DCSR = 0x1d,
        LAW_TRGT_IF_LBC = 0x1f,
@@ -87,6 +91,12 @@ enum law_trgt_if {
        LAW_TRGT_IF_DPAA_SWP_SRAM = 0x0e,
        LAW_TRGT_IF_DDR = 0x0f,
        LAW_TRGT_IF_DDR_2 = 0x16,       /* 2nd controller */
+       /* place holder for 3-way and 4-way interleaving */
+       LAW_TRGT_IF_DDR_3,
+       LAW_TRGT_IF_DDR_4,
+       LAW_TRGT_IF_DDR_INTLV_34,
+       LAW_TRGT_IF_DDR_INTLV_123,
+       LAW_TRGT_IF_DDR_INTLV_1234,
 };
 #define LAW_TRGT_IF_DDR_1      LAW_TRGT_IF_DDR
 #define LAW_TRGT_IF_PCI_1      LAW_TRGT_IF_PCI
index 412244eaad4169e4c0358bde392c20ca0b8550d7..7de33a7dded0f980672bbff09ad4a99d72af9e6b 100644 (file)
@@ -2621,6 +2621,7 @@ struct ccsr_rman {
 #define CONFIG_SYS_FSL_CORENET_CCM_OFFSET      0x0000
 #define CONFIG_SYS_MPC85xx_DDR_OFFSET          0x8000
 #define CONFIG_SYS_MPC85xx_DDR2_OFFSET         0x9000
+#define CONFIG_SYS_MPC85xx_DDR3_OFFSET         0xA000
 #define CONFIG_SYS_FSL_CORENET_CLK_OFFSET      0xE1000
 #define CONFIG_SYS_FSL_CORENET_RCPM_OFFSET     0xE2000
 #define CONFIG_SYS_FSL_CORENET_SERDES_OFFSET   0xEA000
@@ -2740,6 +2741,8 @@ struct ccsr_rman {
        (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR_OFFSET)
 #define CONFIG_SYS_MPC85xx_DDR2_ADDR \
        (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR2_OFFSET)
+#define CONFIG_SYS_MPC85xx_DDR3_ADDR \
+       (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR3_OFFSET)
 #define CONFIG_SYS_LBC_ADDR \
        (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_LBC_OFFSET)
 #define CONFIG_SYS_IFC_ADDR \
index 5e21658765958b0812d8037e80497d772fe4aa7f..f94b56f628cc369a7927a3a683bdf405363a0767 100644 (file)
@@ -1,5 +1,28 @@
-
-Table of interleaving modes supported in cpu/8xxx/ddr/
+Table of interleaving 2-4 controllers
+=====================================
+  +--------------+-----------------------------------------------------------+
+  |Configuration |                    Memory Controller                      |
+  |              |       1              2              3             4       |
+  |--------------+--------------+--------------+-----------------------------+
+  | Two memory   | Not Intlv'ed | Not Intlv'ed |                             |
+  | complexes    +--------------+--------------+                             |
+  |              |      2-way Intlv'ed         |                             |
+  |--------------+--------------+--------------+--------------+              |
+  |              | Not Intlv'ed | Not Intlv'ed | Not Intlv'ed |              |
+  | Three memory +--------------+--------------+--------------+              |
+  | complexes    |         2-way Intlv'ed      | Not Intlv'ed |              |
+  |              +-----------------------------+--------------+              |
+  |              |                  3-way Intlv'ed            |              |
+  +--------------+--------------+--------------+--------------+--------------+
+  |              | Not Intlv'ed | Not Intlv'ed | Not Intlv'ed | Not Intlv'ed |
+  | Four memory  +--------------+--------------+--------------+--------------+
+  | complexes    |       2-way Intlv'ed        |       2-way Intlv'ed        |
+  |              +-----------------------------+-----------------------------+
+  |              |                      4-way Intlv'ed                       |
+  +--------------+-----------------------------------------------------------+
+
+
+Table of 2-way interleaving modes supported in cpu/8xxx/ddr/
 ======================================================
   +-------------+---------------------------------------------------------+
   |            |                   Rank Interleaving                     |
@@ -56,6 +79,15 @@ The ways to configure the ddr interleaving mode
   # superbank
   setenv hwconfig "fsl_ddr:ctlr_intlv=superbank"
 
+  # 1KB 3-way interleaving
+  setenv hwconfig "fsl_ddr:ctlr_intlv=3way_1KB"
+
+  # 4KB 3-way interleaving
+  setenv hwconfig "fsl_ddr:ctlr_intlv=3way_4KB"
+
+  # 8KB 3-way interleaving
+  setenv hwconfig "fsl_ddr:ctlr_intlv=3way_8KB"
+
   # disable bank (chip-select) interleaving
   setenv hwconfig "fsl_ddr:bank_intlv=null"