diff options
Diffstat (limited to 'cpu/mpc8xxx/ddr/lc_common_dimm_params.c')
| -rw-r--r-- | cpu/mpc8xxx/ddr/lc_common_dimm_params.c | 74 | 
1 files changed, 69 insertions, 5 deletions
| diff --git a/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/cpu/mpc8xxx/ddr/lc_common_dimm_params.c index fbeb236d9..e888e3ea5 100644 --- a/cpu/mpc8xxx/ddr/lc_common_dimm_params.c +++ b/cpu/mpc8xxx/ddr/lc_common_dimm_params.c @@ -11,6 +11,59 @@  #include "ddr.h" +unsigned int +compute_cas_latency_ddr3(const dimm_params_t *dimm_params, +			 common_timing_params_t *outpdimm, +			 unsigned int number_of_dimms) +{ +	unsigned int i; +	unsigned int tAAmin_ps = 0; +	unsigned int tCKmin_X_ps = 0; +	unsigned int common_caslat; +	unsigned int caslat_actual; +	unsigned int retry = 16; +	unsigned int tmp; +	const unsigned int mclk_ps = get_memory_clk_period_ps(); + +	/* compute the common CAS latency supported between slots */ +	tmp = dimm_params[0].caslat_X; +	for (i = 1; i < number_of_dimms; i++) +		 tmp &= dimm_params[i].caslat_X; +	common_caslat = tmp; + +	/* compute the max tAAmin tCKmin between slots */ +	for (i = 0; i < number_of_dimms; i++) { +		tAAmin_ps = max(tAAmin_ps, dimm_params[i].tAA_ps); +		tCKmin_X_ps = max(tCKmin_X_ps, dimm_params[i].tCKmin_X_ps); +	} +	/* validate if the memory clk is in the range of dimms */ +	if (mclk_ps < tCKmin_X_ps) { +		printf("The DIMM max tCKmin is %d ps," +			"doesn't support the MCLK cycle %d ps\n", +			tCKmin_X_ps, mclk_ps); +		return 1; +	} +	/* determine the acutal cas latency */ +	caslat_actual = (tAAmin_ps + mclk_ps - 1) / mclk_ps; +	/* check if the dimms support the CAS latency */ +	while (!(common_caslat & (1 << caslat_actual)) && retry > 0) { +		caslat_actual++; +		retry--; +	} +	/* once the caculation of caslat_actual is completed +	 * we must verify that this CAS latency value does not +	 * exceed tAAmax, which is 20 ns for all DDR3 speed grades +	 */ +	if (caslat_actual * mclk_ps > 20000) { +		printf("The choosen cas latency %d is too large\n", +			caslat_actual); +		return 1; +	} +	outpdimm->lowest_common_SPD_caslat = caslat_actual; + +	return 0; +} +  /*   * compute_lowest_common_dimm_parameters()   * @@ -46,12 +99,14 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,  	unsigned int tQHS_ps = 0;  	unsigned int temp1, temp2; -	unsigned int lowest_good_caslat;  	unsigned int additive_latency = 0; +#if !defined(CONFIG_FSL_DDR3)  	const unsigned int mclk_ps = get_memory_clk_period_ps(); +	unsigned int lowest_good_caslat;  	unsigned int not_ok;  	debug("using mclk_ps = %u\n", mclk_ps); +#endif  	temp1 = 0;  	for (i = 0; i < number_of_dimms; i++) { @@ -164,6 +219,10 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,  				"DIMMs detected!\n");  	} +#if defined(CONFIG_FSL_DDR3) +	if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms)) +		return 1; +#else  	/*  	 * Compute a CAS latency suitable for all DIMMs  	 * @@ -281,6 +340,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,  	}  	outpdimm->highest_common_derated_caslat = temp1;  	debug("highest common dereated CAS latency = %u\n", temp1); +#endif /* #if defined(CONFIG_FSL_DDR3) */  	/* Determine if all DIMMs ECC capable. */  	temp1 = 1; @@ -297,14 +357,14 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,  	}  	outpdimm->all_DIMMs_ECC_capable = temp1; - +#ifndef CONFIG_FSL_DDR3  	/* FIXME: move to somewhere else to validate. */  	if (mclk_ps > tCKmax_max_ps) {  		printf("Warning: some of the installed DIMMs "  				"can not operate this slowly.\n");  		return 1;  	} - +#endif  	/*  	 * Compute additive latency.  	 * @@ -314,7 +374,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,  	 *	which comes from Trcd, and also note that:  	 *	    add_lat + caslat must be >= 4  	 * -	 * For DDR3, FIXME additive latency determination +	 * For DDR3, we use the AL=0  	 *  	 * When to use additive latency for DDR2:  	 * @@ -371,7 +431,11 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,  	}  #elif defined(CONFIG_FSL_DDR3) -error "FIXME determine additive latency for DDR3" +	/* +	 * The system will not use the global auto-precharge mode. +	 * However, it uses the page mode, so we set AL=0 +	 */ +	additive_latency = 0;  #endif  	/* |