aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/ibmpowernv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/ibmpowernv.c')
-rw-r--r--drivers/hwmon/ibmpowernv.c96
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++;
}
}