From 9490ff48648d969caeb70dbc6e506175f8699617 Mon Sep 17 00:00:00 2001 From: york Date: Fri, 2 Jul 2010 22:25:55 +0000 Subject: 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 --- .../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 ++++- 4 files changed, 55 insertions(+), 53 deletions(-) (limited to 'arch/powerpc/cpu') 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; -- cgit v1.1