/*
* Copyright 2008-2012 Freescale Semiconductor, Inc.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
+ * SPDX-License-Identifier: GPL-2.0+
*/
/*
#include "ddr.h"
-#ifdef CONFIG_MPC83xx
- #define _DDR_ADDR CONFIG_SYS_MPC83xx_DDR_ADDR
-#elif defined(CONFIG_MPC85xx)
- #define _DDR_ADDR CONFIG_SYS_MPC85xx_DDR_ADDR
-#elif defined(CONFIG_MPC86xx)
- #define _DDR_ADDR CONFIG_SYS_MPC86xx_DDR_ADDR
-#else
- #error "Undefined _DDR_ADDR"
-#endif
+#define _DDR_ADDR CONFIG_SYS_MPC8xxx_DDR_ADDR
-u32 fsl_ddr_get_version(void)
+static u32 fsl_ddr_get_version(void)
{
ccsr_ddr_t *ddr;
u32 ver_major_minor_errata;
/* -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)
*
* 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 */
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;
ddr->timing_cfg_3 = (0
| ((ext_pretoact & 0x1) << 28)
- | ((ext_acttopre & 0x2) << 24)
+ | ((ext_acttopre & 0x3) << 24)
| ((ext_acttorw & 0x1) << 22)
| ((ext_refrec & 0x1F) << 16)
| ((ext_caslat & 0x3) << 12)
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 x4_en = 0; /* x4 DRAM enable */
unsigned int obc_cfg; /* On-The-Fly Burst Chop Cfg */
unsigned int ap_en; /* Address Parity Enable */
unsigned int d_init; /* DRAM data initialization */
ap_en = 0;
}
+ x4_en = popts->x4_en ? 1 : 0;
+
#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
/* Use the DDR controller to auto initialize memory. */
d_init = popts->ECC_init_using_memctl;
| ((odt_cfg & 0x3) << 21)
| ((num_pr & 0xf) << 12)
| ((slow & 1) << 11)
+ | (x4_en << 10)
| (qd_en << 9)
| (unq_mrs_en << 8)
| ((obc_cfg & 0x1) << 6)
{
unsigned int init_value; /* Initialization value */
+#ifdef CONFIG_MEM_INIT_VALUE
+ init_value = CONFIG_MEM_INIT_VALUE;
+#else
init_value = 0xDEADBEEF;
+#endif
ddr->ddr_data_init = init_value;
}
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
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)) {
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 {
+ /* setting bnds to 0xffffffff for inactive CS */
+ ddr->cs[i].bnds = 0xffffffff;
+ }
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);
}
/*
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);
set_ddr_sdram_rcw(ddr, popts, common_dimm);
+#ifdef CONFIG_SYS_FSL_DDR_EMU
+ /* disble DDR training for emulator */
+ ddr->debug[2] = 0x00000400;
+ ddr->debug[4] = 0xff800000;
+#endif
return check_fsl_memctl_config_regs(ddr);
}