summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c62
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c16
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/options.c12
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/util.c12
-rw-r--r--arch/powerpc/include/asm/fsl_ddr_sdram.h2
5 files changed, 87 insertions, 17 deletions
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
index c28f9cd..5928eb8 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
@@ -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;
@@ -1483,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
@@ -1497,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)) {
@@ -1554,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);
}
/*
@@ -1577,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);
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 03a784c..6a1f4e4 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_cas_latency_ddr3(const dimm_params_t *dimm_params,
unsigned int
compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
common_timing_params_t *outpdimm,
- unsigned int number_of_dimms)
+ const unsigned int number_of_dimms)
{
unsigned int i, j;
@@ -126,13 +126,20 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
temp1++;
continue;
}
+
+ /*
+ * check if quad-rank DIMM is plugged if
+ * CONFIG_CHIP_SELECT_QUAD_CAPABLE is not defined
+ * Only the board with proper design is capable
+ */
+#ifndef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
if (dimm_params[i].n_ranks == 4 && \
CONFIG_CHIP_SELECTS_PER_CTRL/CONFIG_DIMM_SLOTS_PER_CTLR < 4) {
printf("Found Quad-rank DIMM, not able to support.");
temp1++;
continue;
}
-
+#endif
/*
* Find minimum tCKmax_ps to find fastest slow speed,
* i.e., this is the slowest the whole system can go.
@@ -236,11 +243,14 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
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++)
+ for (i = 1; i < number_of_dimms; i++) {
+ if (!dimm_params[i].n_ranks)
+ continue;
if (dimm_params[i].rcw[j] != dimm_params[0].rcw[j]) {
temp1 = 1;
break;
}
+ }
}
if (temp1 != 0)
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
index 13e4825..1188df9 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/options.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
@@ -510,6 +510,14 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
}
} else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
switch (pdimm[0].n_ranks) {
+#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+ case 4:
+ pdodt = single_Q;
+ if (pdimm[1].n_ranks)
+ printf("Error: Quad- and Dual-rank DIMMs "
+ "cannot be used together\n");
+ break;
+#endif
case 2:
switch (pdimm[1].n_ranks) {
case 2:
@@ -912,6 +920,10 @@ done:
"interleaving disabled!\n", ctrl_num);
}
#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+ if (pdimm[0].n_ranks == 4)
+ break;
+#endif
if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) {
popts->ba_intlv_ctl = 0;
printf("Not enough bank(chip-select) for "
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/util.c b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
index 664ad09..b439cc9 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/util.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
@@ -140,6 +140,18 @@ void board_add_ram_info(int use_default)
uint32_t sdram_cfg = in_be32(&ddr->sdram_cfg);
int cas_lat;
+#if CONFIG_NUM_DDR_CONTROLLERS >= 2
+ if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
+ ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
+ sdram_cfg = in_be32(&ddr->sdram_cfg);
+ }
+#endif
+#if CONFIG_NUM_DDR_CONTROLLERS >= 3
+ if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
+ ddr = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
+ sdram_cfg = in_be32(&ddr->sdram_cfg);
+ }
+#endif
puts(" (DDR");
switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
SDRAM_CFG_SDRAM_TYPE_SHIFT) {
diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h
index 9cf9bd4..bb79335 100644
--- a/arch/powerpc/include/asm/fsl_ddr_sdram.h
+++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h
@@ -84,6 +84,8 @@ typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
#define FSL_DDR_4WAY_4KB_INTERLEAVING 0x1C
#define FSL_DDR_4WAY_8KB_INTERLEAVING 0x1D
+#define SDRAM_CS_CONFIG_EN 0x80000000
+
/* DDR_SDRAM_CFG - DDR SDRAM Control Configuration
*/
#define SDRAM_CFG_MEM_EN 0x80000000