[U-Boot] [PATCH 1/6] Make DDR interleaving mode work correctly

Fix some bugs: 1. Correctly set intlv_ctl in cs_config. 2. Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled. 3. Set base_address and total memory for each ddr controller in memory controller interleaving mode.
Signed-off-by: Haiying Wang Haiying.Wang@freescale.com --- cpu/mpc8xxx/ddr/ctrl_regs.c | 61 +++++++++++++++++++++++++++++++------- cpu/mpc8xxx/ddr/main.c | 5 +++ include/asm-ppc/fsl_ddr_sdram.h | 12 +++++++ 3 files changed, 66 insertions(+), 12 deletions(-)
diff --git a/cpu/mpc8xxx/ddr/ctrl_regs.c b/cpu/mpc8xxx/ddr/ctrl_regs.c index e6c2a5c..6297141 100644 --- a/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -95,16 +95,10 @@ static void set_csn_config(int i, fsl_ddr_cfg_regs_t *ddr, col_bits_cs_n = dimm_params[i/2].n_col_addr - 8; }
- /* FIXME: intlv_en, intlv_ctl only on CS0_CONFIG */ - if (i != 0) { - intlv_en = 0; - intlv_ctl = 0; - } - ddr->cs[i].config = (0 | ((cs_n_en & 0x1) << 31) | ((intlv_en & 0x3) << 29) - | ((intlv_en & 0xf) << 24) + | ((intlv_ctl & 0xf) << 24) | ((ap_n_en & 0x1) << 23)
/* XXX: some implementation only have 1 bit starting at left */ @@ -874,8 +868,13 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { phys_size_t sa = 0; phys_size_t ea = 0; - if (popts->ba_intlv_ctl && i > 0) { - /* Don't set up boundaries if bank interleaving */ + + if (popts->ba_intlv_ctl && (i > 0) && + ((popts->ba_intlv_ctl & 0x60) != FSL_DDR_CS2_CS3 )) { + /* Don't set up boundaries for other CS + * other than CS0, if bank interleaving + * is enabled and not CS2+CS3 interleaved. + */ break; }
@@ -894,7 +893,9 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, * on each controller is twice the amount present on * each controller. */ - ea = (2 * common_dimm->total_mem >> dbw_cap_adj) - 1; + unsigned long long rank_density + = dimm_params[0].capacity; + ea = (2 * (rank_density >> dbw_cap_adj)) - 1; } else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) { /* @@ -906,8 +907,44 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, * controller needs to be programmed into its * respective CS0_BNDS. */ - sa = common_dimm->base_address; - ea = sa + (common_dimm->total_mem >> dbw_cap_adj) - 1; + unsigned long long rank_density + = dimm_params[i/2].rank_density; + 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; + 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&1)) { + sa = dimm_params[i/2].base_address; + ea = sa + (i * (rank_density >> + dbw_cap_adj)) - 1; + } + break; + case FSL_DDR_CS0_CS1: + /* CS0+CS1 interleaving, CS0_CNDS needs + * to be set + */ + sa = common_dimm->base_address; + ea = sa + (2 * (rank_density >> dbw_cap_adj))-1; + break; + case FSL_DDR_CS2_CS3: + /* CS2+CS3 interleaving*/ + if (i == 2) { + sa = dimm_params[i/2].base_address; + ea = sa + (2 * (rank_density >> + dbw_cap_adj)) - 1; + } + break; + default: /* No bank(chip-select) interleaving */ + break; + } } else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) { /* diff --git a/cpu/mpc8xxx/ddr/main.c b/cpu/mpc8xxx/ddr/main.c index c340d56..d26c5c5 100644 --- a/cpu/mpc8xxx/ddr/main.c +++ b/cpu/mpc8xxx/ddr/main.c @@ -179,6 +179,7 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,
if (*memctl_interleaving) { phys_addr_t addr; + phys_size_t total_mem_per_ctlr = 0;
/* * If interleaving between memory controllers, @@ -197,14 +198,18 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { addr = 0; + pinfo->common_timing_params[i].base_address = + (phys_addr_t)addr; 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 += (phys_addr_t)(cap >> dbw_cap_adj[i]); + total_mem_per_ctlr += cap >> dbw_cap_adj[i]; } } + pinfo->common_timing_params[0].total_mem = total_mem_per_ctlr; } else { /* * Simple linear assignment if memory diff --git a/include/asm-ppc/fsl_ddr_sdram.h b/include/asm-ppc/fsl_ddr_sdram.h index 8adde34..c1ea7cd 100644 --- a/include/asm-ppc/fsl_ddr_sdram.h +++ b/include/asm-ppc/fsl_ddr_sdram.h @@ -36,6 +36,18 @@ typedef ddr2_spd_eeprom_t generic_spd_eeprom_t; typedef ddr3_spd_eeprom_t generic_spd_eeprom_t; #endif
+/* define bank(chip select) interleaving mode */ +#define FSL_DDR_CS0_CS1 0x40 +#define FSL_DDR_CS2_CS3 0x20 +#define FSL_DDR_CS0_CS1_AND_CS2_CS3 (FSL_DDR_CS0_CS1 | FSL_DDR_CS2_CS3) +#define FSL_DDR_CS0_CS1_CS2_CS3 (FSL_DDR_CS0_CS1_AND_CS2_CS3 | 0x04) + +/* define memory controller interleaving mode */ +#define FSL_DDR_CACHE_LINE_INTERLEAVING 0x0 +#define FSL_DDR_PAGE_INTERLEAVING 0x1 +#define FSL_DDR_BANK_INTERLEAVING 0x2 +#define FSL_DDR_SUPERBANK_INTERLEAVING 0x3 + /* Record of register values computed */ typedef struct fsl_ddr_cfg_regs_s { struct {

If Kim and Jon approve, I'll pull these 6 patches into my 85xx-next branch.
On Fri, Oct 3, 2008 at 11:36 AM, Haiying Wang Haiying.Wang@freescale.com wrote:
Fix some bugs:
- Correctly set intlv_ctl in cs_config.
- Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled.
- Set base_address and total memory for each ddr controller in memory controller interleaving mode.
Signed-off-by: Haiying Wang Haiying.Wang@freescale.com
cpu/mpc8xxx/ddr/ctrl_regs.c | 61 +++++++++++++++++++++++++++++++------- cpu/mpc8xxx/ddr/main.c | 5 +++ include/asm-ppc/fsl_ddr_sdram.h | 12 +++++++ 3 files changed, 66 insertions(+), 12 deletions(-)
diff --git a/cpu/mpc8xxx/ddr/ctrl_regs.c b/cpu/mpc8xxx/ddr/ctrl_regs.c index e6c2a5c..6297141 100644 --- a/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -95,16 +95,10 @@ static void set_csn_config(int i, fsl_ddr_cfg_regs_t *ddr, col_bits_cs_n = dimm_params[i/2].n_col_addr - 8; }
/* FIXME: intlv_en, intlv_ctl only on CS0_CONFIG */
if (i != 0) {
intlv_en = 0;
intlv_ctl = 0;
}
ddr->cs[i].config = (0 | ((cs_n_en & 0x1) << 31) | ((intlv_en & 0x3) << 29)
| ((intlv_en & 0xf) << 24)
| ((intlv_ctl & 0xf) << 24) | ((ap_n_en & 0x1) << 23) /* XXX: some implementation only have 1 bit starting at left */
@@ -874,8 +868,13 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { phys_size_t sa = 0; phys_size_t ea = 0;
if (popts->ba_intlv_ctl && i > 0) {
/* Don't set up boundaries if bank interleaving */
if (popts->ba_intlv_ctl && (i > 0) &&
((popts->ba_intlv_ctl & 0x60) != FSL_DDR_CS2_CS3 )) {
/* Don't set up boundaries for other CS
* other than CS0, if bank interleaving
* is enabled and not CS2+CS3 interleaved.
*/ break; }
@@ -894,7 +893,9 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, * on each controller is twice the amount present on * each controller. */
ea = (2 * common_dimm->total_mem >> dbw_cap_adj) - 1;
unsigned long long rank_density
= dimm_params[0].capacity;
ea = (2 * (rank_density >> dbw_cap_adj)) - 1; } else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) { /*
@@ -906,8 +907,44 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, * controller needs to be programmed into its * respective CS0_BNDS. */
sa = common_dimm->base_address;
ea = sa + (common_dimm->total_mem >> dbw_cap_adj) - 1;
unsigned long long rank_density
= dimm_params[i/2].rank_density;
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;
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&1)) {
sa = dimm_params[i/2].base_address;
ea = sa + (i * (rank_density >>
dbw_cap_adj)) - 1;
}
break;
case FSL_DDR_CS0_CS1:
/* CS0+CS1 interleaving, CS0_CNDS needs
* to be set
*/
sa = common_dimm->base_address;
ea = sa + (2 * (rank_density >> dbw_cap_adj))-1;
break;
case FSL_DDR_CS2_CS3:
/* CS2+CS3 interleaving*/
if (i == 2) {
sa = dimm_params[i/2].base_address;
ea = sa + (2 * (rank_density >>
dbw_cap_adj)) - 1;
}
break;
default: /* No bank(chip-select) interleaving */
break;
} } else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) { /*
diff --git a/cpu/mpc8xxx/ddr/main.c b/cpu/mpc8xxx/ddr/main.c index c340d56..d26c5c5 100644 --- a/cpu/mpc8xxx/ddr/main.c +++ b/cpu/mpc8xxx/ddr/main.c @@ -179,6 +179,7 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,
if (*memctl_interleaving) { phys_addr_t addr;
phys_size_t total_mem_per_ctlr = 0; /* * If interleaving between memory controllers,
@@ -197,14 +198,18 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { addr = 0;
pinfo->common_timing_params[i].base_address =
(phys_addr_t)addr; 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 += (phys_addr_t)(cap >> dbw_cap_adj[i]);
total_mem_per_ctlr += cap >> dbw_cap_adj[i]; } }
pinfo->common_timing_params[0].total_mem = total_mem_per_ctlr; } else { /* * Simple linear assignment if memory
diff --git a/include/asm-ppc/fsl_ddr_sdram.h b/include/asm-ppc/fsl_ddr_sdram.h index 8adde34..c1ea7cd 100644 --- a/include/asm-ppc/fsl_ddr_sdram.h +++ b/include/asm-ppc/fsl_ddr_sdram.h @@ -36,6 +36,18 @@ typedef ddr2_spd_eeprom_t generic_spd_eeprom_t; typedef ddr3_spd_eeprom_t generic_spd_eeprom_t; #endif
+/* define bank(chip select) interleaving mode */ +#define FSL_DDR_CS0_CS1 0x40 +#define FSL_DDR_CS2_CS3 0x20 +#define FSL_DDR_CS0_CS1_AND_CS2_CS3 (FSL_DDR_CS0_CS1 | FSL_DDR_CS2_CS3) +#define FSL_DDR_CS0_CS1_CS2_CS3 (FSL_DDR_CS0_CS1_AND_CS2_CS3 | 0x04)
+/* define memory controller interleaving mode */ +#define FSL_DDR_CACHE_LINE_INTERLEAVING 0x0 +#define FSL_DDR_PAGE_INTERLEAVING 0x1 +#define FSL_DDR_BANK_INTERLEAVING 0x2 +#define FSL_DDR_SUPERBANK_INTERLEAVING 0x3
/* Record of register values computed */ typedef struct fsl_ddr_cfg_regs_s { struct { -- 1.6.0.2
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Andy Fleming wrote:
If Kim and Jon approve, I'll pull these 6 patches into my 85xx-next branch.
On Fri, Oct 3, 2008 at 11:36 AM, Haiying Wang Haiying.Wang@freescale.com wrote:
Fix some bugs:
- Correctly set intlv_ctl in cs_config.
- Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled.
- Set base_address and total memory for each ddr controller in memory controller interleaving mode.
Signed-off-by: Haiying Wang Haiying.Wang@freescale.com
Sounds good by me.
ACK.
jdl

On Oct 7, 2008, at 4:38 PM, Andy Fleming wrote:
If Kim and Jon approve, I'll pull these 6 patches into my 85xx-next branch.
The code doesn't impact 83xx and thus not sure why you need Kim's ack.
- k
On Fri, Oct 3, 2008 at 11:36 AM, Haiying Wang Haiying.Wang@freescale.com wrote:
Fix some bugs:
- Correctly set intlv_ctl in cs_config.
- Correctly set sa, ea in cs_bnds when bank interleaving mode is
enabled. 3. Set base_address and total memory for each ddr controller in memory controller interleaving mode.

On Wed, 8 Oct 2008 00:39:38 -0500 Kumar Gala galak@kernel.crashing.org wrote:
On Oct 7, 2008, at 4:38 PM, Andy Fleming wrote:
If Kim and Jon approve, I'll pull these 6 patches into my 85xx-next branch.
The code doesn't impact 83xx and thus not sure why you need Kim's ack.
ack
on Kumar's comment, that is :)
Kim

On Fri, Oct 3, 2008 at 11:36 AM, Haiying Wang Haiying.Wang@freescale.com wrote:
Fix some bugs:
- Correctly set intlv_ctl in cs_config.
- Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled.
- Set base_address and total memory for each ddr controller in memory controller interleaving mode.
Signed-off-by: Haiying Wang Haiying.Wang@freescale.com
Applied 1-6 to 85xx-next with some modifications from Kumar, thanks
participants (5)
-
Andy Fleming
-
Haiying Wang
-
Jon Loeliger
-
Kim Phillips
-
Kumar Gala