summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/cpu/mpc8xxx
diff options
context:
space:
mode:
authorYork Sun <yorksun@freescale.com>2013-06-25 11:37:48 -0700
committerYork Sun <yorksun@freescale.com>2013-08-09 12:41:39 -0700
commitc63e137014cf148bc1d234128941dccee3d519ae (patch)
treeafb69c22c33459d14a174973083e2a70e5f49ea7 /arch/powerpc/cpu/mpc8xxx
parentb61e06156660579ea6e248abd2506ebdd85e7a14 (diff)
downloadblackbird-obmc-uboot-c63e137014cf148bc1d234128941dccee3d519ae.tar.gz
blackbird-obmc-uboot-c63e137014cf148bc1d234128941dccee3d519ae.zip
powerpc/mpc8xxx: Add memory reset control
JEDEC spec requires the clocks to be stable before deasserting reset signal for RDIMMs. Clocks start when any chip select is enabled and clock control register is set. This patch also adds the interface to toggle memory reset signal if needed by the boards. Signed-off-by: York Sun <yorksun@freescale.com>
Diffstat (limited to 'arch/powerpc/cpu/mpc8xxx')
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/ddr.h2
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/main.c54
2 files changed, 48 insertions, 8 deletions
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 */
OpenPOWER on IntegriCloud