diff options
Diffstat (limited to 'drivers/hwmon/ibmpowernv.c')
| -rw-r--r-- | drivers/hwmon/ibmpowernv.c | 96 | 
1 files changed, 81 insertions, 15 deletions
| diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c index 6d2e6605751c..5ccdd0b52650 100644 --- a/drivers/hwmon/ibmpowernv.c +++ b/drivers/hwmon/ibmpowernv.c @@ -50,22 +50,34 @@ enum sensors {  	TEMP,  	POWER_SUPPLY,  	POWER_INPUT, +	CURRENT,  	MAX_SENSOR_TYPE,  };  #define INVALID_INDEX (-1U) +/* + * 'compatible' string properties for sensor types as defined in old + * PowerNV firmware (skiboot). These are ordered as 'enum sensors'. + */ +static const char * const legacy_compatibles[] = { +	"ibm,opal-sensor-cooling-fan", +	"ibm,opal-sensor-amb-temp", +	"ibm,opal-sensor-power-supply", +	"ibm,opal-sensor-power" +}; +  static struct sensor_group { -	const char *name; -	const char *compatible; +	const char *name; /* matches property 'sensor-type' */  	struct attribute_group group;  	u32 attr_count;  	u32 hwmon_index;  } sensor_groups[] = { -	{"fan", "ibm,opal-sensor-cooling-fan"}, -	{"temp", "ibm,opal-sensor-amb-temp"}, -	{"in", "ibm,opal-sensor-power-supply"}, -	{"power", "ibm,opal-sensor-power"} +	{ "fan"   }, +	{ "temp"  }, +	{ "in"    }, +	{ "power" }, +	{ "curr"  },  };  struct sensor_data { @@ -239,8 +251,8 @@ static int get_sensor_type(struct device_node *np)  	enum sensors type;  	const char *str; -	for (type = 0; type < MAX_SENSOR_TYPE; type++) { -		if (of_device_is_compatible(np, sensor_groups[type].compatible)) +	for (type = 0; type < ARRAY_SIZE(legacy_compatibles); type++) { +		if (of_device_is_compatible(np, legacy_compatibles[type]))  			return type;  	} @@ -298,10 +310,14 @@ static int populate_attr_groups(struct platform_device *pdev)  		sensor_groups[type].attr_count++;  		/* -		 * add a new attribute for labels +		 * add attributes for labels, min and max  		 */  		if (!of_property_read_string(np, "label", &label))  			sensor_groups[type].attr_count++; +		if (of_find_property(np, "sensor-data-min", NULL)) +			sensor_groups[type].attr_count++; +		if (of_find_property(np, "sensor-data-max", NULL)) +			sensor_groups[type].attr_count++;  	}  	of_node_put(opal); @@ -337,6 +353,41 @@ static void create_hwmon_attr(struct sensor_data *sdata, const char *attr_name,  	sdata->dev_attr.show = show;  } +static void populate_sensor(struct sensor_data *sdata, int od, int hd, int sid, +			    const char *attr_name, enum sensors type, +			    const struct attribute_group *pgroup, +			    ssize_t (*show)(struct device *dev, +					    struct device_attribute *attr, +					    char *buf)) +{ +	sdata->id = sid; +	sdata->type = type; +	sdata->opal_index = od; +	sdata->hwmon_index = hd; +	create_hwmon_attr(sdata, attr_name, show); +	pgroup->attrs[sensor_groups[type].attr_count++] = &sdata->dev_attr.attr; +} + +static char *get_max_attr(enum sensors type) +{ +	switch (type) { +	case POWER_INPUT: +		return "input_highest"; +	default: +		return "highest"; +	} +} + +static char *get_min_attr(enum sensors type) +{ +	switch (type) { +	case POWER_INPUT: +		return "input_lowest"; +	default: +		return "lowest"; +	} +} +  /*   * Iterate through the device tree for each child of 'sensors' node, create   * a sysfs attribute file, the file is named by translating the DT node name @@ -417,16 +468,31 @@ static int create_device_attrs(struct platform_device *pdev)  			 * attribute. They are related to the same  			 * sensor.  			 */ -			sdata[count].type = type; -			sdata[count].opal_index = sdata[count - 1].opal_index; -			sdata[count].hwmon_index = sdata[count - 1].hwmon_index;  			make_sensor_label(np, &sdata[count], label); +			populate_sensor(&sdata[count], opal_index, +					sdata[count - 1].hwmon_index, +					sensor_id, "label", type, pgroups[type], +					show_label); +			count++; +		} -			create_hwmon_attr(&sdata[count], "label", show_label); +		if (!of_property_read_u32(np, "sensor-data-max", &sensor_id)) { +			attr_name = get_max_attr(type); +			populate_sensor(&sdata[count], opal_index, +					sdata[count - 1].hwmon_index, +					sensor_id, attr_name, type, +					pgroups[type], show_sensor); +			count++; +		} -			pgroups[type]->attrs[sensor_groups[type].attr_count++] = -				&sdata[count++].dev_attr.attr; +		if (!of_property_read_u32(np, "sensor-data-min", &sensor_id)) { +			attr_name = get_min_attr(type); +			populate_sensor(&sdata[count], opal_index, +					sdata[count - 1].hwmon_index, +					sensor_id, attr_name, type, +					pgroups[type], show_sensor); +			count++;  		}  	} |