From: York Sun Date: Fri, 1 Aug 2014 22:51:00 +0000 (-0700) Subject: driver/ddr: Restruct driver to allow standalone memory space X-Git-Tag: v2014.10-rc3~13^2~9 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=1d71efbb0345ff3a8ac45e62bef36813abe1703e;p=u-boot 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 --- diff --git a/README b/README index 70dd97d64d..573666eeed 100644 --- a/README +++ b/README @@ -538,6 +538,12 @@ The following options need to be configured: interleaving mode, handled by Dickens for Freescale layerscape 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: CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO diff --git a/arch/powerpc/cpu/mpc85xx/cpu.c b/arch/powerpc/cpu/mpc85xx/cpu.c index 6274f929dd..3d6ec843df 100644 --- a/arch/powerpc/cpu/mpc85xx/cpu.c +++ b/arch/powerpc/cpu/mpc85xx/cpu.c @@ -441,7 +441,7 @@ phys_size_t initdram(int board_type) /* Board-specific functions defined in each board's ddr.c */ 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, phys_addr_t *rpn); unsigned int @@ -459,7 +459,7 @@ static void dump_spd_ddr_reg(void) spd[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR]; 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("Byte (hex) "); diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index 4745b7fb1b..2418dca6ab 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -113,7 +113,7 @@ compute_ranksize(const struct ddr4_spd_eeprom_s *spd) #define spd_to_ps(mtb, ftb) \ (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. * 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->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->registered_dimm = 0; - switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) { - case DDR3_SPD_MODULETYPE_RDIMM: + switch (spd->module_type & DDR4_SPD_MODULETYPE_MASK) { + case DDR4_SPD_MODULETYPE_RDIMM: /* Registered/buffered DIMMs */ pdimm->registered_dimm = 1; break; - case DDR3_SPD_MODULETYPE_UDIMM: - case DDR3_SPD_MODULETYPE_SO_DIMM: + case DDR4_SPD_MODULETYPE_UDIMM: + case DDR4_SPD_MODULETYPE_SO_DIMM: /* Unbuffered DIMMs */ if (spd->mod_section.unbuffered.addr_mapping & 0x1) pdimm->mirrored_dimm = 1; diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c index 5e001fcb99..b43b669e41 100644 --- a/drivers/ddr/fsl/main.c +++ b/drivers/ddr/fsl/main.c @@ -135,7 +135,7 @@ __attribute__((weak, alias("__get_spd"))) void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address); 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 i2c_address = 0; @@ -145,14 +145,14 @@ void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, 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]; get_spd(&(ctrl_dimms_spd[i]), i2c_address); } } #else 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 */ @@ -231,9 +231,11 @@ const char * step_to_string(unsigned int step) { static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo, 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 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 @@ -241,7 +243,7 @@ static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo, * computed dimm capacities accordingly before * assigning addresses. */ - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + for (i = first_ctrl; i <= last_ctrl; i++) { unsigned int found = 0; 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]); } - current_mem_base = CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY; + current_mem_base = pinfo->mem_base; 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 & + if (pinfo->memctl_opts[first_ctrl].memctl_interleaving) { + rank_density = pinfo->dimm_params[first_ctrl][0].rank_density >> + dbw_cap_adj[first_ctrl]; + switch (pinfo->memctl_opts[first_ctrl].ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { case FSL_DDR_CS0_CS1_CS2_CS3: 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", 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) { switch (pinfo->memctl_opts[i].memctl_interleaving_mode) { 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 * 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; pinfo->common_timing_params[i].base_address = current_mem_base; @@ -408,18 +410,23 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, { unsigned int i, j; 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; 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 */ 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; - } debug("starting at step %u (%s)\n", 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: #if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM) /* STEP 1: Gather all DIMM SPD data */ - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i); + for (i = first_ctrl; i <= last_ctrl; i++) { + fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i, + dimm_slots_per_ctrl); } case STEP_COMPUTE_DIMM_PARMS: /* 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++) { - unsigned int retval; generic_spd_eeprom_t *spd = &(pinfo->spd_installed_dimms[i][j]); dimm_params_t *pdimm = &(pinfo->dimm_params[i][j]); - retval = compute_dimm_parameters(spd, pdimm, i); #ifdef CONFIG_SYS_DDR_RAW_TIMING if (!i && !j && retval) { printf("SPD error on controller %d! " "Trying fallback to raw timing " "calculation\n", i); - fsl_ddr_get_dimm_params(pdimm, i, j); + retval = fsl_ddr_get_dimm_params(pdimm, + i, j); } #else if (retval == 2) { @@ -463,13 +470,26 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, debug("Warning: compute_dimm_parameters" " non-zero return value for memctl=%u " "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) 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++) { dimm_params_t *pdimm = &(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 * 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" " parameters for memctl=%u\n", i); 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: /* 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 " "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) assert_reset = 1; } - if (assert_reset) { - debug("Asserting mem reset\n"); - board_assert_mem_reset(); + if (assert_reset && !size_only) { + if (pinfo->board_mem_reset) { + debug("Asserting mem reset\n"); + pinfo->board_mem_reset(); + } else { + debug("Asserting mem reset missing\n"); + } } case STEP_ASSIGN_ADDRESSES: @@ -530,7 +554,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, case STEP_COMPUTE_REGS: /* STEP 6: compute controller register values */ 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) { memset(&ddr_reg[i], 0, 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; - 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++) { fsl_ddr_cfg_regs_t *reg = &ddr_reg[i]; 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) | - 0xFFFFFFULL) - CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY; + 0xFFFFFFULL) - pinfo->mem_base; } return total_mem; } -/* - * 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) +phys_size_t __fsl_ddr_sdram(fsl_ddr_info_t *pinfo) { - unsigned int i; + unsigned int i, first_ctrl, last_ctrl; #ifdef CONFIG_PPC unsigned int law_memctl = LAW_TRGT_IF_DDR_1; #endif unsigned long long total_memory; - fsl_ddr_info_t info; - int deassert_reset; + int deassert_reset = 0; - /* Reset info structure. */ - memset(&info, 0, sizeof(fsl_ddr_info_t)); + first_ctrl = pinfo->first_ctrl; + last_ctrl = first_ctrl + pinfo->num_ctrls - 1; /* Compute it once normally. */ #ifdef CONFIG_FSL_DDR_INTERACTIVE 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()) { - total_memory = fsl_ddr_interactive(&info, 1); + total_memory = fsl_ddr_interactive(pinfo, 1); } else #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 */ - if (info.memctl_opts[0].memctl_interleaving) { - switch (info.memctl_opts[0].memctl_interleaving_mode) { - case FSL_DDR_3WAY_1KB_INTERLEAVING: - case FSL_DDR_3WAY_4KB_INTERLEAVING: - case FSL_DDR_3WAY_8KB_INTERLEAVING: - fsl_ddr_set_intl3r( - info.memctl_opts[0].memctl_interleaving_mode); - break; - default: - break; - } + switch (pinfo->memctl_opts[first_ctrl].memctl_interleaving_mode) { + case FSL_DDR_3WAY_1KB_INTERLEAVING: + case FSL_DDR_3WAY_4KB_INTERLEAVING: + case FSL_DDR_3WAY_8KB_INTERLEAVING: + fsl_ddr_set_intl3r( + pinfo->memctl_opts[first_ctrl]. + memctl_interleaving_mode); + break; + default: + break; } /* @@ -637,14 +653,15 @@ phys_size_t fsl_ddr_sdram(void) * For non-registered DIMMs, initialization can go through but it is * also OK to follow the same flow. */ - deassert_reset = board_need_mem_reset(); - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { - if (info.common_timing_params[i].all_dimms_registered) + if (pinfo->board_need_mem_reset) + deassert_reset = pinfo->board_need_mem_reset(); + for (i = first_ctrl; i <= last_ctrl; i++) { + if (pinfo->common_timing_params[i].all_dimms_registered) 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); - 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; " "skipping programming\n", i); continue; @@ -653,45 +670,58 @@ phys_size_t fsl_ddr_sdram(void) * The following call with step = 1 returns before enabling * 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); } if (deassert_reset) { /* Use board FPGA or GPIO to deassert reset signal */ - debug("Deasserting mem reset\n"); - board_deassert_mem_reset(); - for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { + if (pinfo->board_mem_de_reset) { + debug("Deasserting mem reset\n"); + 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 */ - fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), + fsl_ddr_set_memctl_regs(&(pinfo->fsl_ddr_config_reg[i]), i, 2); } } #ifdef CONFIG_PPC /* 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) { + for (i = first_ctrl; i <= last_ctrl; 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: + if (i % 2) + break; if (i == 0) { law_memctl = LAW_TRGT_IF_DDR_INTRLV; - fsl_ddr_set_lawbar(&info.common_timing_params[i], + fsl_ddr_set_lawbar( + &pinfo->common_timing_params[i], law_memctl, i); - } else if (i == 2) { + } +#if CONFIG_NUM_DDR_CONTROLLERS > 3 + else if (i == 2) { law_memctl = LAW_TRGT_IF_DDR_INTLV_34; - fsl_ddr_set_lawbar(&info.common_timing_params[i], + fsl_ddr_set_lawbar( + &pinfo->common_timing_params[i], law_memctl, i); } +#endif 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_lawbar(&info.common_timing_params[i], + fsl_ddr_set_lawbar( + &pinfo->common_timing_params[i], law_memctl, i); } break; @@ -700,7 +730,8 @@ phys_size_t fsl_ddr_sdram(void) 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], + fsl_ddr_set_lawbar( + &pinfo->common_timing_params[i], law_memctl, i); /* place holder for future 4-way interleaving */ break; @@ -724,8 +755,8 @@ phys_size_t fsl_ddr_sdram(void) default: break; } - fsl_ddr_set_lawbar(&info.common_timing_params[i], - law_memctl, i); + fsl_ddr_set_lawbar(&pinfo->common_timing_params[i], + law_memctl, i); } } #endif @@ -734,7 +765,7 @@ phys_size_t fsl_ddr_sdram(void) #if !defined(CONFIG_PHYS_64BIT) /* Check for 4G or more. Bad. */ - if (total_memory >= (1ull << 32)) { + if ((first_ctrl == 0) && (total_memory >= (1ull << 32))) { puts("Detected "); print_size(total_memory, " of memory\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 - * memory without setting ddr control registers. + * fsl_ddr_sdram(void) -- 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) +{ + 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 fsl_ddr_sdram_size(void) @@ -758,6 +837,11 @@ fsl_ddr_sdram_size(void) unsigned long long total_memory = 0; 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. */ total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 1); diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index 5986e1a0b9..31cc2bfecd 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -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 long long check_rank_density; 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 * controller interleaving. Identical dimms are recommended. At least * 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++) { + check_n_ranks = pinfo->dimm_params[first_ctrl][0].n_ranks; + check_rank_density = pinfo->dimm_params[first_ctrl][0].rank_density; + check_n_row_addr = pinfo->dimm_params[first_ctrl][0].n_row_addr; + check_n_col_addr = pinfo->dimm_params[first_ctrl][0].n_col_addr; + check_intlv = pinfo->memctl_opts[first_ctrl].memctl_interleaving_mode; + for (i = first_ctrl; i <= last_ctrl; i++) { dimm = &pinfo->dimm_params[i][0]; if (!pinfo->memctl_opts[i].memctl_interleaving) { continue; @@ -1094,7 +1097,7 @@ void check_interleaving_options(fsl_ddr_info_t *pinfo) } 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; printf("Not all DIMMs are identical. " "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); 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; - printf("Not all controllers have compatible " - "interleaving mode. All disabled.\n"); + if ((last_ctrl - first_ctrl) > 1) + puts("Not all controllers have compatible interleaving mode. All disabled.\n"); } } debug("Checking interleaving options completed\n"); diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c index 7a22aa3988..58b519b403 100644 --- a/drivers/ddr/fsl/util.c +++ b/drivers/ddr/fsl/util.c @@ -149,7 +149,7 @@ u32 fsl_ddr_get_intl3r(void) 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 *)(CONFIG_SYS_FSL_DDR_ADDR); @@ -164,17 +164,25 @@ void board_add_ram_info(int use_default) int cas_lat; #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; sdram_cfg = ddr_in32(&ddr->sdram_cfg); } #endif #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; sdram_cfg = ddr_in32(&ddr->sdram_cfg); } #endif + + if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { + puts(" (DDR not enabled)\n"); + return; + } + puts(" (DDR"); switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >> SDRAM_CFG_SDRAM_TYPE_SHIFT) { @@ -241,7 +249,7 @@ void board_add_ram_info(int use_default) #endif #endif #if (CONFIG_NUM_DDR_CONTROLLERS >= 2) - if (cs0_config & 0x20000000) { + if ((cs0_config & 0x20000000) && (start_ctrl == 0)) { puts("\n"); 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(); +} diff --git a/include/fsl_ddr.h b/include/fsl_ddr.h index 5c49b229da..675557ad1f 100644 --- a/include/fsl_ddr.h +++ b/include/fsl_ddr.h @@ -15,6 +15,11 @@ #include +#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 #define ddr_in32(a) in_le32(a) #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]; 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]; + 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; /* Compute steps */ @@ -72,7 +84,6 @@ typedef struct { unsigned long long fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, unsigned int size_only); - const char *step_to_string(unsigned int step); 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); 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, - 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[]); unsigned int check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr); diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h index 987119b014..d03901fe7c 100644 --- a/include/fsl_ddr_sdram.h +++ b/include/fsl_ddr_sdram.h @@ -379,12 +379,20 @@ typedef struct memctl_options_s { unsigned int trwt; /* read-to-write turnaround */ } memctl_options_t; -extern phys_size_t fsl_ddr_sdram(void); -extern phys_size_t fsl_ddr_sdram_size(void); +phys_size_t fsl_ddr_sdram(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 void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, - unsigned int ctrl_num, int step); +void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, + unsigned int ctrl_num, int step); u32 fsl_ddr_get_intl3r(void); +void print_ddr_info(unsigned int start_ctrl); static void __board_assert_mem_reset(void) {