driver/ddr: Restruct driver to allow standalone memory space

U-boot has been initializing DDR for the main memory. The presumption
is the memory stays as a big continuous block, either linear or
interleaved. This change is to support putting some DDR controllers
to separated space without counting into main memory. The standalone
memory controller could use different number of DIMM slots.

Signed-off-by: York Sun <yorksun@freescale.com>
This commit is contained in:
York Sun 2014-08-01 15:51:00 -07:00
parent e211c12e77
commit 1d71efbb03
8 changed files with 240 additions and 110 deletions

6
README
View file

@ -538,6 +538,12 @@ The following options need to be configured:
interleaving mode, handled by Dickens for Freescale layerscape interleaving mode, handled by Dickens for Freescale layerscape
SoCs with ARM core. SoCs with ARM core.
CONFIG_SYS_FSL_DDR_MAIN_NUM_CTRLS
Number of controllers used as main memory.
CONFIG_SYS_FSL_OTHER_DDR_NUM_CTRLS
Number of controllers used for other than main memory.
- Intel Monahans options: - Intel Monahans options:
CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO

View file

@ -441,7 +441,7 @@ phys_size_t initdram(int board_type)
/* Board-specific functions defined in each board's ddr.c */ /* Board-specific functions defined in each board's ddr.c */
void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
unsigned int ctrl_num); unsigned int ctrl_num, unsigned int dimm_slots_per_ctrl);
void read_tlbcam_entry(int idx, u32 *valid, u32 *tsize, unsigned long *epn, void read_tlbcam_entry(int idx, u32 *valid, u32 *tsize, unsigned long *epn,
phys_addr_t *rpn); phys_addr_t *rpn);
unsigned int unsigned int
@ -459,7 +459,7 @@ static void dump_spd_ddr_reg(void)
spd[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR]; spd[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR];
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
fsl_ddr_get_spd(spd[i], i); fsl_ddr_get_spd(spd[i], i, CONFIG_DIMM_SLOTS_PER_CTLR);
puts("SPD data of all dimms (zero vaule is omitted)...\n"); puts("SPD data of all dimms (zero vaule is omitted)...\n");
puts("Byte (hex) "); puts("Byte (hex) ");

View file

@ -113,7 +113,7 @@ compute_ranksize(const struct ddr4_spd_eeprom_s *spd)
#define spd_to_ps(mtb, ftb) \ #define spd_to_ps(mtb, ftb) \
(mtb * pdimm->mtb_ps + (ftb * pdimm->ftb_10th_ps) / 10) (mtb * pdimm->mtb_ps + (ftb * pdimm->ftb_10th_ps) / 10)
/* /*
* ddr_compute_dimm_parameters for DDR3 SPD * ddr_compute_dimm_parameters for DDR4 SPD
* *
* Compute DIMM parameters based upon the SPD information in spd. * Compute DIMM parameters based upon the SPD information in spd.
* Writes the results to the dimm_params_t structure pointed by pdimm. * Writes the results to the dimm_params_t structure pointed by pdimm.
@ -165,17 +165,17 @@ ddr_compute_dimm_parameters(const generic_spd_eeprom_t *spd,
+ pdimm->ec_sdram_width; + pdimm->ec_sdram_width;
pdimm->device_width = 1 << ((spd->organization & 0x7) + 2); pdimm->device_width = 1 << ((spd->organization & 0x7) + 2);
/* These are the types defined by the JEDEC DDR3 SPD spec */ /* These are the types defined by the JEDEC SPD spec */
pdimm->mirrored_dimm = 0; pdimm->mirrored_dimm = 0;
pdimm->registered_dimm = 0; pdimm->registered_dimm = 0;
switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) { switch (spd->module_type & DDR4_SPD_MODULETYPE_MASK) {
case DDR3_SPD_MODULETYPE_RDIMM: case DDR4_SPD_MODULETYPE_RDIMM:
/* Registered/buffered DIMMs */ /* Registered/buffered DIMMs */
pdimm->registered_dimm = 1; pdimm->registered_dimm = 1;
break; break;
case DDR3_SPD_MODULETYPE_UDIMM: case DDR4_SPD_MODULETYPE_UDIMM:
case DDR3_SPD_MODULETYPE_SO_DIMM: case DDR4_SPD_MODULETYPE_SO_DIMM:
/* Unbuffered DIMMs */ /* Unbuffered DIMMs */
if (spd->mod_section.unbuffered.addr_mapping & 0x1) if (spd->mod_section.unbuffered.addr_mapping & 0x1)
pdimm->mirrored_dimm = 1; pdimm->mirrored_dimm = 1;

View file

@ -135,7 +135,7 @@ __attribute__((weak, alias("__get_spd")))
void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address); void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address);
void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
unsigned int ctrl_num) unsigned int ctrl_num, unsigned int dimm_slots_per_ctrl)
{ {
unsigned int i; unsigned int i;
unsigned int i2c_address = 0; unsigned int i2c_address = 0;
@ -145,14 +145,14 @@ void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
return; return;
} }
for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { for (i = 0; i < dimm_slots_per_ctrl; i++) {
i2c_address = spd_i2c_addr[ctrl_num][i]; i2c_address = spd_i2c_addr[ctrl_num][i];
get_spd(&(ctrl_dimms_spd[i]), i2c_address); get_spd(&(ctrl_dimms_spd[i]), i2c_address);
} }
} }
#else #else
void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
unsigned int ctrl_num) unsigned int ctrl_num, unsigned int dimm_slots_per_ctrl)
{ {
} }
#endif /* SPD_EEPROM_ADDRESSx */ #endif /* SPD_EEPROM_ADDRESSx */
@ -231,9 +231,11 @@ const char * step_to_string(unsigned int step) {
static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo, static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo,
unsigned int dbw_cap_adj[]) unsigned int dbw_cap_adj[])
{ {
int i, j; unsigned int i, j;
unsigned long long total_mem, current_mem_base, total_ctlr_mem; unsigned long long total_mem, current_mem_base, total_ctlr_mem;
unsigned long long rank_density, ctlr_density = 0; unsigned long long rank_density, ctlr_density = 0;
unsigned int first_ctrl = pinfo->first_ctrl;
unsigned int last_ctrl = first_ctrl + pinfo->num_ctrls - 1;
/* /*
* If a reduced data width is requested, but the SPD * If a reduced data width is requested, but the SPD
@ -241,7 +243,7 @@ static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo,
* computed dimm capacities accordingly before * computed dimm capacities accordingly before
* assigning addresses. * assigning addresses.
*/ */
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
unsigned int found = 0; unsigned int found = 0;
switch (pinfo->memctl_opts[i].data_bus_width) { switch (pinfo->memctl_opts[i].data_bus_width) {
@ -295,12 +297,12 @@ static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo,
debug("dbw_cap_adj[%d]=%d\n", i, dbw_cap_adj[i]); debug("dbw_cap_adj[%d]=%d\n", i, dbw_cap_adj[i]);
} }
current_mem_base = CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY; current_mem_base = pinfo->mem_base;
total_mem = 0; total_mem = 0;
if (pinfo->memctl_opts[0].memctl_interleaving) { if (pinfo->memctl_opts[first_ctrl].memctl_interleaving) {
rank_density = pinfo->dimm_params[0][0].rank_density >> rank_density = pinfo->dimm_params[first_ctrl][0].rank_density >>
dbw_cap_adj[0]; dbw_cap_adj[first_ctrl];
switch (pinfo->memctl_opts[0].ba_intlv_ctl & switch (pinfo->memctl_opts[first_ctrl].ba_intlv_ctl &
FSL_DDR_CS0_CS1_CS2_CS3) { FSL_DDR_CS0_CS1_CS2_CS3) {
case FSL_DDR_CS0_CS1_CS2_CS3: case FSL_DDR_CS0_CS1_CS2_CS3:
ctlr_density = 4 * rank_density; ctlr_density = 4 * rank_density;
@ -316,7 +318,7 @@ static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo,
} }
debug("rank density is 0x%llx, ctlr density is 0x%llx\n", debug("rank density is 0x%llx, ctlr density is 0x%llx\n",
rank_density, ctlr_density); rank_density, ctlr_density);
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
if (pinfo->memctl_opts[i].memctl_interleaving) { if (pinfo->memctl_opts[i].memctl_interleaving) {
switch (pinfo->memctl_opts[i].memctl_interleaving_mode) { switch (pinfo->memctl_opts[i].memctl_interleaving_mode) {
case FSL_DDR_256B_INTERLEAVING: case FSL_DDR_256B_INTERLEAVING:
@ -372,7 +374,7 @@ static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo,
* Simple linear assignment if memory * Simple linear assignment if memory
* controllers are not interleaved. * controllers are not interleaved.
*/ */
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
total_ctlr_mem = 0; total_ctlr_mem = 0;
pinfo->common_timing_params[i].base_address = pinfo->common_timing_params[i].base_address =
current_mem_base; current_mem_base;
@ -408,18 +410,23 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
{ {
unsigned int i, j; unsigned int i, j;
unsigned long long total_mem = 0; unsigned long long total_mem = 0;
int assert_reset; int assert_reset = 0;
unsigned int first_ctrl = pinfo->first_ctrl;
unsigned int last_ctrl = first_ctrl + pinfo->num_ctrls - 1;
__maybe_unused int retval;
__maybe_unused bool goodspd = false;
__maybe_unused int dimm_slots_per_ctrl = pinfo->dimm_slots_per_ctrl;
fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg; fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg;
common_timing_params_t *timing_params = pinfo->common_timing_params; common_timing_params_t *timing_params = pinfo->common_timing_params;
assert_reset = board_need_mem_reset(); if (pinfo->board_need_mem_reset)
assert_reset = pinfo->board_need_mem_reset();
/* data bus width capacity adjust shift amount */ /* data bus width capacity adjust shift amount */
unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS]; unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS];
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++)
dbw_capacity_adjust[i] = 0; dbw_capacity_adjust[i] = 0;
}
debug("starting at step %u (%s)\n", debug("starting at step %u (%s)\n",
start_step, step_to_string(start_step)); start_step, step_to_string(start_step));
@ -428,28 +435,28 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
case STEP_GET_SPD: case STEP_GET_SPD:
#if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM) #if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM)
/* STEP 1: Gather all DIMM SPD data */ /* STEP 1: Gather all DIMM SPD data */
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i); fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i,
dimm_slots_per_ctrl);
} }
case STEP_COMPUTE_DIMM_PARMS: case STEP_COMPUTE_DIMM_PARMS:
/* STEP 2: Compute DIMM parameters from SPD data */ /* STEP 2: Compute DIMM parameters from SPD data */
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
unsigned int retval;
generic_spd_eeprom_t *spd = generic_spd_eeprom_t *spd =
&(pinfo->spd_installed_dimms[i][j]); &(pinfo->spd_installed_dimms[i][j]);
dimm_params_t *pdimm = dimm_params_t *pdimm =
&(pinfo->dimm_params[i][j]); &(pinfo->dimm_params[i][j]);
retval = compute_dimm_parameters(spd, pdimm, i); retval = compute_dimm_parameters(spd, pdimm, i);
#ifdef CONFIG_SYS_DDR_RAW_TIMING #ifdef CONFIG_SYS_DDR_RAW_TIMING
if (!i && !j && retval) { if (!i && !j && retval) {
printf("SPD error on controller %d! " printf("SPD error on controller %d! "
"Trying fallback to raw timing " "Trying fallback to raw timing "
"calculation\n", i); "calculation\n", i);
fsl_ddr_get_dimm_params(pdimm, i, j); retval = fsl_ddr_get_dimm_params(pdimm,
i, j);
} }
#else #else
if (retval == 2) { if (retval == 2) {
@ -463,13 +470,26 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
debug("Warning: compute_dimm_parameters" debug("Warning: compute_dimm_parameters"
" non-zero return value for memctl=%u " " non-zero return value for memctl=%u "
"dimm=%u\n", i, j); "dimm=%u\n", i, j);
} else {
goodspd = true;
} }
} }
} }
if (!goodspd) {
/*
* No valid SPD found
* Throw an error if this is for main memory, i.e.
* first_ctrl == 0. Otherwise, siliently return 0
* as the memory size.
*/
if (first_ctrl == 0)
printf("Error: No valid SPD detected.\n");
return 0;
}
#elif defined(CONFIG_SYS_DDR_RAW_TIMING) #elif defined(CONFIG_SYS_DDR_RAW_TIMING)
case STEP_COMPUTE_DIMM_PARMS: case STEP_COMPUTE_DIMM_PARMS:
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
dimm_params_t *pdimm = dimm_params_t *pdimm =
&(pinfo->dimm_params[i][j]); &(pinfo->dimm_params[i][j]);
@ -483,7 +503,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
* STEP 3: Compute a common set of timing parameters * STEP 3: Compute a common set of timing parameters
* suitable for all of the DIMMs on each memory controller * suitable for all of the DIMMs on each memory controller
*/ */
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
debug("Computing lowest common DIMM" debug("Computing lowest common DIMM"
" parameters for memctl=%u\n", i); " parameters for memctl=%u\n", i);
compute_lowest_common_dimm_parameters( compute_lowest_common_dimm_parameters(
@ -494,7 +514,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
case STEP_GATHER_OPTS: case STEP_GATHER_OPTS:
/* STEP 4: Gather configuration requirements from user */ /* STEP 4: Gather configuration requirements from user */
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
debug("Reloading memory controller " debug("Reloading memory controller "
"configuration options for memctl=%u\n", i); "configuration options for memctl=%u\n", i);
/* /*
@ -516,9 +536,13 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
if (timing_params[i].all_dimms_registered) if (timing_params[i].all_dimms_registered)
assert_reset = 1; assert_reset = 1;
} }
if (assert_reset) { if (assert_reset && !size_only) {
debug("Asserting mem reset\n"); if (pinfo->board_mem_reset) {
board_assert_mem_reset(); debug("Asserting mem reset\n");
pinfo->board_mem_reset();
} else {
debug("Asserting mem reset missing\n");
}
} }
case STEP_ASSIGN_ADDRESSES: case STEP_ASSIGN_ADDRESSES:
@ -530,7 +554,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
case STEP_COMPUTE_REGS: case STEP_COMPUTE_REGS:
/* STEP 6: compute controller register values */ /* STEP 6: compute controller register values */
debug("FSL Memory ctrl register computation\n"); debug("FSL Memory ctrl register computation\n");
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
if (timing_params[i].ndimms_present == 0) { if (timing_params[i].ndimms_present == 0) {
memset(&ddr_reg[i], 0, memset(&ddr_reg[i], 0,
sizeof(fsl_ddr_cfg_regs_t)); sizeof(fsl_ddr_cfg_regs_t));
@ -558,7 +582,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
*/ */
unsigned int max_end = 0; unsigned int max_end = 0;
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
for (j = 0; j < CONFIG_CHIP_SELECTS_PER_CTRL; j++) { for (j = 0; j < CONFIG_CHIP_SELECTS_PER_CTRL; j++) {
fsl_ddr_cfg_regs_t *reg = &ddr_reg[i]; fsl_ddr_cfg_regs_t *reg = &ddr_reg[i];
if (reg->cs[j].config & 0x80000000) { if (reg->cs[j].config & 0x80000000) {
@ -578,53 +602,45 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
} }
total_mem = 1 + (((unsigned long long)max_end << 24ULL) | total_mem = 1 + (((unsigned long long)max_end << 24ULL) |
0xFFFFFFULL) - CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY; 0xFFFFFFULL) - pinfo->mem_base;
} }
return total_mem; return total_mem;
} }
/* phys_size_t __fsl_ddr_sdram(fsl_ddr_info_t *pinfo)
* fsl_ddr_sdram() -- this is the main function to be called by
* initdram() in the board file.
*
* It returns amount of memory configured in bytes.
*/
phys_size_t fsl_ddr_sdram(void)
{ {
unsigned int i; unsigned int i, first_ctrl, last_ctrl;
#ifdef CONFIG_PPC #ifdef CONFIG_PPC
unsigned int law_memctl = LAW_TRGT_IF_DDR_1; unsigned int law_memctl = LAW_TRGT_IF_DDR_1;
#endif #endif
unsigned long long total_memory; unsigned long long total_memory;
fsl_ddr_info_t info; int deassert_reset = 0;
int deassert_reset;
/* Reset info structure. */ first_ctrl = pinfo->first_ctrl;
memset(&info, 0, sizeof(fsl_ddr_info_t)); last_ctrl = first_ctrl + pinfo->num_ctrls - 1;
/* Compute it once normally. */ /* Compute it once normally. */
#ifdef CONFIG_FSL_DDR_INTERACTIVE #ifdef CONFIG_FSL_DDR_INTERACTIVE
if (tstc() && (getc() == 'd')) { /* we got a key press of 'd' */ if (tstc() && (getc() == 'd')) { /* we got a key press of 'd' */
total_memory = fsl_ddr_interactive(&info, 0); total_memory = fsl_ddr_interactive(pinfo, 0);
} else if (fsl_ddr_interactive_env_var_exists()) { } else if (fsl_ddr_interactive_env_var_exists()) {
total_memory = fsl_ddr_interactive(&info, 1); total_memory = fsl_ddr_interactive(pinfo, 1);
} else } else
#endif #endif
total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0); total_memory = fsl_ddr_compute(pinfo, STEP_GET_SPD, 0);
/* setup 3-way interleaving before enabling DDRC */ /* setup 3-way interleaving before enabling DDRC */
if (info.memctl_opts[0].memctl_interleaving) { switch (pinfo->memctl_opts[first_ctrl].memctl_interleaving_mode) {
switch (info.memctl_opts[0].memctl_interleaving_mode) { case FSL_DDR_3WAY_1KB_INTERLEAVING:
case FSL_DDR_3WAY_1KB_INTERLEAVING: case FSL_DDR_3WAY_4KB_INTERLEAVING:
case FSL_DDR_3WAY_4KB_INTERLEAVING: case FSL_DDR_3WAY_8KB_INTERLEAVING:
case FSL_DDR_3WAY_8KB_INTERLEAVING: fsl_ddr_set_intl3r(
fsl_ddr_set_intl3r( pinfo->memctl_opts[first_ctrl].
info.memctl_opts[0].memctl_interleaving_mode); memctl_interleaving_mode);
break; break;
default: default:
break; break;
}
} }
/* /*
@ -637,14 +653,15 @@ phys_size_t fsl_ddr_sdram(void)
* For non-registered DIMMs, initialization can go through but it is * For non-registered DIMMs, initialization can go through but it is
* also OK to follow the same flow. * also OK to follow the same flow.
*/ */
deassert_reset = board_need_mem_reset(); if (pinfo->board_need_mem_reset)
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { deassert_reset = pinfo->board_need_mem_reset();
if (info.common_timing_params[i].all_dimms_registered) for (i = first_ctrl; i <= last_ctrl; i++) {
if (pinfo->common_timing_params[i].all_dimms_registered)
deassert_reset = 1; deassert_reset = 1;
} }
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
debug("Programming controller %u\n", i); debug("Programming controller %u\n", i);
if (info.common_timing_params[i].ndimms_present == 0) { if (pinfo->common_timing_params[i].ndimms_present == 0) {
debug("No dimms present on controller %u; " debug("No dimms present on controller %u; "
"skipping programming\n", i); "skipping programming\n", i);
continue; continue;
@ -653,45 +670,58 @@ phys_size_t fsl_ddr_sdram(void)
* The following call with step = 1 returns before enabling * The following call with step = 1 returns before enabling
* the controller. It has to finish with step = 2 later. * the controller. It has to finish with step = 2 later.
*/ */
fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i, fsl_ddr_set_memctl_regs(&(pinfo->fsl_ddr_config_reg[i]), i,
deassert_reset ? 1 : 0); deassert_reset ? 1 : 0);
} }
if (deassert_reset) { if (deassert_reset) {
/* Use board FPGA or GPIO to deassert reset signal */ /* Use board FPGA or GPIO to deassert reset signal */
debug("Deasserting mem reset\n"); if (pinfo->board_mem_de_reset) {
board_deassert_mem_reset(); debug("Deasserting mem reset\n");
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { pinfo->board_mem_de_reset();
} else {
debug("Deasserting mem reset missing\n");
}
for (i = first_ctrl; i <= last_ctrl; i++) {
/* Call with step = 2 to continue initialization */ /* Call with step = 2 to continue initialization */
fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), fsl_ddr_set_memctl_regs(&(pinfo->fsl_ddr_config_reg[i]),
i, 2); i, 2);
} }
} }
#ifdef CONFIG_PPC #ifdef CONFIG_PPC
/* program LAWs */ /* program LAWs */
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
if (info.memctl_opts[i].memctl_interleaving) { if (pinfo->memctl_opts[i].memctl_interleaving) {
switch (info.memctl_opts[i].memctl_interleaving_mode) { switch (pinfo->memctl_opts[i].
memctl_interleaving_mode) {
case FSL_DDR_CACHE_LINE_INTERLEAVING: case FSL_DDR_CACHE_LINE_INTERLEAVING:
case FSL_DDR_PAGE_INTERLEAVING: case FSL_DDR_PAGE_INTERLEAVING:
case FSL_DDR_BANK_INTERLEAVING: case FSL_DDR_BANK_INTERLEAVING:
case FSL_DDR_SUPERBANK_INTERLEAVING: case FSL_DDR_SUPERBANK_INTERLEAVING:
if (i % 2)
break;
if (i == 0) { if (i == 0) {
law_memctl = LAW_TRGT_IF_DDR_INTRLV; law_memctl = LAW_TRGT_IF_DDR_INTRLV;
fsl_ddr_set_lawbar(&info.common_timing_params[i], fsl_ddr_set_lawbar(
law_memctl, i); &pinfo->common_timing_params[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); law_memctl, i);
} }
#if CONFIG_NUM_DDR_CONTROLLERS > 3
else if (i == 2) {
law_memctl = LAW_TRGT_IF_DDR_INTLV_34;
fsl_ddr_set_lawbar(
&pinfo->common_timing_params[i],
law_memctl, i);
}
#endif
break; break;
case FSL_DDR_3WAY_1KB_INTERLEAVING: case FSL_DDR_3WAY_1KB_INTERLEAVING:
case FSL_DDR_3WAY_4KB_INTERLEAVING: case FSL_DDR_3WAY_4KB_INTERLEAVING:
case FSL_DDR_3WAY_8KB_INTERLEAVING: case FSL_DDR_3WAY_8KB_INTERLEAVING:
law_memctl = LAW_TRGT_IF_DDR_INTLV_123; law_memctl = LAW_TRGT_IF_DDR_INTLV_123;
if (i == 0) { if (i == 0) {
fsl_ddr_set_lawbar(&info.common_timing_params[i], fsl_ddr_set_lawbar(
&pinfo->common_timing_params[i],
law_memctl, i); law_memctl, i);
} }
break; break;
@ -700,7 +730,8 @@ phys_size_t fsl_ddr_sdram(void)
case FSL_DDR_4WAY_8KB_INTERLEAVING: case FSL_DDR_4WAY_8KB_INTERLEAVING:
law_memctl = LAW_TRGT_IF_DDR_INTLV_1234; law_memctl = LAW_TRGT_IF_DDR_INTLV_1234;
if (i == 0) if (i == 0)
fsl_ddr_set_lawbar(&info.common_timing_params[i], fsl_ddr_set_lawbar(
&pinfo->common_timing_params[i],
law_memctl, i); law_memctl, i);
/* place holder for future 4-way interleaving */ /* place holder for future 4-way interleaving */
break; break;
@ -724,8 +755,8 @@ phys_size_t fsl_ddr_sdram(void)
default: default:
break; break;
} }
fsl_ddr_set_lawbar(&info.common_timing_params[i], fsl_ddr_set_lawbar(&pinfo->common_timing_params[i],
law_memctl, i); law_memctl, i);
} }
} }
#endif #endif
@ -734,7 +765,7 @@ phys_size_t fsl_ddr_sdram(void)
#if !defined(CONFIG_PHYS_64BIT) #if !defined(CONFIG_PHYS_64BIT)
/* Check for 4G or more. Bad. */ /* Check for 4G or more. Bad. */
if (total_memory >= (1ull << 32)) { if ((first_ctrl == 0) && (total_memory >= (1ull << 32))) {
puts("Detected "); puts("Detected ");
print_size(total_memory, " of memory\n"); print_size(total_memory, " of memory\n");
printf(" This U-Boot only supports < 4G of DDR\n"); printf(" This U-Boot only supports < 4G of DDR\n");
@ -748,8 +779,56 @@ phys_size_t fsl_ddr_sdram(void)
} }
/* /*
* fsl_ddr_sdram_size() - This function only returns the size of the total * fsl_ddr_sdram(void) -- this is the main function to be
* memory without setting ddr control registers. * called by initdram() in the board file.
*
* It returns amount of memory configured in bytes.
*/
phys_size_t fsl_ddr_sdram(void)
{
fsl_ddr_info_t info;
/* Reset info structure. */
memset(&info, 0, sizeof(fsl_ddr_info_t));
info.mem_base = CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY;
info.first_ctrl = 0;
info.num_ctrls = CONFIG_SYS_FSL_DDR_MAIN_NUM_CTRLS;
info.dimm_slots_per_ctrl = CONFIG_DIMM_SLOTS_PER_CTLR;
info.board_need_mem_reset = board_need_mem_reset;
info.board_mem_reset = board_assert_mem_reset;
info.board_mem_de_reset = board_deassert_mem_reset;
return __fsl_ddr_sdram(&info);
}
#ifdef CONFIG_SYS_FSL_OTHER_DDR_NUM_CTRLS
phys_size_t fsl_other_ddr_sdram(unsigned long long base,
unsigned int first_ctrl,
unsigned int num_ctrls,
unsigned int dimm_slots_per_ctrl,
int (*board_need_reset)(void),
void (*board_reset)(void),
void (*board_de_reset)(void))
{
fsl_ddr_info_t info;
/* Reset info structure. */
memset(&info, 0, sizeof(fsl_ddr_info_t));
info.mem_base = base;
info.first_ctrl = first_ctrl;
info.num_ctrls = num_ctrls;
info.dimm_slots_per_ctrl = dimm_slots_per_ctrl;
info.board_need_mem_reset = board_need_reset;
info.board_mem_reset = board_reset;
info.board_mem_de_reset = board_de_reset;
return __fsl_ddr_sdram(&info);
}
#endif
/*
* fsl_ddr_sdram_size(first_ctrl, last_intlv) - This function only returns the
* size of the total memory without setting ddr control registers.
*/ */
phys_size_t phys_size_t
fsl_ddr_sdram_size(void) fsl_ddr_sdram_size(void)
@ -758,6 +837,11 @@ fsl_ddr_sdram_size(void)
unsigned long long total_memory = 0; unsigned long long total_memory = 0;
memset(&info, 0 , sizeof(fsl_ddr_info_t)); memset(&info, 0 , sizeof(fsl_ddr_info_t));
info.mem_base = CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY;
info.first_ctrl = 0;
info.num_ctrls = CONFIG_SYS_FSL_DDR_MAIN_NUM_CTRLS;
info.dimm_slots_per_ctrl = CONFIG_DIMM_SLOTS_PER_CTLR;
info.board_need_mem_reset = NULL;
/* Compute it once normally. */ /* Compute it once normally. */
total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 1); total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 1);

View file

@ -1065,18 +1065,21 @@ void check_interleaving_options(fsl_ddr_info_t *pinfo)
unsigned int check_intlv, check_n_row_addr, check_n_col_addr; unsigned int check_intlv, check_n_row_addr, check_n_col_addr;
unsigned long long check_rank_density; unsigned long long check_rank_density;
struct dimm_params_s *dimm; struct dimm_params_s *dimm;
int first_ctrl = pinfo->first_ctrl;
int last_ctrl = first_ctrl + pinfo->num_ctrls - 1;
/* /*
* Check if all controllers are configured for memory * Check if all controllers are configured for memory
* controller interleaving. Identical dimms are recommended. At least * controller interleaving. Identical dimms are recommended. At least
* the size, row and col address should be checked. * the size, row and col address should be checked.
*/ */
j = 0; j = 0;
check_n_ranks = pinfo->dimm_params[0][0].n_ranks; check_n_ranks = pinfo->dimm_params[first_ctrl][0].n_ranks;
check_rank_density = pinfo->dimm_params[0][0].rank_density; check_rank_density = pinfo->dimm_params[first_ctrl][0].rank_density;
check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr; check_n_row_addr = pinfo->dimm_params[first_ctrl][0].n_row_addr;
check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr; check_n_col_addr = pinfo->dimm_params[first_ctrl][0].n_col_addr;
check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode; check_intlv = pinfo->memctl_opts[first_ctrl].memctl_interleaving_mode;
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { for (i = first_ctrl; i <= last_ctrl; i++) {
dimm = &pinfo->dimm_params[i][0]; dimm = &pinfo->dimm_params[i][0];
if (!pinfo->memctl_opts[i].memctl_interleaving) { if (!pinfo->memctl_opts[i].memctl_interleaving) {
continue; continue;
@ -1094,7 +1097,7 @@ void check_interleaving_options(fsl_ddr_info_t *pinfo)
} }
if (intlv_invalid) { if (intlv_invalid) {
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) for (i = first_ctrl; i <= last_ctrl; i++)
pinfo->memctl_opts[i].memctl_interleaving = 0; pinfo->memctl_opts[i].memctl_interleaving = 0;
printf("Not all DIMMs are identical. " printf("Not all DIMMs are identical. "
"Memory controller interleaving disabled.\n"); "Memory controller interleaving disabled.\n");
@ -1123,10 +1126,10 @@ void check_interleaving_options(fsl_ddr_info_t *pinfo)
} }
debug("%d of %d controllers are interleaving.\n", j, k); debug("%d of %d controllers are interleaving.\n", j, k);
if (j && (j != k)) { if (j && (j != k)) {
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) for (i = first_ctrl; i <= last_ctrl; i++)
pinfo->memctl_opts[i].memctl_interleaving = 0; pinfo->memctl_opts[i].memctl_interleaving = 0;
printf("Not all controllers have compatible " if ((last_ctrl - first_ctrl) > 1)
"interleaving mode. All disabled.\n"); puts("Not all controllers have compatible interleaving mode. All disabled.\n");
} }
} }
debug("Checking interleaving options completed\n"); debug("Checking interleaving options completed\n");

View file

@ -149,7 +149,7 @@ u32 fsl_ddr_get_intl3r(void)
return val; return val;
} }
void board_add_ram_info(int use_default) void print_ddr_info(unsigned int start_ctrl)
{ {
struct ccsr_ddr __iomem *ddr = struct ccsr_ddr __iomem *ddr =
(struct ccsr_ddr __iomem *)(CONFIG_SYS_FSL_DDR_ADDR); (struct ccsr_ddr __iomem *)(CONFIG_SYS_FSL_DDR_ADDR);
@ -164,17 +164,25 @@ void board_add_ram_info(int use_default)
int cas_lat; int cas_lat;
#if CONFIG_NUM_DDR_CONTROLLERS >= 2 #if CONFIG_NUM_DDR_CONTROLLERS >= 2
if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { if ((!(sdram_cfg & SDRAM_CFG_MEM_EN)) ||
(start_ctrl == 1)) {
ddr = (void __iomem *)CONFIG_SYS_FSL_DDR2_ADDR; ddr = (void __iomem *)CONFIG_SYS_FSL_DDR2_ADDR;
sdram_cfg = ddr_in32(&ddr->sdram_cfg); sdram_cfg = ddr_in32(&ddr->sdram_cfg);
} }
#endif #endif
#if CONFIG_NUM_DDR_CONTROLLERS >= 3 #if CONFIG_NUM_DDR_CONTROLLERS >= 3
if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { if ((!(sdram_cfg & SDRAM_CFG_MEM_EN)) ||
(start_ctrl == 2)) {
ddr = (void __iomem *)CONFIG_SYS_FSL_DDR3_ADDR; ddr = (void __iomem *)CONFIG_SYS_FSL_DDR3_ADDR;
sdram_cfg = ddr_in32(&ddr->sdram_cfg); sdram_cfg = ddr_in32(&ddr->sdram_cfg);
} }
#endif #endif
if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
puts(" (DDR not enabled)\n");
return;
}
puts(" (DDR"); puts(" (DDR");
switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >> switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
SDRAM_CFG_SDRAM_TYPE_SHIFT) { SDRAM_CFG_SDRAM_TYPE_SHIFT) {
@ -241,7 +249,7 @@ void board_add_ram_info(int use_default)
#endif #endif
#endif #endif
#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) #if (CONFIG_NUM_DDR_CONTROLLERS >= 2)
if (cs0_config & 0x20000000) { if ((cs0_config & 0x20000000) && (start_ctrl == 0)) {
puts("\n"); puts("\n");
puts(" DDR Controller Interleaving Mode: "); puts(" DDR Controller Interleaving Mode: ");
@ -290,3 +298,13 @@ void board_add_ram_info(int use_default)
} }
} }
} }
void __weak detail_board_ddr_info(void)
{
print_ddr_info(0);
}
void board_add_ram_info(int use_default)
{
detail_board_ddr_info();
}

View file

@ -15,6 +15,11 @@
#include <common_timing_params.h> #include <common_timing_params.h>
#ifndef CONFIG_SYS_FSL_DDR_MAIN_NUM_CTRLS
/* All controllers are for main memory */
#define CONFIG_SYS_FSL_DDR_MAIN_NUM_CTRLS CONFIG_NUM_DDR_CONTROLLERS
#endif
#ifdef CONFIG_SYS_FSL_DDR_LE #ifdef CONFIG_SYS_FSL_DDR_LE
#define ddr_in32(a) in_le32(a) #define ddr_in32(a) in_le32(a)
#define ddr_out32(a, v) out_le32(a, v) #define ddr_out32(a, v) out_le32(a, v)
@ -57,6 +62,13 @@ typedef struct {
memctl_options_t memctl_opts[CONFIG_SYS_NUM_DDR_CTLRS]; memctl_options_t memctl_opts[CONFIG_SYS_NUM_DDR_CTLRS];
common_timing_params_t common_timing_params[CONFIG_SYS_NUM_DDR_CTLRS]; common_timing_params_t common_timing_params[CONFIG_SYS_NUM_DDR_CTLRS];
fsl_ddr_cfg_regs_t fsl_ddr_config_reg[CONFIG_SYS_NUM_DDR_CTLRS]; fsl_ddr_cfg_regs_t fsl_ddr_config_reg[CONFIG_SYS_NUM_DDR_CTLRS];
unsigned int first_ctrl;
unsigned int num_ctrls;
unsigned long long mem_base;
unsigned int dimm_slots_per_ctrl;
int (*board_need_mem_reset)(void);
void (*board_mem_reset)(void);
void (*board_mem_de_reset)(void);
} fsl_ddr_info_t; } fsl_ddr_info_t;
/* Compute steps */ /* Compute steps */
@ -72,7 +84,6 @@ typedef struct {
unsigned long long unsigned long long
fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
unsigned int size_only); unsigned int size_only);
const char *step_to_string(unsigned int step); const char *step_to_string(unsigned int step);
unsigned int compute_fsl_memctl_config_regs(const memctl_options_t *popts, unsigned int compute_fsl_memctl_config_regs(const memctl_options_t *popts,
@ -102,7 +113,7 @@ void fsl_ddr_set_lawbar(
int fsl_ddr_interactive_env_var_exists(void); int fsl_ddr_interactive_env_var_exists(void);
unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set); unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set);
void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
unsigned int ctrl_num); unsigned int ctrl_num, unsigned int dimm_slots_per_ctrl);
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
unsigned int check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr); unsigned int check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr);

View file

@ -379,12 +379,20 @@ typedef struct memctl_options_s {
unsigned int trwt; /* read-to-write turnaround */ unsigned int trwt; /* read-to-write turnaround */
} memctl_options_t; } memctl_options_t;
extern phys_size_t fsl_ddr_sdram(void); phys_size_t fsl_ddr_sdram(void);
extern phys_size_t fsl_ddr_sdram_size(void); phys_size_t fsl_ddr_sdram_size(void);
phys_size_t fsl_other_ddr_sdram(unsigned long long base,
unsigned int first_ctrl,
unsigned int num_ctrls,
unsigned int dimm_slots_per_ctrl,
int (*board_need_reset)(void),
void (*board_reset)(void),
void (*board_de_reset)(void));
extern int fsl_use_spd(void); extern int fsl_use_spd(void);
extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
unsigned int ctrl_num, int step); unsigned int ctrl_num, int step);
u32 fsl_ddr_get_intl3r(void); u32 fsl_ddr_get_intl3r(void);
void print_ddr_info(unsigned int start_ctrl);
static void __board_assert_mem_reset(void) static void __board_assert_mem_reset(void)
{ {