mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-27 17:41:34 +00:00
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>
This commit is contained in:
parent
1c9aa76bf9
commit
dbbbb3abef
3 changed files with 66 additions and 12 deletions
|
@ -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;
|
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
|
ddr->cs[i].config = (0
|
||||||
| ((cs_n_en & 0x1) << 31)
|
| ((cs_n_en & 0x1) << 31)
|
||||||
| ((intlv_en & 0x3) << 29)
|
| ((intlv_en & 0x3) << 29)
|
||||||
| ((intlv_en & 0xf) << 24)
|
| ((intlv_ctl & 0xf) << 24)
|
||||||
| ((ap_n_en & 0x1) << 23)
|
| ((ap_n_en & 0x1) << 23)
|
||||||
|
|
||||||
/* XXX: some implementation only have 1 bit starting at left */
|
/* 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++) {
|
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
|
||||||
phys_size_t sa = 0;
|
phys_size_t sa = 0;
|
||||||
phys_size_t ea = 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,7 +893,9 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
|
||||||
* on each controller is twice the amount present on
|
* on each controller is twice the amount present on
|
||||||
* each controller.
|
* 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) {
|
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
|
* controller needs to be programmed into its
|
||||||
* respective CS0_BNDS.
|
* respective CS0_BNDS.
|
||||||
*/
|
*/
|
||||||
sa = common_dimm->base_address;
|
unsigned long long rank_density
|
||||||
ea = sa + (common_dimm->total_mem >> dbw_cap_adj) - 1;
|
= 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) {
|
else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -179,6 +179,7 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,
|
||||||
|
|
||||||
if (*memctl_interleaving) {
|
if (*memctl_interleaving) {
|
||||||
phys_addr_t addr;
|
phys_addr_t addr;
|
||||||
|
phys_size_t total_mem_per_ctlr = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If interleaving between memory controllers,
|
* 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++) {
|
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
|
||||||
addr = 0;
|
addr = 0;
|
||||||
|
pinfo->common_timing_params[i].base_address =
|
||||||
|
(phys_addr_t)addr;
|
||||||
for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
|
for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
|
||||||
unsigned long long cap
|
unsigned long long cap
|
||||||
= pinfo->dimm_params[i][j].capacity;
|
= pinfo->dimm_params[i][j].capacity;
|
||||||
|
|
||||||
pinfo->dimm_params[i][j].base_address = addr;
|
pinfo->dimm_params[i][j].base_address = addr;
|
||||||
addr += (phys_addr_t)(cap >> dbw_cap_adj[i]);
|
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 {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Simple linear assignment if memory
|
* Simple linear assignment if memory
|
||||||
|
|
|
@ -36,6 +36,18 @@ typedef ddr2_spd_eeprom_t generic_spd_eeprom_t;
|
||||||
typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
|
typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
|
||||||
#endif
|
#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 */
|
/* Record of register values computed */
|
||||||
typedef struct fsl_ddr_cfg_regs_s {
|
typedef struct fsl_ddr_cfg_regs_s {
|
||||||
struct {
|
struct {
|
||||||
|
|
Loading…
Add table
Reference in a new issue