diff options
| -rw-r--r-- | arch/powerpc/cpu/mpc8xxx/ddr/options.c | 78 | ||||
| -rw-r--r-- | common/hwconfig.c | 86 | ||||
| -rw-r--r-- | include/hwconfig.h | 68 | 
3 files changed, 154 insertions, 78 deletions
| diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c index c641e8506..0e7097bab 100644 --- a/arch/powerpc/cpu/mpc8xxx/ddr/options.c +++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c @@ -13,6 +13,14 @@  #include "ddr.h" +/* + * Use our own stack based buffer before relocation to allow accessing longer + * hwconfig strings that might be in the environment before we've relocated. + * This is pretty fragile on both the use of stack and if the buffer is big + * enough. However we will get a warning from getenv_f for the later. + */ +#define HWCONFIG_BUFFER_SIZE	128 +  /* Board-specific functions defined in each board's ddr.c */  extern void fsl_ddr_board_options(memctl_options_t *popts,  		dimm_params_t *pdimm, @@ -24,6 +32,15 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  			unsigned int ctrl_num)  {  	unsigned int i; +	char buffer[HWCONFIG_BUFFER_SIZE]; +	char *buf = NULL; + +	/* +	 * Extract hwconfig from environment since we have not properly setup +	 * the environment but need it for ddr config params +	 */ +	if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0) +		buf = buffer;  	/* Chip select options. */ @@ -221,7 +238,7 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  	 * should be a subset of the requested configuration.  	 */  #if (CONFIG_NUM_DDR_CONTROLLERS > 1) -	if (hwconfig_sub("fsl_ddr", "ctlr_intlv")) { +	if (hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf)) {  		if (pdimm[0].n_ranks == 0) {  			printf("There is no rank on CS0 for controller %d. Because only"  				" rank on CS0 and ranks chip-select interleaved with CS0" @@ -234,19 +251,25 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  			 * test null first. if CONFIG_HWCONFIG is not defined  			 * hwconfig_arg_cmp returns non-zero  			 */ -			if (hwconfig_subarg_cmp("fsl_ddr", "ctlr_intlv", "null")) { +			if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", +						    "null", buf)) {  				popts->memctl_interleaving = 0;  				debug("memory controller interleaving disabled.\n"); -			} else if (hwconfig_subarg_cmp("fsl_ddr", "ctlr_intlv", "cacheline")) +			} else if (hwconfig_subarg_cmp_f("fsl_ddr", +							 "ctlr_intlv", +							 "cacheline", buf))  				popts->memctl_interleaving_mode =  					FSL_DDR_CACHE_LINE_INTERLEAVING; -			else if (hwconfig_subarg_cmp("fsl_ddr", "ctlr_intlv", "page")) +			else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", +						       "page", buf))  				popts->memctl_interleaving_mode =  					FSL_DDR_PAGE_INTERLEAVING; -			else if (hwconfig_subarg_cmp("fsl_ddr", "ctlr_intlv", "bank")) +			else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", +						       "bank", buf))  				popts->memctl_interleaving_mode =  					FSL_DDR_BANK_INTERLEAVING; -			else if (hwconfig_subarg_cmp("fsl_ddr", "ctlr_intlv", "superbank")) +			else if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv", +						       "superbank", buf))  				popts->memctl_interleaving_mode =  					FSL_DDR_SUPERBANK_INTERLEAVING;  			else { @@ -256,19 +279,24 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  		}  	}  #endif -	if ((hwconfig_sub("fsl_ddr", "bank_intlv")) && +	if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&  		(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")) +		 * hwconfig_subarg_cmp_f returns non-zero */ +		if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", +					    "null", buf))  			debug("bank interleaving disabled.\n"); -		else if (hwconfig_subarg_cmp("fsl_ddr", "bank_intlv", "cs0_cs1")) +		else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", +						 "cs0_cs1", buf))  			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1; -		else if (hwconfig_subarg_cmp("fsl_ddr", "bank_intlv", "cs2_cs3")) +		else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", +						 "cs2_cs3", buf))  			popts->ba_intlv_ctl = FSL_DDR_CS2_CS3; -		else if (hwconfig_subarg_cmp("fsl_ddr", "bank_intlv", "cs0_cs1_and_cs2_cs3")) +		else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", +						 "cs0_cs1_and_cs2_cs3", buf))  			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3; -		else if (hwconfig_subarg_cmp("fsl_ddr", "bank_intlv", "cs0_cs1_cs2_cs3")) +		else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv", +						 "cs0_cs1_cs2_cs3", buf))  			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3;  		else  			printf("hwconfig has unrecognized parameter for bank_intlv.\n"); @@ -342,10 +370,11 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,  		}  	} -	if (hwconfig_sub("fsl_ddr", "addr_hash")) { -		if (hwconfig_subarg_cmp("fsl_ddr", "addr_hash", "null")) +	if (hwconfig_sub_f("fsl_ddr", "addr_hash", buf)) { +		if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", "null", buf))  			popts->addr_hash = 0; -		else if (hwconfig_subarg_cmp("fsl_ddr", "addr_hash", "true")) +		else if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", +					       "true", buf))  			popts->addr_hash = 1;  	} @@ -393,11 +422,22 @@ int fsl_use_spd(void)  	int use_spd = 0;  #ifdef CONFIG_DDR_SPD +	char buffer[HWCONFIG_BUFFER_SIZE]; +	char *buf = NULL; + +	/* +	 * Extract hwconfig from environment since we have not properly setup +	 * the environment but need it for ddr config params +	 */ +	if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0) +		buf = buffer; +  	/* if hwconfig is not enabled, or "sdram" is not defined, use spd */ -	if (hwconfig_sub("fsl_ddr", "sdram")) { -		if (hwconfig_subarg_cmp("fsl_ddr", "sdram", "spd")) +	if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) { +		if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", "spd", buf))  			use_spd = 1; -		else if (hwconfig_subarg_cmp("fsl_ddr", "sdram", "fixed")) +		else if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", +					       "fixed", buf))  			use_spd = 0;  		else  			use_spd = 1; diff --git a/common/hwconfig.c b/common/hwconfig.c index 193863a97..515074808 100644 --- a/common/hwconfig.c +++ b/common/hwconfig.c @@ -2,6 +2,7 @@   * An inteface for configuring a hardware via u-boot environment.   *   * Copyright (c) 2009  MontaVista Software, Inc. + * Copyright 2011 Freescale Semiconductor, Inc.   *   * Author: Anton Vorontsov <avorontsov@ru.mvista.com>   * @@ -71,25 +72,19 @@ next:  const char cpu_hwconfig[] __attribute__((weak)) = "";  const char board_hwconfig[] __attribute__((weak)) = ""; -#define HWCONFIG_PRE_RELOC_BUF_SIZE	128 - -static const char *__hwconfig(const char *opt, size_t *arglen) +static const char *__hwconfig(const char *opt, size_t *arglen, +			      const char *env_hwconfig)  { -	const char *env_hwconfig = NULL, *ret; -	char buf[HWCONFIG_PRE_RELOC_BUF_SIZE]; +	const char *ret; -	if (gd->flags & GD_FLG_ENV_READY) { +	/* if we are passed a buffer use it, otherwise try the environment */ +	if (!env_hwconfig) { +		if (!(gd->flags & GD_FLG_ENV_READY)) { +			printf("WARNING: Calling __hwconfig without a buffer " +					"and before environment is ready\n");  +			return NULL;  +		}  		env_hwconfig = getenv("hwconfig"); -	} else { -		/* -		 * Use our own on stack based buffer before relocation to allow -		 * accessing longer hwconfig strings that might be in the -		 * environment before we've relocated.  This is pretty fragile -		 * on both the use of stack and if the buffer is big enough. -		 * However we will get a warning from getenv_f for the later. -		 */ -		if ((getenv_f("hwconfig", buf, sizeof(buf))) > 0) -			env_hwconfig = buf;  	}  	if (env_hwconfig) { @@ -109,8 +104,9 @@ static const char *__hwconfig(const char *opt, size_t *arglen)  }  /* - * hwconfig - query if a particular hwconfig option is specified + * hwconfig_f - query if a particular hwconfig option is specified   * @opt:	a string representing an option + * @buf:	if non-NULL use this buffer to parse, otherwise try env   *   * This call can be used to find out whether U-Boot should configure   * a particular hardware option. @@ -127,34 +123,36 @@ static const char *__hwconfig(const char *opt, size_t *arglen)   * that the board file only calls things that are actually used, so   * hwconfig() will always return true result.   */ -int hwconfig(const char *opt) +int hwconfig_f(const char *opt, char *buf)  { -	return !!__hwconfig(opt, NULL); +	return !!__hwconfig(opt, NULL, buf);  }  /* - * hwconfig_arg - get hwconfig option's argument + * hwconfig_arg_f - get hwconfig option's argument   * @opt:	a string representing an option   * @arglen:	a pointer to an allocated size_t variable + * @buf:	if non-NULL use this buffer to parse, otherwise try env   * - * Unlike hwconfig() function, this function returns a pointer to the + * Unlike hwconfig_f() function, this function returns a pointer to the   * start of the hwconfig arguments, if option is not found or it has   * no specified arguments, the function returns NULL pointer.   *   * If CONFIG_HWCONFIG is undefined, the function returns "", and   * arglen is set to 0.   */ -const char *hwconfig_arg(const char *opt, size_t *arglen) +const char *hwconfig_arg_f(const char *opt, size_t *arglen, char *buf)  { -	return __hwconfig(opt, arglen); +	return __hwconfig(opt, arglen, buf);  }  /* - * hwconfig_arg_cmp - compare hwconfig option's argument + * hwconfig_arg_cmp_f - compare hwconfig option's argument   * @opt:	a string representing an option   * @arg:	a string for comparing an option's argument + * @buf:	if non-NULL use this buffer to parse, otherwise try env   * - * This call is similar to hwconfig_arg, but instead of returning + * This call is similar to hwconfig_arg_f, but instead of returning   * hwconfig argument and its length, it is comparing it to @arg.   *   * Returns non-zero value if @arg matches, 0 otherwise. @@ -162,12 +160,12 @@ const char *hwconfig_arg(const char *opt, size_t *arglen)   * If CONFIG_HWCONFIG is undefined, the function returns a non-zero   * value, i.e. the argument matches.   */ -int hwconfig_arg_cmp(const char *opt, const char *arg) +int hwconfig_arg_cmp_f(const char *opt, const char *arg, char *buf)  {  	const char *argstr;  	size_t arglen; -	argstr = hwconfig_arg(opt, &arglen); +	argstr = hwconfig_arg_f(opt, &arglen, buf);  	if (!argstr || arglen != strlen(arg))  		return 0; @@ -175,63 +173,67 @@ int hwconfig_arg_cmp(const char *opt, const char *arg)  }  /* - * hwconfig_sub - query if a particular hwconfig sub-option is specified + * hwconfig_sub_f - query if a particular hwconfig sub-option is specified   * @opt:	a string representing an option   * @subopt:	a string representing a sub-option + * @buf:	if non-NULL use this buffer to parse, otherwise try env   * - * This call is similar to hwconfig(), except that it takes additional + * This call is similar to hwconfig_f(), except that it takes additional   * argument @subopt. In this example:   * 	"dr_usb:mode=peripheral"   * "dr_usb" is an option, "mode" is a sub-option, and "peripheral" is its   * argument.   */ -int hwconfig_sub(const char *opt, const char *subopt) +int hwconfig_sub_f(const char *opt, const char *subopt, char *buf)  {  	size_t arglen;  	const char *arg; -	arg = __hwconfig(opt, &arglen); +	arg = __hwconfig(opt, &arglen, buf);  	if (!arg)  		return 0;  	return !!hwconfig_parse(arg, arglen, subopt, ",;", '=', NULL);  }  /* - * hwconfig_subarg - get hwconfig sub-option's argument + * hwconfig_subarg_f - get hwconfig sub-option's argument   * @opt:	a string representing an option   * @subopt:	a string representing a sub-option   * @subarglen:	a pointer to an allocated size_t variable + * @buf:	if non-NULL use this buffer to parse, otherwise try env   * - * This call is similar to hwconfig_arg(), except that it takes an additional - * argument @subopt, and so works with sub-options. + * This call is similar to hwconfig_arg_f(), except that it takes an + * additional argument @subopt, and so works with sub-options.   */ -const char *hwconfig_subarg(const char *opt, const char *subopt, -			    size_t *subarglen) +const char *hwconfig_subarg_f(const char *opt, const char *subopt, +			      size_t *subarglen, char *buf)  {  	size_t arglen;  	const char *arg; -	arg = __hwconfig(opt, &arglen); +	arg = __hwconfig(opt, &arglen, buf);  	if (!arg)  		return NULL;  	return hwconfig_parse(arg, arglen, subopt, ",;", '=', subarglen);  }  /* - * hwconfig_arg_cmp - compare hwconfig sub-option's argument + * hwconfig_arg_cmp_f - compare hwconfig sub-option's argument   * @opt:	a string representing an option   * @subopt:	a string representing a sub-option   * @subarg:	a string for comparing an sub-option's argument + * @buf:	if non-NULL use this buffer to parse, otherwise try env   * - * This call is similar to hwconfig_arg_cmp, except that it takes an additional - * argument @subopt, and so works with sub-options. + * This call is similar to hwconfig_arg_cmp_f, except that it takes an + * additional argument @subopt, and so works with sub-options.   */ -int hwconfig_subarg_cmp(const char *opt, const char *subopt, const char *subarg) +int hwconfig_subarg_cmp_f(const char *opt, const char *subopt, +			  const char *subarg, char *buf)  {  	const char *argstr;  	size_t arglen; -	argstr = hwconfig_subarg(opt, subopt, &arglen); +	argstr = hwconfig_subarg_f(opt, subopt, &arglen, buf);  	if (!argstr || arglen != strlen(subarg))  		return 0; diff --git a/include/hwconfig.h b/include/hwconfig.h index d517f782f..a037ed885 100644 --- a/include/hwconfig.h +++ b/include/hwconfig.h @@ -2,6 +2,7 @@   * An inteface for configuring a hardware via u-boot environment.   *   * Copyright (c) 2009  MontaVista Software, Inc. + * Copyright 2011 Freescale Semiconductor, Inc.   *   * Author: Anton Vorontsov <avorontsov@ru.mvista.com>   * @@ -19,51 +20,84 @@  #ifdef CONFIG_HWCONFIG -extern int hwconfig(const char *opt); -extern const char *hwconfig_arg(const char *opt, size_t *arglen); -extern int hwconfig_arg_cmp(const char *opt, const char *arg); -extern int hwconfig_sub(const char *opt, const char *subopt); -extern const char *hwconfig_subarg(const char *opt, const char *subopt, -				   size_t *subarglen); -extern int hwconfig_subarg_cmp(const char *opt, const char *subopt, -			       const char *subarg); - +extern int hwconfig_f(const char *opt, char *buf); +extern const char *hwconfig_arg_f(const char *opt, size_t *arglen, char *buf); +extern int hwconfig_arg_cmp_f(const char *opt, const char *arg, char *buf); +extern int hwconfig_sub_f(const char *opt, const char *subopt, char *buf); +extern const char *hwconfig_subarg_f(const char *opt, const char *subopt, +				     size_t *subarglen, char *buf); +extern int hwconfig_subarg_cmp_f(const char *opt, const char *subopt, +				 const char *subarg, char *buf);  #else -static inline int hwconfig(const char *opt) +static inline int hwconfig_f(const char *opt, char *buf)  {  	return -ENOSYS;  } -static inline const char *hwconfig_arg(const char *opt, size_t *arglen) +static inline const char *hwconfig_arg_f(const char *opt, size_t *arglen, +					 char *buf)  {  	*arglen = 0;  	return "";  } -static inline int hwconfig_arg_cmp(const char *opt, const char *arg) +static inline int hwconfig_arg_cmp_f(const char *opt, const char *arg, +				     char *buf)  {  	return -ENOSYS;  } -static inline int hwconfig_sub(const char *opt, const char *subopt) +static inline int hwconfig_sub_f(const char *opt, const char *subopt, char *buf)  {  	return -ENOSYS;  } -static inline const char *hwconfig_subarg(const char *opt, const char *subopt, -					  size_t *subarglen) +static inline const char *hwconfig_subarg_f(const char *opt, const char *subopt, +					    size_t *subarglen, char *buf)  {  	*subarglen = 0;  	return "";  } -static inline int hwconfig_subarg_cmp(const char *opt, const char *subopt, -				      const char *subarg) +static inline int hwconfig_subarg_cmp_f(const char *opt, const char *subopt, +					const char *subarg, char *buf)  {  	return -ENOSYS;  }  #endif /* CONFIG_HWCONFIG */ +static inline int hwconfig(const char *opt) +{ +	return hwconfig_f(opt, NULL); +} + +static inline const char *hwconfig_arg(const char *opt, size_t *arglen) +{ +	return hwconfig_arg_f(opt, arglen, NULL); +} + +static inline int hwconfig_arg_cmp(const char *opt, const char *arg) +{ +	return hwconfig_arg_cmp_f(opt, arg, NULL); +} + +static inline int hwconfig_sub(const char *opt, const char *subopt) +{ +	return hwconfig_sub_f(opt, subopt, NULL); +} + +static inline const char *hwconfig_subarg(const char *opt, const char *subopt, +					  size_t *subarglen) +{ +	return hwconfig_subarg_f(opt, subopt, subarglen, NULL); +} + +static inline int hwconfig_subarg_cmp(const char *opt, const char *subopt, +				      const char *subarg) +{ +	return hwconfig_subarg_cmp_f(opt, subopt, subarg, NULL); +} +  #endif /* _HWCONFIG_H */ |