diff options
| author | Haiying Wang <Haiying.Wang@freescale.com> | 2008-10-03 12:36:39 -0400 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2008-10-18 21:54:04 +0200 | 
| commit | dbbbb3abeff325855cae76e33d69d5665631443f (patch) | |
| tree | 2df59a7ac7364e4c501e228c74db3cd5f14ad3b1 | |
| parent | 1c9aa76bf9013069e24258f46f4687c9f98a02d6 (diff) | |
| download | olio-uboot-2014.01-dbbbb3abeff325855cae76e33d69d5665631443f.tar.xz olio-uboot-2014.01-dbbbb3abeff325855cae76e33d69d5665631443f.zip | |
Make DDR interleaving mode work correctly
Fix some bugs:
  1. Correctly set intlv_ctl in cs_config.
  2. Correctly set sa, ea in cs_bnds when bank interleaving mode is enabled.
  3. Set base_address and total memory for each ddr controller in memory
     controller interleaving mode.
Signed-off-by: Haiying Wang <Haiying.Wang@freescale.com>
| -rw-r--r-- | cpu/mpc8xxx/ddr/ctrl_regs.c | 61 | ||||
| -rw-r--r-- | cpu/mpc8xxx/ddr/main.c | 5 | ||||
| -rw-r--r-- | include/asm-ppc/fsl_ddr_sdram.h | 12 | 
3 files changed, 66 insertions, 12 deletions
| diff --git a/cpu/mpc8xxx/ddr/ctrl_regs.c b/cpu/mpc8xxx/ddr/ctrl_regs.c index e6c2a5ce7..629714116 100644 --- a/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -95,16 +95,10 @@ static void set_csn_config(int i, fsl_ddr_cfg_regs_t *ddr,  		col_bits_cs_n = dimm_params[i/2].n_col_addr - 8;  	} -	/* FIXME: intlv_en, intlv_ctl only on CS0_CONFIG */ -	if (i != 0) { -		intlv_en = 0; -		intlv_ctl = 0; -	} -  	ddr->cs[i].config = (0  		| ((cs_n_en & 0x1) << 31)  		| ((intlv_en & 0x3) << 29) -		| ((intlv_en & 0xf) << 24) +		| ((intlv_ctl & 0xf) << 24)  		| ((ap_n_en & 0x1) << 23)  		/* XXX: some implementation only have 1 bit starting at left */ @@ -874,8 +868,13 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,  	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {  		phys_size_t sa = 0;  		phys_size_t ea = 0; -		if (popts->ba_intlv_ctl && i > 0) { -			/* Don't set up boundaries if bank interleaving */ + +		if (popts->ba_intlv_ctl && (i > 0) && +			((popts->ba_intlv_ctl & 0x60) != FSL_DDR_CS2_CS3 )) { +			/* Don't set up boundaries for other CS +			 * other than CS0, if bank interleaving +			 * is enabled and not CS2+CS3 interleaved. +			 */  			break;  		} @@ -894,7 +893,9 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,  			 * on each controller is twice the amount present on  			 * each controller.  			 */ -			ea = (2 * common_dimm->total_mem >> dbw_cap_adj) - 1; +			unsigned long long rank_density +					= dimm_params[0].capacity; +			ea = (2 * (rank_density >> dbw_cap_adj)) - 1;  		}  		else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) {  			/* @@ -906,8 +907,44 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,  			 * controller needs to be programmed into its  			 * respective CS0_BNDS.  			 */ -			sa = common_dimm->base_address; -			ea = sa + (common_dimm->total_mem >> dbw_cap_adj) - 1; +			unsigned long long rank_density +						= dimm_params[i/2].rank_density; +			switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { +			case FSL_DDR_CS0_CS1_CS2_CS3: +				/* CS0+CS1+CS2+CS3 interleaving, only CS0_CNDS +				 * needs to be set. +				 */ +				sa = common_dimm->base_address; +				ea = sa + (4 * (rank_density >> dbw_cap_adj))-1; +				break; +			case FSL_DDR_CS0_CS1_AND_CS2_CS3: +				/* CS0+CS1 and CS2+CS3 interleaving, CS0_CNDS +				 * and CS2_CNDS need to be set. +				 */ +				if (!(i&1)) { +					sa = dimm_params[i/2].base_address; +					ea = sa + (i * (rank_density >> +						dbw_cap_adj)) - 1; +				} +				break; +			case FSL_DDR_CS0_CS1: +				/* CS0+CS1 interleaving, CS0_CNDS needs +				 * to be set +				 */ +				sa = common_dimm->base_address; +				ea = sa + (2 * (rank_density >> dbw_cap_adj))-1; +				break; +			case FSL_DDR_CS2_CS3: +				/* CS2+CS3 interleaving*/ +				if (i == 2) { +					sa = dimm_params[i/2].base_address; +					ea = sa + (2 * (rank_density >> +						dbw_cap_adj)) - 1; +				} +				break; +			default:  /* No bank(chip-select) interleaving */ +				break; +			}  		}  		else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) {  			/* diff --git a/cpu/mpc8xxx/ddr/main.c b/cpu/mpc8xxx/ddr/main.c index c340d569f..d26c5c5c2 100644 --- a/cpu/mpc8xxx/ddr/main.c +++ b/cpu/mpc8xxx/ddr/main.c @@ -179,6 +179,7 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,  	if (*memctl_interleaving) {  		phys_addr_t addr; +		phys_size_t total_mem_per_ctlr = 0;  		/*  		 * If interleaving between memory controllers, @@ -197,14 +198,18 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,  		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {  			addr = 0; +			pinfo->common_timing_params[i].base_address = +						(phys_addr_t)addr;  			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {  				unsigned long long cap  					= pinfo->dimm_params[i][j].capacity;  				pinfo->dimm_params[i][j].base_address = addr;  				addr += (phys_addr_t)(cap >> dbw_cap_adj[i]); +				total_mem_per_ctlr += cap >> dbw_cap_adj[i];  			}  		} +		pinfo->common_timing_params[0].total_mem = total_mem_per_ctlr;  	} else {  		/*  		 * Simple linear assignment if memory diff --git a/include/asm-ppc/fsl_ddr_sdram.h b/include/asm-ppc/fsl_ddr_sdram.h index 8adde3424..c1ea7cd6b 100644 --- a/include/asm-ppc/fsl_ddr_sdram.h +++ b/include/asm-ppc/fsl_ddr_sdram.h @@ -36,6 +36,18 @@ typedef ddr2_spd_eeprom_t generic_spd_eeprom_t;  typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;  #endif +/* define bank(chip select) interleaving mode */ +#define FSL_DDR_CS0_CS1			0x40 +#define FSL_DDR_CS2_CS3			0x20 +#define FSL_DDR_CS0_CS1_AND_CS2_CS3	(FSL_DDR_CS0_CS1 | FSL_DDR_CS2_CS3) +#define FSL_DDR_CS0_CS1_CS2_CS3		(FSL_DDR_CS0_CS1_AND_CS2_CS3 | 0x04) + +/* define memory controller interleaving mode */ +#define FSL_DDR_CACHE_LINE_INTERLEAVING	0x0 +#define FSL_DDR_PAGE_INTERLEAVING	0x1 +#define FSL_DDR_BANK_INTERLEAVING	0x2 +#define FSL_DDR_SUPERBANK_INTERLEAVING	0x3 +  /* Record of register values computed */  typedef struct fsl_ddr_cfg_regs_s {  	struct { |