summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen1.c2
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen2.c2
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen3.c29
-rw-r--r--arch/powerpc/cpu/mpc86xx/ddr-8641.c2
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/ddr.h2
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/main.c54
-rw-r--r--arch/powerpc/include/asm/fsl_ddr_sdram.h24
-rw-r--r--board/freescale/bsc9131rdb/ddr.c2
-rw-r--r--board/freescale/bsc9132qds/ddr.c2
-rw-r--r--board/freescale/common/qixis.c20
-rw-r--r--board/freescale/corenet_ds/ddr.c4
-rw-r--r--board/freescale/p1010rdb/ddr.c2
-rw-r--r--board/freescale/p1_p2_rdb/ddr.c2
-rw-r--r--board/freescale/p1_p2_rdb_pc/ddr.c2
-rw-r--r--board/freescale/p1_twr/ddr.c2
-rw-r--r--include/configs/T4240QDS.h1
16 files changed, 131 insertions, 21 deletions
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen1.c b/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
index 8a86819fb5..4dd8c0b5bf 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
@@ -15,7 +15,7 @@
#endif
void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
- unsigned int ctrl_num)
+ unsigned int ctrl_num, int step)
{
unsigned int i;
volatile ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen2.c b/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
index a705862522..542bc84acf 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
@@ -16,7 +16,7 @@
#endif
void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
- unsigned int ctrl_num)
+ unsigned int ctrl_num, int step)
{
unsigned int i;
ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
index 3e7a56489f..1be51d3307 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -15,8 +15,18 @@
#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
#endif
+
+/*
+ * regs has the to-be-set values for DDR controller registers
+ * ctrl_num is the DDR controller number
+ * step: 0 goes through the initialization in one pass
+ * 1 sets registers and returns before enabling controller
+ * 2 resumes from step 1 and continues to initialize
+ * Dividing the initialization to two steps to deassert DDR reset signal
+ * to comply with JEDEC specs for RDIMMs.
+ */
void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
- unsigned int ctrl_num)
+ unsigned int ctrl_num, int step)
{
unsigned int i, bus_width;
volatile ccsr_ddr_t *ddr;
@@ -54,6 +64,9 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
return;
}
+ if (step == 2)
+ goto step2;
+
if (regs->ddr_eor)
out_be32(&ddr->eor, regs->ddr_eor);
#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
@@ -157,6 +170,20 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
out_be32(&ddr->debug[21], 0x24000000);
#endif /* CONFIG_SYS_FSL_ERRATUM_DDR_A003474 */
+ /*
+ * For RDIMMs, JEDEC spec requires clocks to be stable before reset is
+ * deasserted. Clocks start when any chip select is enabled and clock
+ * control register is set. Because all DDR components are connected to
+ * one reset signal, this needs to be done in two steps. Step 1 is to
+ * get the clocks started. Step 2 resumes after reset signal is
+ * deasserted.
+ */
+ if (step == 1) {
+ udelay(200);
+ return;
+ }
+
+step2:
/* Set, but do not enable the memory */
temp_sdram_cfg = regs->ddr_sdram_cfg;
temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
diff --git a/arch/powerpc/cpu/mpc86xx/ddr-8641.c b/arch/powerpc/cpu/mpc86xx/ddr-8641.c
index 92ba26dc8e..33a91f9f78 100644
--- a/arch/powerpc/cpu/mpc86xx/ddr-8641.c
+++ b/arch/powerpc/cpu/mpc86xx/ddr-8641.c
@@ -15,7 +15,7 @@
#endif
void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
- unsigned int ctrl_num)
+ unsigned int ctrl_num, int step)
{
unsigned int i;
volatile ccsr_ddr_t *ddr;
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h b/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h
index 4dd55fc4c3..c173a5a74b 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h
@@ -96,7 +96,7 @@ unsigned int check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr);
/* processor specific function */
void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
- unsigned int ctrl_num);
+ unsigned int ctrl_num, int step);
/* board specific function */
int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/main.c b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
index c35405dcc9..9f4f25343b 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/main.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
@@ -25,10 +25,6 @@ void fsl_ddr_set_lawbar(
unsigned int ctrl_num);
void fsl_ddr_set_intl3r(const unsigned int granule_size);
-/* processor specific function */
-extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
- unsigned int ctrl_num);
-
#if defined(SPD_EEPROM_ADDRESS) || \
defined(SPD_EEPROM_ADDRESS1) || defined(SPD_EEPROM_ADDRESS2) || \
defined(SPD_EEPROM_ADDRESS3) || defined(SPD_EEPROM_ADDRESS4)
@@ -365,9 +361,11 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
{
unsigned int i, j;
unsigned long long total_mem = 0;
+ int assert_reset;
fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg;
common_timing_params_t *timing_params = pinfo->common_timing_params;
+ assert_reset = board_need_mem_reset();
/* data bus width capacity adjust shift amount */
unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS];
@@ -462,7 +460,20 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
timing_params[i].all_DIMMs_registered,
&pinfo->memctl_opts[i],
pinfo->dimm_params[i], i);
+ /*
+ * For RDIMMs, JEDEC spec requires clocks to be stable
+ * before reset signal is deasserted. For the boards
+ * using fixed parameters, this function should be
+ * be called from board init file.
+ */
+ if (timing_params[i].all_DIMMs_registered)
+ assert_reset = 1;
+ }
+ if (assert_reset) {
+ debug("Asserting mem reset\n");
+ board_assert_mem_reset();
}
+
case STEP_ASSIGN_ADDRESSES:
/* STEP 5: Assign addresses to chip selects */
check_interleaving_options(pinfo);
@@ -537,6 +548,7 @@ phys_size_t fsl_ddr_sdram(void)
unsigned int law_memctl = LAW_TRGT_IF_DDR_1;
unsigned long long total_memory;
fsl_ddr_info_t info;
+ int deassert_reset;
/* Reset info structure. */
memset(&info, 0, sizeof(fsl_ddr_info_t));
@@ -565,7 +577,21 @@ phys_size_t fsl_ddr_sdram(void)
}
}
- /* Program configuration registers. */
+ /*
+ * Program configuration registers.
+ * JEDEC specs requires clocks to be stable before deasserting reset
+ * for RDIMMs. Clocks start after chip select is enabled and clock
+ * control register is set. During step 1, all controllers have their
+ * registers set but not enabled. Step 2 proceeds after deasserting
+ * reset through board FPGA or GPIO.
+ * For non-registered DIMMs, initialization can go through but it is
+ * also OK to follow the same flow.
+ */
+ deassert_reset = board_need_mem_reset();
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (info.common_timing_params[i].all_DIMMs_registered)
+ deassert_reset = 1;
+ }
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
debug("Programming controller %u\n", i);
if (info.common_timing_params[i].ndimms_present == 0) {
@@ -573,8 +599,22 @@ phys_size_t fsl_ddr_sdram(void)
"skipping programming\n", i);
continue;
}
-
- fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i);
+ /*
+ * The following call with step = 1 returns before enabling
+ * the controller. It has to finish with step = 2 later.
+ */
+ fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i,
+ deassert_reset ? 1 : 0);
+ }
+ if (deassert_reset) {
+ /* Use board FPGA or GPIO to deassert reset signal */
+ debug("Deasserting mem reset\n");
+ board_deassert_mem_reset();
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ /* Call with step = 2 to continue initialization */
+ fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]),
+ i, 2);
+ }
}
/* program LAWs */
diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h
index bac22fcd1d..f4eec82d5d 100644
--- a/arch/powerpc/include/asm/fsl_ddr_sdram.h
+++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h
@@ -331,9 +331,31 @@ extern phys_size_t fsl_ddr_sdram(void);
extern phys_size_t fsl_ddr_sdram_size(void);
extern int fsl_use_spd(void);
extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
- unsigned int ctrl_num);
+ unsigned int ctrl_num, int step);
u32 fsl_ddr_get_intl3r(void);
+static void __board_assert_mem_reset(void)
+{
+}
+
+static void __board_deassert_mem_reset(void)
+{
+}
+
+void board_assert_mem_reset(void)
+ __attribute__((weak, alias("__board_assert_mem_reset")));
+
+void board_deassert_mem_reset(void)
+ __attribute__((weak, alias("__board_deassert_mem_reset")));
+
+static int __board_need_mem_reset(void)
+{
+ return 0;
+}
+
+int board_need_mem_reset(void)
+ __attribute__((weak, alias("__board_need_mem_reset")));
+
/*
* The 85xx boards have a common prototype for fixed_sdram so put the
* declaration here.
diff --git a/board/freescale/bsc9131rdb/ddr.c b/board/freescale/bsc9131rdb/ddr.c
index a4161ad649..c82fe0aab3 100644
--- a/board/freescale/bsc9131rdb/ddr.c
+++ b/board/freescale/bsc9131rdb/ddr.c
@@ -87,7 +87,7 @@ phys_size_t fixed_sdram(void)
}
ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
- fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0);
+ fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE, ddr_size,
LAW_TRGT_IF_DDR_1) < 0) {
diff --git a/board/freescale/bsc9132qds/ddr.c b/board/freescale/bsc9132qds/ddr.c
index 05bea8ad52..fdea193129 100644
--- a/board/freescale/bsc9132qds/ddr.c
+++ b/board/freescale/bsc9132qds/ddr.c
@@ -109,7 +109,7 @@ phys_size_t fixed_sdram(void)
strmhz(buf, ddr_freq));
ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
- fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0);
+ fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE, ddr_size,
LAW_TRGT_IF_DDR_1) < 0) {
diff --git a/board/freescale/common/qixis.c b/board/freescale/common/qixis.c
index 40ce6b082d..a49e3006d9 100644
--- a/board/freescale/common/qixis.c
+++ b/board/freescale/common/qixis.c
@@ -107,6 +107,26 @@ const char *byte_to_binary_mask(u8 val, u8 mask, char *buf)
return buf;
}
+#ifdef QIXIS_RST_FORCE_MEM
+void board_assert_mem_reset(void)
+{
+ u8 rst;
+
+ rst = QIXIS_READ(rst_frc[0]);
+ if (!(rst & QIXIS_RST_FORCE_MEM))
+ QIXIS_WRITE(rst_frc[0], rst | QIXIS_RST_FORCE_MEM);
+}
+
+void board_deassert_mem_reset(void)
+{
+ u8 rst;
+
+ rst = QIXIS_READ(rst_frc[0]);
+ if (rst & QIXIS_RST_FORCE_MEM)
+ QIXIS_WRITE(rst_frc[0], rst & ~QIXIS_RST_FORCE_MEM);
+}
+#endif
+
void qixis_reset(void)
{
QIXIS_WRITE(rst_ctl, QIXIS_RST_CTL_RESET);
diff --git a/board/freescale/corenet_ds/ddr.c b/board/freescale/corenet_ds/ddr.c
index da284cde95..517e87ff4c 100644
--- a/board/freescale/corenet_ds/ddr.c
+++ b/board/freescale/corenet_ds/ddr.c
@@ -56,14 +56,14 @@ phys_size_t fixed_sdram(void)
ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
ddr_cfg_regs.ddr_cdr1 = DDR_CDR1_DHC_EN;
- fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0);
+ fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
#if (CONFIG_NUM_DDR_CONTROLLERS == 2)
memcpy(&ddr_cfg_regs,
fixed_ddr_parm_1[i].ddr_settings,
sizeof(ddr_cfg_regs));
ddr_cfg_regs.ddr_cdr1 = DDR_CDR1_DHC_EN;
- fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 1);
+ fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 1, 0);
#endif
/*
diff --git a/board/freescale/p1010rdb/ddr.c b/board/freescale/p1010rdb/ddr.c
index aa8badab48..681f052e41 100644
--- a/board/freescale/p1010rdb/ddr.c
+++ b/board/freescale/p1010rdb/ddr.c
@@ -139,7 +139,7 @@ phys_size_t fixed_sdram(void)
}
ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
- fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0);
+ fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE, ddr_size,
LAW_TRGT_IF_DDR_1) < 0) {
diff --git a/board/freescale/p1_p2_rdb/ddr.c b/board/freescale/p1_p2_rdb/ddr.c
index 0038077fcc..5bee22e638 100644
--- a/board/freescale/p1_p2_rdb/ddr.c
+++ b/board/freescale/p1_p2_rdb/ddr.c
@@ -220,7 +220,7 @@ phys_size_t fixed_sdram (void)
ddr_cfg_regs.cs[0].bnds = 0x0000001F;
}
- fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0);
+ fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
set_ddr_laws(0, ddr_size, LAW_TRGT_IF_DDR_1);
return ddr_size;
diff --git a/board/freescale/p1_p2_rdb_pc/ddr.c b/board/freescale/p1_p2_rdb_pc/ddr.c
index 9355536b35..14f0539b4e 100644
--- a/board/freescale/p1_p2_rdb_pc/ddr.c
+++ b/board/freescale/p1_p2_rdb_pc/ddr.c
@@ -251,7 +251,7 @@ phys_size_t fixed_sdram(void)
ddr_size = CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
- fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0);
+ fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE,
ddr_size, LAW_TRGT_IF_DDR_1) < 0) {
diff --git a/board/freescale/p1_twr/ddr.c b/board/freescale/p1_twr/ddr.c
index ff278ae9f1..f94e1ab175 100644
--- a/board/freescale/p1_twr/ddr.c
+++ b/board/freescale/p1_twr/ddr.c
@@ -59,7 +59,7 @@ phys_size_t fixed_sdram(void)
ddr_size = CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
- fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0);
+ fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE,
ddr_size, LAW_TRGT_IF_DDR_1) < 0) {
diff --git a/include/configs/T4240QDS.h b/include/configs/T4240QDS.h
index 2cf4a69f2a..d92de3596c 100644
--- a/include/configs/T4240QDS.h
+++ b/include/configs/T4240QDS.h
@@ -161,6 +161,7 @@ unsigned long get_board_ddr_clk(void);
#define QIXIS_LBMAP_DFLTBANK 0x00
#define QIXIS_LBMAP_ALTBANK 0x04
#define QIXIS_RST_CTL_RESET 0x83
+#define QIXIS_RST_FORCE_MEM 0x1
#define QIXIS_RCFG_CTL_RECONFIG_IDLE 0x20
#define QIXIS_RCFG_CTL_RECONFIG_START 0x21
#define QIXIS_RCFG_CTL_WATCHDOG_ENBLE 0x08