powerpc/8xxx: Enable DDR3 RDIMM support

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@freescale.com>
This commit is contained in:
york 2010-07-02 22:25:55 +00:00 committed by Kumar Gala
parent 7fd101c97b
commit 9490ff4864
6 changed files with 72 additions and 53 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;

View File

@ -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(

View File

@ -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;