powerpc/mpc8xxx: Enable 3-way and 4-way DDR interleaving
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>
This commit is contained in:
parent
fcea30688f
commit
a4c66509f1
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
@ -15,13 +15,15 @@
|
||||
#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. */
|
||||
|
@ -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)
|
||||
|
@ -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: ");
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -1,5 +1,28 @@
|
||||
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 interleaving modes supported in cpu/8xxx/ddr/
|
||||
|
||||
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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user