diff options
Diffstat (limited to 'arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c')
-rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c | 86 |
1 files changed, 69 insertions, 17 deletions
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c index 2592873..088cc0e 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -28,7 +28,7 @@ #error "Undefined _DDR_ADDR" #endif -u32 fsl_ddr_get_version(void) +static u32 fsl_ddr_get_version(void) { ccsr_ddr_t *ddr; u32 ver_major_minor_errata; @@ -229,6 +229,26 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr) /* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */ #if !defined(CONFIG_FSL_DDR1) +static inline int avoid_odt_overlap(const dimm_params_t *dimm_params) +{ +#if CONFIG_DIMM_SLOTS_PER_CTLR == 1 + if (dimm_params[0].n_ranks == 4) + return 1; +#endif + +#if CONFIG_DIMM_SLOTS_PER_CTLR == 2 + if ((dimm_params[0].n_ranks == 2) && + (dimm_params[1].n_ranks == 2)) + return 1; + +#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE + if (dimm_params[0].n_ranks == 4) + return 1; +#endif +#endif + return 0; +} + /* * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0) * @@ -236,7 +256,8 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr) * dreams up non-zero default values to be backwards compatible. */ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, - const memctl_options_t *popts) + const memctl_options_t *popts, + const dimm_params_t *dimm_params) { unsigned char trwt_mclk = 0; /* Read-to-write turnaround */ unsigned char twrt_mclk = 0; /* Write-to-read turnaround */ @@ -266,7 +287,18 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr, unsigned int data_rate = get_ddr_freq(0); tmrd_mclk = 4; /* set the turnaround time */ - trwt_mclk = 1; + + /* + * for single quad-rank DIMM and two dual-rank DIMMs + * to avoid ODT overlap + */ + if (avoid_odt_overlap(dimm_params)) { + twwt_mclk = 2; + trrt_mclk = 1; + } + /* for faster clock, need more time for data setup */ + trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1; + if ((data_rate/1000000 > 1150) || (popts->memctl_interleaving)) twrt_mclk = 1; @@ -451,8 +483,8 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, | ((caslat_ctrl & 0xF) << 16) | ((refrec_ctrl & 0xF) << 12) | ((wrrec_mclk & 0x0F) << 8) - | ((acttoact_mclk & 0x07) << 4) - | ((wrtord_mclk & 0x07) << 0) + | ((acttoact_mclk & 0x0F) << 4) + | ((wrtord_mclk & 0x0F) << 0) ); debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1); } @@ -659,6 +691,7 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, unsigned int dqs_cfg; /* DQS configuration */ unsigned int odt_cfg = 0; /* ODT configuration */ unsigned int num_pr; /* Number of posted refreshes */ + unsigned int slow = 0; /* DDR will be run less than 1250 */ unsigned int obc_cfg; /* On-The-Fly Burst Chop Cfg */ unsigned int ap_en; /* Address Parity Enable */ unsigned int d_init; /* DRAM data initialization */ @@ -692,6 +725,10 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, obc_cfg = 0; #endif +#if (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7) + slow = get_ddr_freq(0) < 1249000000; +#endif + if (popts->registered_dimm_en) { rcw_en = 1; ap_en = popts->ap_en; @@ -720,6 +757,7 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, | ((dqs_cfg & 0x3) << 26) | ((odt_cfg & 0x3) << 21) | ((num_pr & 0xf) << 12) + | ((slow & 1) << 11) | (qd_en << 9) | (unq_mrs_en << 8) | ((obc_cfg & 0x1) << 6) @@ -1347,6 +1385,11 @@ static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en, | ((wrlvl_start & 0x1F) << 0) ); debug("FSLDDR: wrlvl_cntl = 0x%08x\n", ddr->ddr_wrlvl_cntl); + ddr->ddr_wrlvl_cntl_2 = popts->wrlvl_ctl_2; + debug("FSLDDR: wrlvl_cntl_2 = 0x%08x\n", ddr->ddr_wrlvl_cntl_2); + ddr->ddr_wrlvl_cntl_3 = popts->wrlvl_ctl_3; + debug("FSLDDR: wrlvl_cntl_3 = 0x%08x\n", ddr->ddr_wrlvl_cntl_3); + } /* DDR Self Refresh Counter (DDR_SR_CNTR) */ @@ -1370,6 +1413,12 @@ static void set_ddr_cdr1(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts) debug("FSLDDR: ddr_cdr1 = 0x%08x\n", ddr->ddr_cdr1); } +static void set_ddr_cdr2(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts) +{ + ddr->ddr_cdr2 = popts->ddr_cdr2; + debug("FSLDDR: ddr_cdr2 = 0x%08x\n", ddr->ddr_cdr2); +} + unsigned int check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr) { @@ -1466,7 +1515,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, break; } sa = common_dimm->base_address; - ea = common_dimm->total_mem - 1; + ea = sa + common_dimm->total_mem - 1; } else if (!popts->memctl_interleaving) { /* * If memory interleaving between controllers is NOT @@ -1480,7 +1529,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { case FSL_DDR_CS0_CS1_CS2_CS3: sa = common_dimm->base_address; - ea = common_dimm->total_mem - 1; + ea = sa + common_dimm->total_mem - 1; break; case FSL_DDR_CS0_CS1_AND_CS2_CS3: if ((i >= 2) && (dimm_number == 0)) { @@ -1537,17 +1586,19 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, sa >>= 24; ea >>= 24; - ddr->cs[i].bnds = (0 - | ((sa & 0xFFF) << 16) /* starting address MSB */ - | ((ea & 0xFFF) << 0) /* ending address MSB */ - ); + if (cs_en) { + ddr->cs[i].bnds = (0 + | ((sa & 0xFFF) << 16)/* starting address MSB */ + | ((ea & 0xFFF) << 0) /* ending address MSB */ + ); + } else { + debug("FSLDDR: setting bnds to 0 for inactive CS\n"); + ddr->cs[i].bnds = 0; + } debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds); - if (cs_en) { - set_csn_config(dimm_number, i, ddr, popts, dimm_params); - set_csn_config_2(i, ddr); - } else - debug("CS%d is disabled.\n", i); + set_csn_config(dimm_number, i, ddr, popts, dimm_params); + set_csn_config_2(i, ddr); } /* @@ -1560,7 +1611,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, set_ddr_eor(ddr, popts); #if !defined(CONFIG_FSL_DDR1) - set_timing_cfg_0(ddr, popts); + set_timing_cfg_0(ddr, popts, dimm_params); #endif set_timing_cfg_3(ddr, popts, common_dimm, cas_latency); @@ -1569,6 +1620,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, cas_latency, additive_latency); set_ddr_cdr1(ddr, popts); + set_ddr_cdr2(ddr, popts); set_ddr_sdram_cfg(ddr, popts, common_dimm); ip_rev = fsl_ddr_get_version(); if (ip_rev > 0x40400) |