[U-Boot] [PATCH 5/8] powerpc/8xxx: Enable DDR3 RDIMM support

Kumar Gala galak at kernel.crashing.org
Wed Jul 14 17:14:59 CEST 2010


From: york <yorksun at freescale.com>

Enabled registered DIMMs using data from SPD. RDIMMs have registers
which need to be configured before using. The register configuration
words are stored in SPD byte 60~116 (JEDEC standard No.21-C). Software
should read those RCWs and put into DDR controller before initialization.

Signed-off-by: York Sun <yorksun at freescale.com>
---
 .../powerpc/cpu/mpc8xxx/ddr/common_timing_params.h |    3 +
 arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c           |   81 ++++++++------------
 arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c    |    6 +-
 .../cpu/mpc8xxx/ddr/lc_common_dimm_params.c        |   18 ++++-
 arch/powerpc/include/asm/fsl_ddr_dimm_params.h     |    3 +
 include/ddr_spd.h                                  |   14 ++++
 6 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h b/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h
index 5aea517..06706ed 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h
@@ -48,6 +48,9 @@ typedef struct {
 
 	unsigned long long total_mem;
 	unsigned long long base_address;
+
+	/* DDR3 RDIMM */
+	unsigned char rcw[16];	/* Register Control Word 0-15 */
 } common_timing_params_t;
 
 #endif
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
index ff0ddd1..b2962d2 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
@@ -448,6 +448,35 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 	debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2);
 }
 
+/* DDR SDRAM Register Control Word */
+static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
+			       const common_timing_params_t *common_dimm)
+{
+	if (common_dimm->all_DIMMs_registered
+		&& !common_dimm->all_DIMMs_unbuffered) {
+		ddr->ddr_sdram_rcw_1 =
+			common_dimm->rcw[0] << 28 | \
+			common_dimm->rcw[1] << 24 | \
+			common_dimm->rcw[2] << 20 | \
+			common_dimm->rcw[3] << 16 | \
+			common_dimm->rcw[4] << 12 | \
+			common_dimm->rcw[5] << 8 | \
+			common_dimm->rcw[6] << 4 | \
+			common_dimm->rcw[7];
+		ddr->ddr_sdram_rcw_2 =
+			common_dimm->rcw[8] << 28 | \
+			common_dimm->rcw[9] << 24 | \
+			common_dimm->rcw[10] << 20 | \
+			common_dimm->rcw[11] << 16 | \
+			common_dimm->rcw[12] << 12 | \
+			common_dimm->rcw[13] << 8 | \
+			common_dimm->rcw[14] << 4 | \
+			common_dimm->rcw[15];
+		debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n", ddr->ddr_sdram_rcw_1);
+		debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n", ddr->ddr_sdram_rcw_2);
+	}
+}
+
 /* DDR SDRAM control configuration (DDR_SDRAM_CFG) */
 static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
 			       const memctl_options_t *popts,
@@ -938,6 +967,7 @@ static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr,
 
 	clk_adjust = popts->clk_adjust;
 	ddr->ddr_sdram_clk_cntl = (clk_adjust & 0xF) << 23;
+	debug("FSLDDR: clk_cntl = 0x%08x\n", ddr->ddr_sdram_clk_cntl);
 }
 
 /* DDR Initialization Address (DDR_INIT_ADDR) */
@@ -1113,54 +1143,6 @@ static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it)
 	ddr->ddr_sr_cntr = (sr_it & 0xF) << 16;
 }
 
-/* DDR SDRAM Register Control Word 1 (DDR_SDRAM_RCW_1) */
-static void set_ddr_sdram_rcw_1(fsl_ddr_cfg_regs_t *ddr)
-{
-	unsigned int rcw0 = 0;	/* RCW0: Register Control Word 0 */
-	unsigned int rcw1 = 0;	/* RCW1: Register Control Word 1 */
-	unsigned int rcw2 = 0;	/* RCW2: Register Control Word 2 */
-	unsigned int rcw3 = 0;	/* RCW3: Register Control Word 3 */
-	unsigned int rcw4 = 0;	/* RCW4: Register Control Word 4 */
-	unsigned int rcw5 = 0;	/* RCW5: Register Control Word 5 */
-	unsigned int rcw6 = 0;	/* RCW6: Register Control Word 6 */
-	unsigned int rcw7 = 0;	/* RCW7: Register Control Word 7 */
-
-	ddr->ddr_sdram_rcw_1 = (0
-				| ((rcw0 & 0xF) << 28)
-				| ((rcw1 & 0xF) << 24)
-				| ((rcw2 & 0xF) << 20)
-				| ((rcw3 & 0xF) << 16)
-				| ((rcw4 & 0xF) << 12)
-				| ((rcw5 & 0xF) << 8)
-				| ((rcw6 & 0xF) << 4)
-				| ((rcw7 & 0xF) << 0)
-				);
-}
-
-/* DDR SDRAM Register Control Word 2 (DDR_SDRAM_RCW_2) */
-static void set_ddr_sdram_rcw_2(fsl_ddr_cfg_regs_t *ddr)
-{
-	unsigned int rcw8 = 0;	/* RCW0: Register Control Word 8 */
-	unsigned int rcw9 = 0;	/* RCW1: Register Control Word 9 */
-	unsigned int rcw10 = 0;	/* RCW2: Register Control Word 10 */
-	unsigned int rcw11 = 0;	/* RCW3: Register Control Word 11 */
-	unsigned int rcw12 = 0;	/* RCW4: Register Control Word 12 */
-	unsigned int rcw13 = 0;	/* RCW5: Register Control Word 13 */
-	unsigned int rcw14 = 0;	/* RCW6: Register Control Word 14 */
-	unsigned int rcw15 = 0;	/* RCW7: Register Control Word 15 */
-
-	ddr->ddr_sdram_rcw_2 = (0
-				| ((rcw8 & 0xF) << 28)
-				| ((rcw9 & 0xF) << 24)
-				| ((rcw10 & 0xF) << 20)
-				| ((rcw11 & 0xF) << 16)
-				| ((rcw12 & 0xF) << 12)
-				| ((rcw13 & 0xF) << 8)
-				| ((rcw14 & 0xF) << 4)
-				| ((rcw15 & 0xF) << 0)
-				);
-}
-
 static void set_ddr_eor(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
 {
 	if (popts->addr_hash) {
@@ -1430,8 +1412,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 
 	set_ddr_sr_cntr(ddr, sr_it);
 
-	set_ddr_sdram_rcw_1(ddr);
-	set_ddr_sdram_rcw_2(ddr);
+	set_ddr_sdram_rcw(ddr, common_dimm);
 
 	return check_fsl_memctl_config_regs(ddr);
 }
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c
index d4199ba..29cea53 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c
@@ -90,6 +90,7 @@ ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd,
 {
 	unsigned int retval;
 	unsigned int mtb_ps;
+	int i;
 
 	if (spd->mem_type) {
 		if (spd->mem_type != SPD_MEMTYPE_DDR3) {
@@ -131,8 +132,11 @@ ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd,
 	case 0x01:	/* RDIMM */
 	case 0x05:	/* Mini-RDIMM */
 		pdimm->registered_dimm = 1; /* register buffered */
+		for (i = 0; i < 16; i += 2) {
+			pdimm->rcw[i] = spd->mod_section.registered.rcw[i/2] & 0x0F;
+			pdimm->rcw[i+1] = (spd->mod_section.registered.rcw[i/2] >> 4) & 0x0F;
+		}
 		break;
-
 	case 0x02:	/* UDIMM */
 	case 0x03:	/* SO-DIMM */
 	case 0x04:	/* Micro-DIMM */
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
index ce6c148..029e566 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
@@ -76,7 +76,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 				      common_timing_params_t *outpdimm,
 				      unsigned int number_of_dimms)
 {
-	unsigned int i;
+	unsigned int i, j;
 
 	unsigned int tCKmin_X_ps = 0;
 	unsigned int tCKmax_ps = 0xFFFFFFFF;
@@ -98,7 +98,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	unsigned int tDQSQ_max_ps = 0;
 	unsigned int tQHS_ps = 0;
 
-	unsigned int temp1, temp2;
+	unsigned int temp1, temp2, temp3;
 	unsigned int additive_latency = 0;
 #if !defined(CONFIG_FSL_DDR3)
 	const unsigned int mclk_ps = get_memory_clk_period_ps();
@@ -231,6 +231,20 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 				"DIMMs detected!\n");
 	}
 
+	temp1 = 0;
+	if (outpdimm->all_DIMMs_registered)
+		for (j = 0; j < 16; j++) {
+			outpdimm->rcw[j] = dimm_params[0].rcw[j];
+			for (i = 1; i < number_of_dimms; i++)
+				if (dimm_params[i].rcw[j] != dimm_params[0].rcw[j]) {
+					temp3 = 1;
+					break;
+				}
+		}
+
+	if (temp1 != 0)
+		printf("ERROR: Mix different RDIMM detected!\n");
+
 #if defined(CONFIG_FSL_DDR3)
 	if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms))
 		return 1;
diff --git a/arch/powerpc/include/asm/fsl_ddr_dimm_params.h b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h
index 55923e0..be82602 100644
--- a/arch/powerpc/include/asm/fsl_ddr_dimm_params.h
+++ b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h
@@ -81,6 +81,9 @@ typedef struct dimm_params_s {
 	unsigned int tRTP_ps;	/* byte 38, spd->trtp */
 	unsigned int tDQSQ_max_ps;	/* byte 44, spd->tdqsq */
 	unsigned int tQHS_ps;	/* byte 45, spd->tqhs */
+
+	/* DDR3 RDIMM */
+	unsigned char rcw[16];	/* Register Control Word 0-15 */
 } dimm_params_t;
 
 extern unsigned int ddr_compute_dimm_parameters(
diff --git a/include/ddr_spd.h b/include/ddr_spd.h
index 10402c5..710e528 100644
--- a/include/ddr_spd.h
+++ b/include/ddr_spd.h
@@ -243,6 +243,20 @@ typedef struct ddr3_spd_eeprom_s {
 			unsigned char mod_thickness;
 			/* 62 (Registered) Reference Raw Card Used */
 			unsigned char ref_raw_card;
+			/* 63 DIMM Module Attributes */
+			unsigned char modu_attr;
+			/* 64 RDIMM Thermal Heat Spreader Solution */
+			unsigned char thermal;
+			/* 65 Register Manufacturer ID Code, Least Significant Byte */
+			unsigned char reg_id_lo;
+			/* 66 Register Manufacturer ID Code, Most Significant Byte */
+			unsigned char reg_id_hi;
+			/* 67 Register Revision Number */
+			unsigned char reg_rev;
+			/* 68 Register Type */
+			unsigned char reg_type;
+			/* 69-76 RC1,3,5...15 (MS Nibble) / RC0,2,4...14 (LS Nibble) */
+			unsigned char rcw[8];
 		} registered;
 		unsigned char uc[57]; /* 60-116 Module-Specific Section */
 	} mod_section;
-- 
1.6.0.6



More information about the U-Boot mailing list