diff options
| -rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c | 62 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c | 16 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/options.c | 12 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/util.c | 12 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/fsl_ddr_sdram.h | 2 | 
5 files changed, 87 insertions, 17 deletions
| diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c index c28f9cd20..5928eb880 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -229,6 +229,26 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)  /* -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)   * @@ -236,7 +256,8 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)   * 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 */ @@ -266,7 +287,18 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,  	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; @@ -1483,7 +1515,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,  				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 @@ -1497,7 +1529,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,  			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)) { @@ -1554,17 +1586,19 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,  		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 { +			debug("FSLDDR: setting bnds to 0 for inactive CS\n"); +			ddr->cs[i].bnds = 0; +		}  		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);  	}  	/* @@ -1577,7 +1611,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,  	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); diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c index 03a784cd4..6a1f4e4e3 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c @@ -76,7 +76,7 @@ compute_cas_latency_ddr3(const dimm_params_t *dimm_params,  unsigned int  compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,  				      common_timing_params_t *outpdimm, -				      unsigned int number_of_dimms) +				      const unsigned int number_of_dimms)  {  	unsigned int i, j; @@ -126,13 +126,20 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,  			temp1++;  			continue;  		} + +		/* +		 * check if quad-rank DIMM is plugged if +		 * CONFIG_CHIP_SELECT_QUAD_CAPABLE is not defined +		 * Only the board with proper design is capable +		 */ +#ifndef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE  		if (dimm_params[i].n_ranks == 4 && \  		  CONFIG_CHIP_SELECTS_PER_CTRL/CONFIG_DIMM_SLOTS_PER_CTLR < 4) {  			printf("Found Quad-rank DIMM, not able to support.");  			temp1++;  			continue;  		} - +#endif  		/*  		 * Find minimum tCKmax_ps to find fastest slow speed,  		 * i.e., this is the slowest the whole system can go. @@ -236,11 +243,14 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,  	if (outpdimm->all_DIMMs_registered)  		for (j = 0; j < 16; j++) {  			outpdimm->rcw[j] = dimm_params[0].rcw[j]; -			for (i = 1; i < number_of_dimms; i++) +			for (i = 1; i < number_of_dimms; i++) { +				if (!dimm_params[i].n_ranks) +					continue;  				if (dimm_params[i].rcw[j] != dimm_params[0].rcw[j]) {  					temp1 = 1;  					break;  				} +			}  		}  	if (temp1 != 0) diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c index 13e482527..1188df917 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/options.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c @@ -510,6 +510,14 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  		}  	} else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {  		switch (pdimm[0].n_ranks) { +#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE +		case 4: +			pdodt = single_Q; +			if (pdimm[1].n_ranks) +				printf("Error: Quad- and Dual-rank DIMMs " +					"cannot be used together\n"); +			break; +#endif  		case 2:  			switch (pdimm[1].n_ranks) {  			case 2: @@ -912,6 +920,10 @@ done:  					"interleaving disabled!\n", ctrl_num);  			}  #elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) +#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE +			if (pdimm[0].n_ranks == 4) +				break; +#endif  			if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) {  				popts->ba_intlv_ctl = 0;  				printf("Not enough bank(chip-select) for " diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/util.c b/arch/powerpc/cpu/mpc8xxx/ddr/util.c index 664ad0929..b439cc975 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/util.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/util.c @@ -140,6 +140,18 @@ void board_add_ram_info(int use_default)  	uint32_t sdram_cfg = in_be32(&ddr->sdram_cfg);  	int cas_lat; +#if CONFIG_NUM_DDR_CONTROLLERS >= 2 +	if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { +		ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR; +		sdram_cfg = in_be32(&ddr->sdram_cfg); +	} +#endif +#if CONFIG_NUM_DDR_CONTROLLERS >= 3 +	if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { +		ddr = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR; +		sdram_cfg = in_be32(&ddr->sdram_cfg); +	} +#endif  	puts(" (DDR");  	switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>  		SDRAM_CFG_SDRAM_TYPE_SHIFT) { diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h index 9cf9bd4a2..bb79335b1 100644 --- a/arch/powerpc/include/asm/fsl_ddr_sdram.h +++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h @@ -84,6 +84,8 @@ typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;  #define FSL_DDR_4WAY_4KB_INTERLEAVING	0x1C  #define FSL_DDR_4WAY_8KB_INTERLEAVING	0x1D +#define SDRAM_CS_CONFIG_EN		0x80000000 +  /* DDR_SDRAM_CFG - DDR SDRAM Control Configuration   */  #define SDRAM_CFG_MEM_EN		0x80000000 |