[U-Boot] [PATCH 1/2] driver/ddr: Restruct driver to allow standalone memory space

York Sun yorksun at freescale.com
Sat Aug 2 00:51:00 CEST 2014


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 at freescale.com>
---
 README                             |    6 +
 arch/powerpc/cpu/mpc85xx/cpu.c     |    4 +-
 drivers/ddr/fsl/ddr4_dimm_params.c |   12 +-
 drivers/ddr/fsl/main.c             |  244 ++++++++++++++++++++++++------------
 drivers/ddr/fsl/options.c          |   23 ++--
 drivers/ddr/fsl/util.c             |   26 +++-
 include/fsl_ddr.h                  |   15 ++-
 include/fsl_ddr_sdram.h            |   16 ++-
 8 files changed, 238 insertions(+), 108 deletions(-)

diff --git a/README b/README
index 4ac7399..dcfff51 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 6274f92..3d6ec84 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 4745b7f..2418dca 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 5e001fc..b43b669 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 5986e1a..31cc2bf 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 7a22aa3..58b519b 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 5c49b22..675557a 100644
--- a/include/fsl_ddr.h
+++ b/include/fsl_ddr.h
@@ -15,6 +15,11 @@
 
 #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
 #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 e8a2db9..c594fdb 100644
--- a/include/fsl_ddr_sdram.h
+++ b/include/fsl_ddr_sdram.h
@@ -377,12 +377,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)
 {
-- 
1.7.9.5



More information about the U-Boot mailing list