Newer
Older
* Copyright 2008-2014 Freescale Semiconductor, Inc.
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
* Based on code from spd_sdram.c
* Author: James Yang [at freescale.com]
*/
#include <common.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr.h>
#include <asm/io.h>
/*
* Determine Rtt value.
*
* This should likely be either board or controller specific.
*
* 0 = Rtt disabled
* 1 = 75 ohm
* 2 = 150 ohm
* 3 = 50 ohm
* Rtt(nominal) - DDR3:
* 0 = Rtt disabled
* 1 = 60 ohm
* 2 = 120 ohm
* 3 = 40 ohm
* 4 = 20 ohm
* 5 = 30 ohm
*
* FIXME: Apparently 8641 needs a value of 2
* FIXME: Old code seys if 667 MHz or higher, use 3 on 8572
*
* FIXME: There was some effort down this line earlier:
*
* unsigned int i;
* for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) {
* if (popts->dimmslot[i].num_valid_cs
* && (popts->cs_local_opts[2*i].odt_rd_cfg
* || popts->cs_local_opts[2*i].odt_wr_cfg)) {
* rtt = 2;
* break;
* }
* }
*/
static inline int fsl_ddr_get_rtt(void)
{
int rtt;
#if defined(CONFIG_SYS_FSL_DDR1)
#elif defined(CONFIG_SYS_FSL_DDR2)
rtt = 3;
#else
#endif
return rtt;
}
#ifdef CONFIG_SYS_FSL_DDR4
/*
* compute CAS write latency according to DDR4 spec
* CWL = 9 for <= 1600MT/s
* 10 for <= 1866MT/s
* 11 for <= 2133MT/s
* 12 for <= 2400MT/s
* 14 for <= 2667MT/s
* 16 for <= 2933MT/s
* 18 for higher
*/
static inline unsigned int compute_cas_write_latency(
const unsigned int ctrl_num)
{
unsigned int cwl;
const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
if (mclk_ps >= 1250)
cwl = 9;
else if (mclk_ps >= 1070)
cwl = 10;
else if (mclk_ps >= 935)
cwl = 11;
else if (mclk_ps >= 833)
cwl = 12;
else if (mclk_ps >= 750)
cwl = 14;
else if (mclk_ps >= 681)
cwl = 16;
else
cwl = 18;
return cwl;
}
#else
/*
* compute the CAS write latency according to DDR3 spec
* CWL = 5 if tCK >= 2.5ns
* 6 if 2.5ns > tCK >= 1.875ns
* 7 if 1.875ns > tCK >= 1.5ns
* 8 if 1.5ns > tCK >= 1.25ns
* 9 if 1.25ns > tCK >= 1.07ns
* 10 if 1.07ns > tCK >= 0.935ns
* 11 if 0.935ns > tCK >= 0.833ns
* 12 if 0.833ns > tCK >= 0.75ns
static inline unsigned int compute_cas_write_latency(
const unsigned int ctrl_num)
const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
if (mclk_ps >= 2500)
cwl = 5;
else if (mclk_ps >= 1875)
cwl = 6;
else if (mclk_ps >= 1500)
cwl = 7;
else if (mclk_ps >= 1250)
cwl = 8;
else if (mclk_ps >= 1070)
cwl = 9;
else if (mclk_ps >= 935)
cwl = 10;
else if (mclk_ps >= 833)
cwl = 11;
else if (mclk_ps >= 750)
cwl = 12;
else {
cwl = 12;
printf("Warning: CWL is out of range\n");
}
/* Chip Select Configuration (CSn_CONFIG) */
static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
const memctl_options_t *popts,
const dimm_params_t *dimm_params)
{
unsigned int cs_n_en = 0; /* Chip Select enable */
unsigned int intlv_en = 0; /* Memory controller interleave enable */
unsigned int intlv_ctl = 0; /* Interleaving control */
unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */
unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */
unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */
unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */
unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */
unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */
#ifdef CONFIG_SYS_FSL_DDR4
unsigned int bg_bits_cs_n = 0; /* Num of bank group bits */
#else
unsigned int n_banks_per_sdram_device;
#endif
/* Compute CS_CONFIG only for existing ranks of each DIMM. */
switch (i) {
case 0:
if (dimm_params[dimm_number].n_ranks > 0) {
go_config = 1;
/* These fields only available in CS0_CONFIG */
if (!popts->memctl_interleaving)
break;
switch (popts->memctl_interleaving_mode) {
case FSL_DDR_256B_INTERLEAVING:
case FSL_DDR_CACHE_LINE_INTERLEAVING:
case FSL_DDR_PAGE_INTERLEAVING:
case FSL_DDR_BANK_INTERLEAVING:
case FSL_DDR_SUPERBANK_INTERLEAVING:
intlv_en = popts->memctl_interleaving;
intlv_ctl = popts->memctl_interleaving_mode;
break;
default:
break;
}
break;
case 1:
if ((dimm_number == 0 && dimm_params[0].n_ranks > 1) || \
(dimm_number == 1 && dimm_params[1].n_ranks > 0))
go_config = 1;
break;
case 2:
if ((dimm_number == 0 && dimm_params[0].n_ranks > 2) || \
(dimm_number >= 1 && dimm_params[dimm_number].n_ranks > 0))
break;
default:
break;
}
if (go_config) {
cs_n_en = 1;
ap_n_en = popts->cs_local_opts[i].auto_precharge;
odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
#ifdef CONFIG_SYS_FSL_DDR4
ba_bits_cs_n = dimm_params[dimm_number].bank_addr_bits;
bg_bits_cs_n = dimm_params[dimm_number].bank_group_bits;
#else
n_banks_per_sdram_device
= dimm_params[dimm_number].n_banks_per_sdram_device;
ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
row_bits_cs_n = dimm_params[dimm_number].n_row_addr - 12;
col_bits_cs_n = dimm_params[dimm_number].n_col_addr - 8;
}
ddr->cs[i].config = (0
| ((cs_n_en & 0x1) << 31)
| ((intlv_en & 0x3) << 29)
| ((ap_n_en & 0x1) << 23)
/* XXX: some implementation only have 1 bit starting at left */
| ((odt_rd_cfg & 0x7) << 20)
/* XXX: Some implementation only have 1 bit starting at left */
| ((odt_wr_cfg & 0x7) << 16)
| ((ba_bits_cs_n & 0x3) << 14)
| ((row_bits_cs_n & 0x7) << 8)
#ifdef CONFIG_SYS_FSL_DDR4
| ((bg_bits_cs_n & 0x3) << 4)
#endif
| ((col_bits_cs_n & 0x7) << 0)
);
debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config);
}
/* Chip Select Configuration 2 (CSn_CONFIG_2) */
/* FIXME: 8572 */
static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
{
unsigned int pasr_cfg = 0; /* Partial array self refresh config */
ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24);
debug("FSLDDR: cs[%d]_config_2 = 0x%08x\n", i, ddr->cs[i].config_2);
}
/* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */
#if !defined(CONFIG_SYS_FSL_DDR1)
/*
* Check DIMM configuration, return 2 if quad-rank or two dual-rank
* Return 1 if other two slots configuration. Return 0 if single slot.
*/
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 2;
#endif
#if CONFIG_DIMM_SLOTS_PER_CTLR == 2
if ((dimm_params[0].n_ranks == 2) &&
(dimm_params[1].n_ranks == 2))
return 2;
#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
if (dimm_params[0].n_ranks == 4)
return 2;
#endif
if ((dimm_params[0].n_ranks != 0) &&
(dimm_params[2].n_ranks != 0))
return 1;
#endif
return 0;
}
/*
* DDR SDRAM Timing Configuration 0 (TIMING_CFG_0)
*
* Avoid writing for DDR I. The new PQ38 DDR controller
* dreams up non-zero default values to be backwards compatible.
*/
static void set_timing_cfg_0(const unsigned int ctrl_num,
fsl_ddr_cfg_regs_t *ddr,
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 */
/* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */
unsigned char trrt_mclk = 0; /* Read-to-read turnaround */
unsigned char twwt_mclk = 0; /* Write-to-write turnaround */
/* Active powerdown exit timing (tXARD and tXARDS). */
unsigned char act_pd_exit_mclk;
/* Precharge powerdown exit timing (tXP). */
unsigned char pre_pd_exit_mclk;
/* ODT powerdown exit timing (tAXPD). */
unsigned char taxpd_mclk = 0;
/* Mode register set cycle time (tMRD). */
unsigned char tmrd_mclk;
#if defined(CONFIG_SYS_FSL_DDR4) || defined(CONFIG_SYS_FSL_DDR3)
const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num);
#ifdef CONFIG_SYS_FSL_DDR4
/* tXP=max(4nCK, 6ns) */
int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */
unsigned int data_rate = get_ddr_freq(ctrl_num);
/* for faster clock, need more time for data setup */
trwt_mclk = (data_rate/1000000 > 1900) ? 3 : 2;
act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
pre_pd_exit_mclk = act_pd_exit_mclk;
/*
* MRS_CYC = max(tMRD, tMOD)
* tMRD = 8nCK, tMOD = max(24nCK, 15ns)
*/
tmrd_mclk = max(24U, picos_to_mclk(ctrl_num, 15000));
#elif defined(CONFIG_SYS_FSL_DDR3)
unsigned int data_rate = get_ddr_freq(ctrl_num);
int odt_overlap;
/*
* (tXARD and tXARDS). Empirical?
* The DDR3 spec has not tXARD,
* we use the tXP instead of it.
* tXP=max(3nCK, 7.5ns) for DDR3-800, 1066
* max(3nCK, 6ns) for DDR3-1333, 1600, 1866, 2133
* tAXPD=1, need design to confirm.
txp = max((int)mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000));
ip_rev = fsl_ddr_get_version(ctrl_num);
if (ip_rev >= 0x40700) {
/*
* MRS_CYC = max(tMRD, tMOD)
* tMRD = 4nCK (8nCK for RDIMM)
* tMOD = max(12nCK, 15ns)
*/
tmrd_mclk = max((unsigned int)12,
picos_to_mclk(ctrl_num, 15000));
} else {
/*
* MRS_CYC = tMRD
* tMRD = 4nCK (8nCK for RDIMM)
*/
if (popts->registered_dimm_en)
tmrd_mclk = 8;
else
tmrd_mclk = 4;
}
/*
* for single quad-rank DIMM and two-slot DIMMs
* to avoid ODT overlap
*/
odt_overlap = avoid_odt_overlap(dimm_params);
switch (odt_overlap) {
case 2:
twwt_mclk = 2;
trrt_mclk = 1;
break;
case 1:
twwt_mclk = 1;
trrt_mclk = 0;
break;
default:
break;
}
/* 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;
if (popts->dynamic_power == 0) { /* powerdown is not used */
act_pd_exit_mclk = 1;
pre_pd_exit_mclk = 1;
taxpd_mclk = 1;
} else {
/* act_pd_exit_mclk = tXARD, see above */
act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp);
/* Mode register MR0[A12] is '1' - fast exit */
pre_pd_exit_mclk = act_pd_exit_mclk;
taxpd_mclk = 1;
}
#else /* CONFIG_SYS_FSL_DDR2 */
/*
* (tXARD and tXARDS). Empirical?
* tXARD = 2 for DDR2
* tXP=2
* tAXPD=8
*/
act_pd_exit_mclk = 2;
pre_pd_exit_mclk = 2;
taxpd_mclk = 8;
if (popts->trwt_override)
trwt_mclk = popts->trwt;
ddr->timing_cfg_0 = (0
| ((trwt_mclk & 0x3) << 30) /* RWT */
| ((twrt_mclk & 0x3) << 28) /* WRT */
| ((trrt_mclk & 0x3) << 26) /* RRT */
| ((twwt_mclk & 0x3) << 24) /* WWT */
| ((act_pd_exit_mclk & 0xf) << 20) /* ACT_PD_EXIT */
| ((pre_pd_exit_mclk & 0xF) << 16) /* PRE_PD_EXIT */
| ((taxpd_mclk & 0xf) << 8) /* ODT_PD_EXIT */
| ((tmrd_mclk & 0x1f) << 0) /* MRS_CYC */
);
debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
}
#endif /* !defined(CONFIG_SYS_FSL_DDR1) */
/* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */
static void set_timing_cfg_3(const unsigned int ctrl_num,
fsl_ddr_cfg_regs_t *ddr,
const memctl_options_t *popts,
const common_timing_params_t *common_dimm,
unsigned int cas_latency,
unsigned int additive_latency)
/* Extended precharge to activate interval (tRP) */
unsigned int ext_pretoact = 0;
/* Extended Activate to precharge interval (tRAS) */
unsigned int ext_acttopre = 0;
/* Extended activate to read/write interval (tRCD) */
unsigned int ext_acttorw = 0;
/* Extended refresh recovery time (tRFC) */
unsigned int ext_refrec;
/* Extended MCAS latency from READ cmd */
unsigned int ext_caslat = 0;
/* Extended additive latency */
unsigned int ext_add_lat = 0;
/* Extended last data to precharge interval (tWR) */
unsigned int ext_wrrec = 0;
/* Control Adjust */
unsigned int cntl_adj = 0;
ext_pretoact = picos_to_mclk(ctrl_num, common_dimm->trp_ps) >> 4;
ext_acttopre = picos_to_mclk(ctrl_num, common_dimm->tras_ps) >> 4;
ext_acttorw = picos_to_mclk(ctrl_num, common_dimm->trcd_ps) >> 4;
ext_caslat = (2 * cas_latency - 1) >> 4;
ext_add_lat = additive_latency >> 4;
#ifdef CONFIG_SYS_FSL_DDR4
ext_refrec = (picos_to_mclk(ctrl_num, common_dimm->trfc1_ps) - 8) >> 4;
Loading
Loading full blame...