@@ -20,6 +20,11 @@ struct scmi_sensors {
20
20
const struct scmi_sensor_info * * info [hwmon_max ];
21
21
};
22
22
23
+ struct scmi_thermal_sensor {
24
+ const struct scmi_protocol_handle * ph ;
25
+ const struct scmi_sensor_info * info ;
26
+ };
27
+
23
28
static inline u64 __pow10 (u8 x )
24
29
{
25
30
u64 r = 1 ;
@@ -64,16 +69,14 @@ static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value)
64
69
return 0 ;
65
70
}
66
71
67
- static int scmi_hwmon_read (struct device * dev , enum hwmon_sensor_types type ,
68
- u32 attr , int channel , long * val )
72
+ static int scmi_hwmon_read_scaled_value (const struct scmi_protocol_handle * ph ,
73
+ const struct scmi_sensor_info * sensor ,
74
+ long * val )
69
75
{
70
76
int ret ;
71
77
u64 value ;
72
- const struct scmi_sensor_info * sensor ;
73
- struct scmi_sensors * scmi_sensors = dev_get_drvdata (dev );
74
78
75
- sensor = * (scmi_sensors -> info [type ] + channel );
76
- ret = sensor_ops -> reading_get (scmi_sensors -> ph , sensor -> id , & value );
79
+ ret = sensor_ops -> reading_get (ph , sensor -> id , & value );
77
80
if (ret )
78
81
return ret ;
79
82
@@ -84,6 +87,17 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
84
87
return ret ;
85
88
}
86
89
90
+ static int scmi_hwmon_read (struct device * dev , enum hwmon_sensor_types type ,
91
+ u32 attr , int channel , long * val )
92
+ {
93
+ const struct scmi_sensor_info * sensor ;
94
+ struct scmi_sensors * scmi_sensors = dev_get_drvdata (dev );
95
+
96
+ sensor = * (scmi_sensors -> info [type ] + channel );
97
+
98
+ return scmi_hwmon_read_scaled_value (scmi_sensors -> ph , sensor , val );
99
+ }
100
+
87
101
static int
88
102
scmi_hwmon_read_string (struct device * dev , enum hwmon_sensor_types type ,
89
103
u32 attr , int channel , const char * * str )
@@ -122,6 +136,25 @@ static struct hwmon_chip_info scmi_chip_info = {
122
136
.info = NULL ,
123
137
};
124
138
139
+ static int scmi_hwmon_thermal_get_temp (struct thermal_zone_device * tz ,
140
+ int * temp )
141
+ {
142
+ int ret ;
143
+ long value ;
144
+ struct scmi_thermal_sensor * th_sensor = tz -> devdata ;
145
+
146
+ ret = scmi_hwmon_read_scaled_value (th_sensor -> ph , th_sensor -> info ,
147
+ & value );
148
+ if (!ret )
149
+ * temp = value ;
150
+
151
+ return ret ;
152
+ }
153
+
154
+ static const struct thermal_zone_device_ops scmi_hwmon_thermal_ops = {
155
+ .get_temp = scmi_hwmon_thermal_get_temp ,
156
+ };
157
+
125
158
static int scmi_hwmon_add_chan_info (struct hwmon_channel_info * scmi_hwmon_chan ,
126
159
struct device * dev , int num ,
127
160
enum hwmon_sensor_types type , u32 config )
@@ -149,22 +182,58 @@ static enum hwmon_sensor_types scmi_types[] = {
149
182
};
150
183
151
184
static u32 hwmon_attributes [hwmon_max ] = {
152
- [hwmon_chip ] = HWMON_C_REGISTER_TZ ,
153
185
[hwmon_temp ] = HWMON_T_INPUT | HWMON_T_LABEL ,
154
186
[hwmon_in ] = HWMON_I_INPUT | HWMON_I_LABEL ,
155
187
[hwmon_curr ] = HWMON_C_INPUT | HWMON_C_LABEL ,
156
188
[hwmon_power ] = HWMON_P_INPUT | HWMON_P_LABEL ,
157
189
[hwmon_energy ] = HWMON_E_INPUT | HWMON_E_LABEL ,
158
190
};
159
191
192
+ static int scmi_thermal_sensor_register (struct device * dev ,
193
+ const struct scmi_protocol_handle * ph ,
194
+ const struct scmi_sensor_info * sensor )
195
+ {
196
+ struct scmi_thermal_sensor * th_sensor ;
197
+ struct thermal_zone_device * tzd ;
198
+
199
+ th_sensor = devm_kzalloc (dev , sizeof (* th_sensor ), GFP_KERNEL );
200
+ if (!th_sensor )
201
+ return - ENOMEM ;
202
+
203
+ th_sensor -> ph = ph ;
204
+ th_sensor -> info = sensor ;
205
+
206
+ /*
207
+ * Try to register a temperature sensor with the Thermal Framework:
208
+ * skip sensors not defined as part of any thermal zone (-ENODEV) but
209
+ * report any other errors related to misconfigured zones/sensors.
210
+ */
211
+ tzd = devm_thermal_of_zone_register (dev , th_sensor -> info -> id , th_sensor ,
212
+ & scmi_hwmon_thermal_ops );
213
+ if (IS_ERR (tzd )) {
214
+ devm_kfree (dev , th_sensor );
215
+
216
+ if (PTR_ERR (tzd ) != - ENODEV )
217
+ return PTR_ERR (tzd );
218
+
219
+ dev_dbg (dev , "Sensor '%s' not attached to any thermal zone.\n" ,
220
+ sensor -> name );
221
+ } else {
222
+ dev_dbg (dev , "Sensor '%s' attached to thermal zone ID:%d\n" ,
223
+ sensor -> name , tzd -> id );
224
+ }
225
+
226
+ return 0 ;
227
+ }
228
+
160
229
static int scmi_hwmon_probe (struct scmi_device * sdev )
161
230
{
162
231
int i , idx ;
163
232
u16 nr_sensors ;
164
233
enum hwmon_sensor_types type ;
165
234
struct scmi_sensors * scmi_sensors ;
166
235
const struct scmi_sensor_info * sensor ;
167
- int nr_count [hwmon_max ] = {0 }, nr_types = 0 ;
236
+ int nr_count [hwmon_max ] = {0 }, nr_types = 0 , nr_count_temp = 0 ;
168
237
const struct hwmon_chip_info * chip_info ;
169
238
struct device * hwdev , * dev = & sdev -> dev ;
170
239
struct hwmon_channel_info * scmi_hwmon_chan ;
@@ -208,10 +277,8 @@ static int scmi_hwmon_probe(struct scmi_device *sdev)
208
277
}
209
278
}
210
279
211
- if (nr_count [hwmon_temp ]) {
212
- nr_count [hwmon_chip ]++ ;
213
- nr_types ++ ;
214
- }
280
+ if (nr_count [hwmon_temp ])
281
+ nr_count_temp = nr_count [hwmon_temp ];
215
282
216
283
scmi_hwmon_chan = devm_kcalloc (dev , nr_types , sizeof (* scmi_hwmon_chan ),
217
284
GFP_KERNEL );
@@ -262,8 +329,31 @@ static int scmi_hwmon_probe(struct scmi_device *sdev)
262
329
hwdev = devm_hwmon_device_register_with_info (dev , "scmi_sensors" ,
263
330
scmi_sensors , chip_info ,
264
331
NULL );
332
+ if (IS_ERR (hwdev ))
333
+ return PTR_ERR (hwdev );
265
334
266
- return PTR_ERR_OR_ZERO (hwdev );
335
+ for (i = 0 ; i < nr_count_temp ; i ++ ) {
336
+ int ret ;
337
+
338
+ sensor = * (scmi_sensors -> info [hwmon_temp ] + i );
339
+ if (!sensor )
340
+ continue ;
341
+
342
+ /*
343
+ * Warn on any misconfiguration related to thermal zones but
344
+ * bail out of probing only on memory errors.
345
+ */
346
+ ret = scmi_thermal_sensor_register (dev , ph , sensor );
347
+ if (ret ) {
348
+ if (ret == - ENOMEM )
349
+ return ret ;
350
+ dev_warn (dev ,
351
+ "Thermal zone misconfigured for %s. err=%d\n" ,
352
+ sensor -> name , ret );
353
+ }
354
+ }
355
+
356
+ return 0 ;
267
357
}
268
358
269
359
static const struct scmi_device_id scmi_id_table [] = {
0 commit comments