2016-07-20 13:44:56 +00:00
|
|
|
From: Wei Ni <wni@nvidia.com>
|
|
|
|
Subject: hwmon: lm90: expose to thermal fw via DT nodes
|
|
|
|
|
|
|
|
This patch adds to lm90 temperature sensor the possibility
|
|
|
|
to expose itself as thermal zone device, registered on the
|
|
|
|
thermal framework.
|
|
|
|
|
|
|
|
The thermal zone is built only if a device tree node
|
|
|
|
describing a thermal zone for this sensor is present
|
|
|
|
inside the lm90 DT node. Otherwise, the driver behavior
|
|
|
|
will be the same.
|
|
|
|
|
|
|
|
Discussed in:
|
|
|
|
http://www.gossamer-threads.com/lists/linux/kernel/1992853
|
|
|
|
|
|
|
|
BUG=chrome-os-partner:30834
|
|
|
|
TEST=Verified. Build and boot up system.
|
|
|
|
|
|
|
|
Signed-off-by: Wei Ni <wni@nvidia.com>
|
|
|
|
Reviewed-on: https://chromium-review.googlesource.com/181447
|
|
|
|
Reviewed-by: Dylan Reid <dgreid@chromium.org>
|
|
|
|
Tested-by: Dylan Reid <dgreid@chromium.org>
|
|
|
|
Commit-Queue: Dylan Reid <dgreid@chromium.org>
|
|
|
|
Change-Id: Id356b94d7e8f4b49ec15e46b17a1fa2ff0cbf8cf
|
|
|
|
Reviewed-on: https://chromium-review.googlesource.com/212414
|
|
|
|
Tested-by: Wei Ni <wni.nvidia@gmail.com>
|
|
|
|
Reviewed-by: Olof Johansson <olofj@chromium.org>
|
|
|
|
Commit-Queue: Olof Johansson <olofj@chromium.org>
|
|
|
|
---
|
|
|
|
--- a/drivers/hwmon/lm90.c
|
|
|
|
+++ b/drivers/hwmon/lm90.c
|
|
|
|
@@ -96,6 +96,8 @@
|
|
|
|
#include <linux/sysfs.h>
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/regulator/consumer.h>
|
|
|
|
+#include <linux/of.h>
|
|
|
|
+#include <linux/thermal.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Addresses to scan
|
2016-08-22 17:05:45 +00:00
|
|
|
@@ -119,6 +121,13 @@ static const unsigned short normal_i2c[]
|
2016-07-20 13:44:56 +00:00
|
|
|
enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
|
|
|
|
max6646, w83l771, max6696, sa56004, g781, tmp451 };
|
2016-08-22 17:05:45 +00:00
|
|
|
|
2016-07-20 13:44:56 +00:00
|
|
|
+enum sensor_id {
|
|
|
|
+ LOCAL = 0,
|
|
|
|
+ REMOTE,
|
|
|
|
+ REMOTE2,
|
|
|
|
+ SENSOR_ID_END,
|
|
|
|
+};
|
2016-08-22 17:05:45 +00:00
|
|
|
+
|
2016-07-20 13:44:56 +00:00
|
|
|
/*
|
|
|
|
* The LM90 registers
|
2016-08-22 17:05:45 +00:00
|
|
|
*/
|
|
|
|
@@ -368,6 +377,7 @@ struct lm90_data {
|
2016-07-20 13:44:56 +00:00
|
|
|
struct i2c_client *client;
|
|
|
|
struct device *hwmon_dev;
|
|
|
|
const struct attribute_group *groups[6];
|
|
|
|
+ struct thermal_zone_device *tz[SENSOR_ID_END];
|
|
|
|
struct mutex update_lock;
|
|
|
|
struct regulator *regulator;
|
|
|
|
char valid; /* zero until following fields are valid */
|
2016-08-22 17:05:45 +00:00
|
|
|
@@ -880,6 +890,24 @@ static ssize_t show_temp11(struct device
|
2016-07-20 13:44:56 +00:00
|
|
|
return sprintf(buf, "%d\n", read_temp11(dev, attr->index));
|
2016-08-22 17:05:45 +00:00
|
|
|
}
|
|
|
|
|
2016-07-20 13:44:56 +00:00
|
|
|
+static int lm90_read_local_temp(void *dev, int *temp)
|
|
|
|
+{
|
|
|
|
+ *temp = read_temp11(dev, 4);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int lm90_read_remote_temp(void *dev, int *temp)
|
|
|
|
+{
|
|
|
|
+ *temp = read_temp11(dev, 0);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int lm90_read_remote2_temp(void *dev, int *temp)
|
|
|
|
+{
|
|
|
|
+ *temp = read_temp11(dev, 5);
|
|
|
|
+ return 0;
|
2016-08-22 17:05:45 +00:00
|
|
|
+}
|
|
|
|
+
|
2016-07-20 13:44:56 +00:00
|
|
|
static int write_temp11(struct device *dev, int nr, int index, long val)
|
2016-08-22 17:05:45 +00:00
|
|
|
{
|
|
|
|
struct {
|
|
|
|
@@ -1210,6 +1238,18 @@ static const struct attribute_group lm90
|
2016-07-20 13:44:56 +00:00
|
|
|
.attrs = lm90_temp3_attributes,
|
|
|
|
};
|
|
|
|
|
|
|
|
+static const struct thermal_zone_of_device_ops local_temp_sensor = {
|
|
|
|
+ .get_temp = lm90_read_local_temp,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static const struct thermal_zone_of_device_ops remote_temp_sensor = {
|
|
|
|
+ .get_temp = lm90_read_remote_temp,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static const struct thermal_zone_of_device_ops remote2_temp_sensor = {
|
|
|
|
+ .get_temp = lm90_read_remote2_temp,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
/* pec used for ADM1032 only */
|
|
|
|
static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
|
|
|
|
char *buf)
|
2016-08-22 17:05:45 +00:00
|
|
|
@@ -1659,6 +1699,30 @@ static int lm90_probe(struct i2c_client
|
2016-07-20 13:44:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+ data->tz[LOCAL] = thermal_zone_of_sensor_register(&client->dev,
|
|
|
|
+ LOCAL,
|
|
|
|
+ &client->dev,
|
|
|
|
+ &local_temp_sensor);
|
|
|
|
+ if (IS_ERR(data->tz[LOCAL]))
|
|
|
|
+ data->tz[LOCAL] = NULL;
|
|
|
|
+
|
|
|
|
+ data->tz[REMOTE] = thermal_zone_of_sensor_register(&client->dev,
|
|
|
|
+ REMOTE,
|
|
|
|
+ &client->dev,
|
|
|
|
+ &remote_temp_sensor);
|
|
|
|
+ if (IS_ERR(data->tz[REMOTE]))
|
|
|
|
+ data->tz[REMOTE] = NULL;
|
|
|
|
+
|
|
|
|
+ if (data->flags & LM90_HAVE_TEMP3) {
|
|
|
|
+ data->tz[REMOTE2] = thermal_zone_of_sensor_register(
|
|
|
|
+ &client->dev,
|
|
|
|
+ REMOTE2,
|
|
|
|
+ &client->dev,
|
|
|
|
+ &remote2_temp_sensor);
|
|
|
|
+ if (IS_ERR(data->tz[REMOTE2]))
|
|
|
|
+ data->tz[REMOTE2] = NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
exit_unregister:
|
2016-08-22 17:05:45 +00:00
|
|
|
@@ -1674,8 +1738,11 @@ exit_restore:
|
2016-07-20 13:44:56 +00:00
|
|
|
|
|
|
|
static int lm90_remove(struct i2c_client *client)
|
|
|
|
{
|
|
|
|
+ int i;
|
|
|
|
struct lm90_data *data = i2c_get_clientdata(client);
|
|
|
|
|
|
|
|
+ for (i = 0; i < SENSOR_ID_END; i++)
|
|
|
|
+ thermal_zone_of_sensor_unregister(&client->dev, data->tz[i]);
|
|
|
|
hwmon_device_unregister(data->hwmon_dev);
|
|
|
|
device_remove_file(&client->dev, &dev_attr_pec);
|
|
|
|
lm90_restore_conf(client, data);
|