aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/apm821xx/patches-4.4/912-hwmon-lm90-expose-to-thermal-fw-via-DT.patch
blob: 9eb9ceeaacdd4f06bc42be235b71a7147c145c56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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
@@ -119,6 +121,13 @@ static const unsigned short normal_i2c[]
 enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
 	max6646, w83l771, max6696, sa56004, g781, tmp451 };
 
+enum sensor_id {
+	LOCAL = 0,
+	REMOTE,
+	REMOTE2,
+	SENSOR_ID_END,
+};
+
 /*
  * The LM90 registers
  */
@@ -368,6 +377,7 @@ struct lm90_data {
 	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 */
@@ -880,6 +890,24 @@ static ssize_t show_temp11(struct device
 	return sprintf(buf, "%d\n", read_temp11(dev, attr->index));
 }
 
+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;
+}
+
 static int write_temp11(struct device *dev, int nr, int index, long val)
 {
 	struct {
@@ -1210,6 +1238,18 @@ static const struct attribute_group lm90
 	.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)
@@ -1659,6 +1699,30 @@ static int lm90_probe(struct i2c_client
 		}
 	}
 
+	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:
@@ -1674,8 +1738,11 @@ exit_restore:
 
 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);