diff options
Diffstat (limited to 'arch/powerpc/cpu/mpc8xxx/ddr/options.c')
| -rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/options.c | 107 | 
1 files changed, 89 insertions, 18 deletions
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c index 11281b7de..ebbdb69c0 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/options.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c @@ -212,10 +212,9 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  	 * Please refer to doc/README.fsl-ddr for the detail.  	 *  	 * If memory controller interleaving is enabled, then the data -	 * bus widths must be programmed identically for the 2 memory -	 * controllers. +	 * bus widths must be programmed identically for all memory controllers.  	 * -	 * XXX: Attempt to set both controllers to the same chip select +	 * XXX: Attempt to set all controllers to the same chip select  	 * interleaving mode. It will do a best effort to get the  	 * requested ranks interleaved together such that the result  	 * should be a subset of the requested configuration. @@ -223,15 +222,17 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  #if (CONFIG_NUM_DDR_CONTROLLERS > 1)  	if (hwconfig_sub("fsl_ddr", "ctlr_intlv")) {  		if (pdimm[0].n_ranks == 0) { -			printf("There is no rank on CS0. Because only rank on " -				"CS0 and ranks chip-select interleaved with CS0" +			printf("There is no rank on CS0 for controller %d. Because only" +				" rank on CS0 and ranks chip-select interleaved with CS0"  				" are controller interleaved, force non memory " -				"controller interleaving\n"); +				"controller interleaving\n", ctrl_num);  			popts->memctl_interleaving = 0;  		} else {  			popts->memctl_interleaving = 1; -			/* test null first. if CONFIG_HWCONFIG is not defined -			 * hwconfig_arg_cmp returns non-zero */ +			/* +			 * test null first. if CONFIG_HWCONFIG is not defined +			 * hwconfig_arg_cmp returns non-zero +			 */  			if (hwconfig_subarg_cmp("fsl_ddr", "ctlr_intlv", "null")) {  				popts->memctl_interleaving = 0;  				debug("memory controller interleaving disabled.\n"); @@ -254,13 +255,12 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  		}  	}  #endif -  	if ((hwconfig_sub("fsl_ddr", "bank_intlv")) &&  		(CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {  		/* test null first. if CONFIG_HWCONFIG is not defined,  		 * hwconfig_arg_cmp returns non-zero */  		if (hwconfig_subarg_cmp("fsl_ddr", "bank_intlv", "null")) -			printf("bank interleaving disabled.\n"); +			debug("bank interleaving disabled.\n");  		else if (hwconfig_subarg_cmp("fsl_ddr", "bank_intlv", "cs0_cs1"))  			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1;  		else if (hwconfig_subarg_cmp("fsl_ddr", "bank_intlv", "cs2_cs3")) @@ -270,30 +270,70 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  		else if (hwconfig_subarg_cmp("fsl_ddr", "bank_intlv", "cs0_cs1_cs2_cs3"))  			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3;  		else -			printf("hwconfig has unrecognized parameter for ba_intlv_ctl.\n"); - +			printf("hwconfig has unrecognized parameter for bank_intlv.\n");  		switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {  		case FSL_DDR_CS0_CS1_CS2_CS3: +#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) +			if (pdimm[0].n_ranks != 4) { +				popts->ba_intlv_ctl = 0; +				printf("Not enough bank(chip-select) for " +					"CS0+CS1+CS2+CS3 on controller %d, " +					"force non-interleaving!\n", ctrl_num); +			} +#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) +			if ((pdimm[0].n_ranks != 2) && (pdimm[1].n_ranks != 2)) { +				popts->ba_intlv_ctl = 0; +				printf("Not enough bank(chip-select) for " +					"CS0+CS1+CS2+CS3 on controller %d, " +					"force non-interleaving!\n", ctrl_num); +			} +			if (pdimm[0].capacity != pdimm[1].capacity) { +				popts->ba_intlv_ctl = 0; +				printf("Not identical DIMM size for " +					"CS0+CS1+CS2+CS3 on controller %d, " +					"force non-interleaving!\n", ctrl_num); +			} +#endif +			break;  		case FSL_DDR_CS0_CS1:  			if (pdimm[0].n_ranks != 2) {  				popts->ba_intlv_ctl = 0;  				printf("Not enough bank(chip-select) for " -					"CS0+CS1, force non-interleaving!\n"); +					"CS0+CS1 on controller %d, " +					"force non-interleaving!\n", ctrl_num);  			}  			break;  		case FSL_DDR_CS2_CS3: -			if (pdimm[1].n_ranks !=2){ +#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) +			if (pdimm[0].n_ranks != 4) { +				popts->ba_intlv_ctl = 0; +				printf("Not enough bank(chip-select) for CS2+CS3 " +					"on controller %d, force non-interleaving!\n", ctrl_num); +			} +#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2) +			if (pdimm[1].n_ranks != 2) {  				popts->ba_intlv_ctl = 0; -				printf("Not enough bank(CS) for CS2+CS3, " -					"force non-interleaving!\n"); +				printf("Not enough bank(chip-select) for CS2+CS3 " +					"on controller %d, force non-interleaving!\n", ctrl_num);  			} +#endif  			break;  		case FSL_DDR_CS0_CS1_AND_CS2_CS3: +#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) +			if (pdimm[0].n_ranks != 4) { +				popts->ba_intlv_ctl = 0; +				printf("Not enough bank(CS) for CS0+CS1 and " +					"CS2+CS3 on controller %d, " +					"force non-interleaving!\n", ctrl_num); +			} +#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)  			if ((pdimm[0].n_ranks != 2)||(pdimm[1].n_ranks != 2)) {  				popts->ba_intlv_ctl = 0; -				printf("Not enough bank(CS) for CS0+CS1 or " -					"CS2+CS3, force non-interleaving!\n"); +				printf("Not enough bank(CS) for CS0+CS1 and " +					"CS2+CS3 on controller %d, " +					"force non-interleaving!\n", ctrl_num);  			} +#endif  			break;  		default:  			popts->ba_intlv_ctl = 0; @@ -305,3 +345,34 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  	return 0;  } + +void check_interleaving_options(fsl_ddr_info_t *pinfo) +{ +	int i, j, check_n_ranks, intlv_fixed = 0; +	unsigned long long check_rank_density; +	/* +	 * Check if all controllers are configured for memory +	 * controller interleaving. Identical dimms are recommended. At least +	 * the size should be checked. +	 */ +	j = 0; +	check_n_ranks = pinfo->dimm_params[0][0].n_ranks; +	check_rank_density = pinfo->dimm_params[0][0].rank_density; +	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { +		if ((pinfo->memctl_opts[i].memctl_interleaving) && \ +		    (check_rank_density == pinfo->dimm_params[i][0].rank_density) && \ +		    (check_n_ranks == pinfo->dimm_params[i][0].n_ranks)) { +			j++; +		} +	} +	if (j != CONFIG_NUM_DDR_CONTROLLERS) { +		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) +			if (pinfo->memctl_opts[i].memctl_interleaving) { +				pinfo->memctl_opts[i].memctl_interleaving = 0; +				intlv_fixed = 1; +			} +		if (intlv_fixed) +			printf("Not all DIMMs are identical in size. " +				"Memory controller interleaving disabled.\n"); +	} +}  |