diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/firmware.c')
| -rw-r--r-- | arch/powerpc/platforms/pseries/firmware.c | 71 | 
1 files changed, 59 insertions, 12 deletions
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 0a14d8cd314..8c80588abac 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -28,13 +28,18 @@  #include "pseries.h" -typedef struct { +struct hypertas_fw_feature {      unsigned long val;      char * name; -} firmware_feature_t; +}; -static __initdata firmware_feature_t -firmware_features_table[FIRMWARE_MAX_FEATURES] = { +/* + * The names in this table match names in rtas/ibm,hypertas-functions.  If the + * entry ends in a '*', only upto the '*' is matched.  Otherwise the entire + * string must match. + */ +static __initdata struct hypertas_fw_feature +hypertas_fw_features_table[] = {  	{FW_FEATURE_PFT,		"hcall-pft"},  	{FW_FEATURE_TCE,		"hcall-tce"},  	{FW_FEATURE_SPRG0,		"hcall-sprg0"}, @@ -55,32 +60,74 @@ firmware_features_table[FIRMWARE_MAX_FEATURES] = {  	{FW_FEATURE_XDABR,		"hcall-xdabr"},  	{FW_FEATURE_MULTITCE,		"hcall-multi-tce"},  	{FW_FEATURE_SPLPAR,		"hcall-splpar"}, +	{FW_FEATURE_VPHN,		"hcall-vphn"}, +	{FW_FEATURE_SET_MODE,		"hcall-set-mode"}, +	{FW_FEATURE_BEST_ENERGY,	"hcall-best-energy-1*"},  };  /* Build up the firmware features bitmask using the contents of   * device-tree/ibm,hypertas-functions.  Ultimately this functionality may   * be moved into prom.c prom_init().   */ -void __init fw_feature_init(const char *hypertas, unsigned long len) +void __init fw_hypertas_feature_init(const char *hypertas, unsigned long len)  {  	const char *s;  	int i; -	pr_debug(" -> fw_feature_init()\n"); +	pr_debug(" -> fw_hypertas_feature_init()\n");  	for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { -		for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { -			/* check value against table of strings */ -			if (!firmware_features_table[i].name || -			    strcmp(firmware_features_table[i].name, s)) +		for (i = 0; i < ARRAY_SIZE(hypertas_fw_features_table); i++) { +			const char *name = hypertas_fw_features_table[i].name; +			size_t size; + +			/* +			 * If there is a '*' at the end of name, only check +			 * upto there +			 */ +			size = strlen(name); +			if (size && name[size - 1] == '*') { +				if (strncmp(name, s, size - 1)) +					continue; +			} else if (strcmp(name, s))  				continue;  			/* we have a match */  			powerpc_firmware_features |= -				firmware_features_table[i].val; +				hypertas_fw_features_table[i].val;  			break;  		}  	} -	pr_debug(" <- fw_feature_init()\n"); +	pr_debug(" <- fw_hypertas_feature_init()\n"); +} + +struct vec5_fw_feature { +	unsigned long	val; +	unsigned int	feature; +}; + +static __initdata struct vec5_fw_feature +vec5_fw_features_table[] = { +	{FW_FEATURE_TYPE1_AFFINITY,	OV5_TYPE1_AFFINITY}, +	{FW_FEATURE_PRRN,		OV5_PRRN}, +}; + +void __init fw_vec5_feature_init(const char *vec5, unsigned long len) +{ +	unsigned int index, feat; +	int i; + +	pr_debug(" -> fw_vec5_feature_init()\n"); + +	for (i = 0; i < ARRAY_SIZE(vec5_fw_features_table); i++) { +		index = OV5_INDX(vec5_fw_features_table[i].feature); +		feat = OV5_FEAT(vec5_fw_features_table[i].feature); + +		if (vec5[index] & feat) +			powerpc_firmware_features |= +				vec5_fw_features_table[i].val; +	} + +	pr_debug(" <- fw_vec5_feature_init()\n");  }  | 
