diff options
author | york <yorksun@freescale.com> | 2010-07-02 22:25:55 +0000 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2010-07-26 13:16:10 -0500 |
commit | 9490ff48648d969caeb70dbc6e506175f8699617 (patch) | |
tree | 19d3caa8fa415392cb93e304c925a3dc5a58cbe5 /arch/powerpc/cpu/mpc8xxx | |
parent | 7fd101c97b58dab7b0bd87f30c3dedb0db21d15f (diff) |
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>
Diffstat (limited to 'arch/powerpc/cpu/mpc8xxx')
-rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h | 3 | ||||
-rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c | 81 | ||||
-rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c | 6 | ||||
-rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c | 18 |
4 files changed, 55 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 5aea517f25..06706ed78c 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 ff0ddd1894..b2962d26c4 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 d4199baa82..29cea53266 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 ce6c148d09..029e566b6b 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; |