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))
Loading
Loading full blame...