OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From 4e87400732c77765afae2ea89ed43837457aa604 Mon Sep 17 00:00:00 2001 |
2 | From: Rajith Cherian <rajith@codeaurora.org> |
||
3 | Date: Wed, 1 Feb 2017 19:00:26 +0530 |
||
4 | Subject: [PATCH] ipq8064: tsens: Support for configurable interrupts |
||
5 | |||
6 | Provide support for adding configurable high and |
||
7 | configurable low trip temperatures. An interrupts is |
||
8 | also triggerred when these trip points are hit. The |
||
9 | interrupts can be activated or deactivated from sysfs. |
||
10 | This functionality is made available only if |
||
11 | CONFIG_THERMAL_WRITABLE_TRIPS is defined. |
||
12 | |||
13 | Change-Id: Ib73f3f9459de4fffce7bb985a0312a88291f4934 |
||
14 | Signed-off-by: Rajith Cherian <rajith@codeaurora.org> |
||
15 | --- |
||
16 | .../devicetree/bindings/thermal/qcom-tsens.txt | 4 ++ |
||
17 | drivers/thermal/of-thermal.c | 63 ++++++++++++++++++---- |
||
18 | drivers/thermal/qcom/tsens.c | 43 ++++++++++++--- |
||
19 | drivers/thermal/qcom/tsens.h | 11 ++++ |
||
20 | drivers/thermal/thermal_core.c | 44 ++++++++++++++- |
||
21 | include/linux/thermal.h | 14 +++++ |
||
22 | 6 files changed, 162 insertions(+), 17 deletions(-) |
||
23 | |||
24 | --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt |
||
25 | +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt |
||
26 | @@ -12,11 +12,15 @@ Required properties: |
||
27 | - Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify |
||
28 | nvmem cells |
||
29 | |||
30 | +Optional properties: |
||
31 | +- interrupts: Interrupt which gets triggered when threshold is hit |
||
32 | + |
||
33 | Example: |
||
34 | tsens: thermal-sensor@900000 { |
||
35 | compatible = "qcom,msm8916-tsens"; |
||
36 | reg = <0x4a8000 0x2000>; |
||
37 | nvmem-cells = <&tsens_caldata>, <&tsens_calsel>; |
||
38 | nvmem-cell-names = "caldata", "calsel"; |
||
39 | + interrupts = <0 178 0>; |
||
40 | #thermal-sensor-cells = <1>; |
||
41 | }; |
||
42 | --- a/drivers/thermal/of-thermal.c |
||
43 | +++ b/drivers/thermal/of-thermal.c |
||
44 | @@ -95,7 +95,7 @@ static int of_thermal_get_temp(struct th |
||
45 | { |
||
46 | struct __thermal_zone *data = tz->devdata; |
||
47 | |||
48 | - if (!data->ops->get_temp) |
||
49 | + if (!data->ops->get_temp || (data->mode == THERMAL_DEVICE_DISABLED)) |
||
50 | return -EINVAL; |
||
51 | |||
52 | return data->ops->get_temp(data->sensor_data, temp); |
||
53 | @@ -106,7 +106,8 @@ static int of_thermal_set_trips(struct t |
||
54 | { |
||
55 | struct __thermal_zone *data = tz->devdata; |
||
56 | |||
57 | - if (!data->ops || !data->ops->set_trips) |
||
58 | + if (!data->ops || !data->ops->set_trips |
||
59 | + || (data->mode == THERMAL_DEVICE_DISABLED)) |
||
60 | return -EINVAL; |
||
61 | |||
62 | return data->ops->set_trips(data->sensor_data, low, high); |
||
63 | @@ -192,6 +193,9 @@ static int of_thermal_set_emul_temp(stru |
||
64 | { |
||
65 | struct __thermal_zone *data = tz->devdata; |
||
66 | |||
67 | + if (data->mode == THERMAL_DEVICE_DISABLED) |
||
68 | + return -EINVAL; |
||
69 | + |
||
70 | return data->ops->set_emul_temp(data->sensor_data, temp); |
||
71 | } |
||
72 | |||
73 | @@ -200,7 +204,7 @@ static int of_thermal_get_trend(struct t |
||
74 | { |
||
75 | struct __thermal_zone *data = tz->devdata; |
||
76 | |||
77 | - if (!data->ops->get_trend) |
||
78 | + if (!data->ops->get_trend || (data->mode == THERMAL_DEVICE_DISABLED)) |
||
79 | return -EINVAL; |
||
80 | |||
81 | return data->ops->get_trend(data->sensor_data, trip, trend); |
||
3 | office | 82 | @@ -286,7 +290,9 @@ static int of_thermal_set_mode(struct th |
1 | office | 83 | mutex_unlock(&tz->lock); |
84 | |||
85 | data->mode = mode; |
||
86 | - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); |
||
87 | + |
||
88 | + if (mode == THERMAL_DEVICE_ENABLED) |
||
89 | + thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); |
||
90 | |||
91 | return 0; |
||
92 | } |
||
3 | office | 93 | @@ -296,7 +302,8 @@ static int of_thermal_get_trip_type(stru |
1 | office | 94 | { |
95 | struct __thermal_zone *data = tz->devdata; |
||
96 | |||
97 | - if (trip >= data->ntrips || trip < 0) |
||
98 | + if (trip >= data->ntrips || trip < 0 |
||
99 | + || (data->mode == THERMAL_DEVICE_DISABLED)) |
||
100 | return -EDOM; |
||
101 | |||
102 | *type = data->trips[trip].type; |
||
3 | office | 103 | @@ -304,12 +311,39 @@ static int of_thermal_get_trip_type(stru |
1 | office | 104 | return 0; |
105 | } |
||
106 | |||
107 | +static int of_thermal_activate_trip_type(struct thermal_zone_device *tz, |
||
108 | + int trip, enum thermal_trip_activation_mode mode) |
||
109 | +{ |
||
110 | + struct __thermal_zone *data = tz->devdata; |
||
111 | + |
||
112 | + if (trip >= data->ntrips || trip < 0 |
||
113 | + || (data->mode == THERMAL_DEVICE_DISABLED)) |
||
114 | + return -EDOM; |
||
115 | + |
||
116 | + /* |
||
117 | + * The configurable_hi and configurable_lo trip points can be |
||
118 | + * activated and deactivated. |
||
119 | + */ |
||
120 | + |
||
121 | + if (data->ops->set_trip_activate) { |
||
122 | + int ret; |
||
123 | + |
||
124 | + ret = data->ops->set_trip_activate(data->sensor_data, |
||
125 | + trip, mode); |
||
126 | + if (ret) |
||
127 | + return ret; |
||
128 | + } |
||
129 | + |
||
130 | + return 0; |
||
131 | +} |
||
132 | + |
||
133 | static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip, |
||
134 | int *temp) |
||
135 | { |
||
136 | struct __thermal_zone *data = tz->devdata; |
||
137 | |||
138 | - if (trip >= data->ntrips || trip < 0) |
||
139 | + if (trip >= data->ntrips || trip < 0 |
||
140 | + || (data->mode == THERMAL_DEVICE_DISABLED)) |
||
141 | return -EDOM; |
||
142 | |||
143 | *temp = data->trips[trip].temperature; |
||
3 | office | 144 | @@ -322,7 +356,8 @@ static int of_thermal_set_trip_temp(stru |
1 | office | 145 | { |
146 | struct __thermal_zone *data = tz->devdata; |
||
147 | |||
148 | - if (trip >= data->ntrips || trip < 0) |
||
149 | + if (trip >= data->ntrips || trip < 0 |
||
150 | + || (data->mode == THERMAL_DEVICE_DISABLED)) |
||
151 | return -EDOM; |
||
152 | |||
153 | if (data->ops->set_trip_temp) { |
||
3 | office | 154 | @@ -344,7 +379,8 @@ static int of_thermal_get_trip_hyst(stru |
1 | office | 155 | { |
156 | struct __thermal_zone *data = tz->devdata; |
||
157 | |||
158 | - if (trip >= data->ntrips || trip < 0) |
||
159 | + if (trip >= data->ntrips || trip < 0 |
||
160 | + || (data->mode == THERMAL_DEVICE_DISABLED)) |
||
161 | return -EDOM; |
||
162 | |||
163 | *hyst = data->trips[trip].hysteresis; |
||
3 | office | 164 | @@ -357,7 +393,8 @@ static int of_thermal_set_trip_hyst(stru |
1 | office | 165 | { |
166 | struct __thermal_zone *data = tz->devdata; |
||
167 | |||
168 | - if (trip >= data->ntrips || trip < 0) |
||
169 | + if (trip >= data->ntrips || trip < 0 |
||
170 | + || (data->mode == THERMAL_DEVICE_DISABLED)) |
||
171 | return -EDOM; |
||
172 | |||
173 | /* thermal framework should take care of data->mask & (1 << trip) */ |
||
3 | office | 174 | @@ -432,6 +469,9 @@ thermal_zone_of_add_sensor(struct device |
1 | office | 175 | if (ops->set_emul_temp) |
176 | tzd->ops->set_emul_temp = of_thermal_set_emul_temp; |
||
177 | |||
178 | + if (ops->set_trip_activate) |
||
179 | + tzd->ops->set_trip_activate = of_thermal_activate_trip_type; |
||
180 | + |
||
181 | mutex_unlock(&tzd->lock); |
||
182 | |||
183 | return tzd; |
||
3 | office | 184 | @@ -726,7 +766,10 @@ static const char * const trip_types[] = |
1 | office | 185 | [THERMAL_TRIP_ACTIVE] = "active", |
186 | [THERMAL_TRIP_PASSIVE] = "passive", |
||
187 | [THERMAL_TRIP_HOT] = "hot", |
||
188 | - [THERMAL_TRIP_CRITICAL] = "critical", |
||
189 | + [THERMAL_TRIP_CRITICAL] = "critical_high", |
||
190 | + [THERMAL_TRIP_CONFIGURABLE_HI] = "configurable_hi", |
||
191 | + [THERMAL_TRIP_CONFIGURABLE_LOW] = "configurable_lo", |
||
192 | + [THERMAL_TRIP_CRITICAL_LOW] = "critical_low", |
||
193 | }; |
||
194 | |||
195 | /** |
||
196 | --- a/drivers/thermal/qcom/tsens.c |
||
197 | +++ b/drivers/thermal/qcom/tsens.c |
||
198 | @@ -31,7 +31,7 @@ static int tsens_get_temp(void *data, in |
||
199 | |||
200 | static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend) |
||
201 | { |
||
202 | - const struct tsens_sensor *s = p; |
||
203 | + struct tsens_sensor *s = p; |
||
204 | struct tsens_device *tmdev = s->tmdev; |
||
205 | |||
206 | if (tmdev->ops->get_trend) |
||
207 | @@ -40,9 +40,10 @@ static int tsens_get_trend(void *p, int |
||
208 | return -ENOTSUPP; |
||
209 | } |
||
210 | |||
211 | -static int __maybe_unused tsens_suspend(struct device *dev) |
||
212 | +static int __maybe_unused tsens_suspend(void *data) |
||
213 | { |
||
214 | - struct tsens_device *tmdev = dev_get_drvdata(dev); |
||
215 | + struct tsens_sensor *s = data; |
||
216 | + struct tsens_device *tmdev = s->tmdev; |
||
217 | |||
218 | if (tmdev->ops && tmdev->ops->suspend) |
||
219 | return tmdev->ops->suspend(tmdev); |
||
220 | @@ -50,9 +51,10 @@ static int __maybe_unused tsens_suspend |
||
221 | return 0; |
||
222 | } |
||
223 | |||
224 | -static int __maybe_unused tsens_resume(struct device *dev) |
||
225 | +static int __maybe_unused tsens_resume(void *data) |
||
226 | { |
||
227 | - struct tsens_device *tmdev = dev_get_drvdata(dev); |
||
228 | + struct tsens_sensor *s = data; |
||
229 | + struct tsens_device *tmdev = s->tmdev; |
||
230 | |||
231 | if (tmdev->ops && tmdev->ops->resume) |
||
232 | return tmdev->ops->resume(tmdev); |
||
233 | @@ -60,6 +62,30 @@ static int __maybe_unused tsens_resume(s |
||
234 | return 0; |
||
235 | } |
||
236 | |||
237 | +static int __maybe_unused tsens_set_trip_temp(void *data, int trip, int temp) |
||
238 | +{ |
||
239 | + struct tsens_sensor *s = data; |
||
240 | + struct tsens_device *tmdev = s->tmdev; |
||
241 | + |
||
242 | + if (tmdev->ops && tmdev->ops->set_trip_temp) |
||
243 | + return tmdev->ops->set_trip_temp(s, trip, temp); |
||
244 | + |
||
245 | + return 0; |
||
246 | +} |
||
247 | + |
||
248 | +static int __maybe_unused tsens_activate_trip_type(void *data, int trip, |
||
249 | + enum thermal_trip_activation_mode mode) |
||
250 | +{ |
||
251 | + struct tsens_sensor *s = data; |
||
252 | + struct tsens_device *tmdev = s->tmdev; |
||
253 | + |
||
254 | + if (tmdev->ops && tmdev->ops->set_trip_activate) |
||
255 | + return tmdev->ops->set_trip_activate(s, trip, mode); |
||
256 | + |
||
257 | + return 0; |
||
258 | +} |
||
259 | + |
||
260 | + |
||
261 | static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume); |
||
262 | |||
263 | static const struct of_device_id tsens_table[] = { |
||
264 | @@ -83,6 +109,8 @@ MODULE_DEVICE_TABLE(of, tsens_table); |
||
265 | static const struct thermal_zone_of_device_ops tsens_of_ops = { |
||
266 | .get_temp = tsens_get_temp, |
||
267 | .get_trend = tsens_get_trend, |
||
268 | + .set_trip_temp = tsens_set_trip_temp, |
||
269 | + .set_trip_activate = tsens_activate_trip_type, |
||
270 | }; |
||
271 | |||
272 | static int tsens_register(struct tsens_device *tmdev) |
||
273 | @@ -131,7 +159,7 @@ static int tsens_probe(struct platform_d |
||
274 | if (id) |
||
275 | data = id->data; |
||
276 | else |
||
277 | - data = &data_8960; |
||
278 | + return -EINVAL; |
||
279 | |||
280 | if (data->num_sensors <= 0) { |
||
281 | dev_err(dev, "invalid number of sensors\n"); |
||
282 | @@ -146,6 +174,9 @@ static int tsens_probe(struct platform_d |
||
283 | tmdev->dev = dev; |
||
284 | tmdev->num_sensors = data->num_sensors; |
||
285 | tmdev->ops = data->ops; |
||
286 | + |
||
287 | + tmdev->tsens_irq = platform_get_irq(pdev, 0); |
||
288 | + |
||
289 | for (i = 0; i < tmdev->num_sensors; i++) { |
||
290 | if (data->hw_ids) |
||
291 | tmdev->sensor[i].hw_id = data->hw_ids[i]; |
||
292 | --- a/drivers/thermal/qcom/tsens.h |
||
293 | +++ b/drivers/thermal/qcom/tsens.h |
||
294 | @@ -24,9 +24,12 @@ struct tsens_device; |
||
295 | struct tsens_sensor { |
||
296 | struct tsens_device *tmdev; |
||
297 | struct thermal_zone_device *tzd; |
||
298 | + struct work_struct notify_work; |
||
299 | int offset; |
||
300 | int id; |
||
301 | int hw_id; |
||
302 | + int calib_data; |
||
303 | + int calib_data_backup; |
||
304 | int slope; |
||
305 | u32 status; |
||
306 | }; |
||
307 | @@ -41,6 +44,9 @@ struct tsens_sensor { |
||
308 | * @suspend: Function to suspend the tsens device |
||
309 | * @resume: Function to resume the tsens device |
||
310 | * @get_trend: Function to get the thermal/temp trend |
||
311 | + * @set_trip_temp: Function to set trip temp |
||
312 | + * @get_trip_temp: Function to get trip temp |
||
313 | + * @set_trip_activate: Function to activate trip points |
||
314 | */ |
||
315 | struct tsens_ops { |
||
316 | /* mandatory callbacks */ |
||
317 | @@ -53,6 +59,9 @@ struct tsens_ops { |
||
318 | int (*suspend)(struct tsens_device *); |
||
319 | int (*resume)(struct tsens_device *); |
||
320 | int (*get_trend)(struct tsens_device *, int, enum thermal_trend *); |
||
321 | + int (*set_trip_temp)(void *, int, int); |
||
322 | + int (*set_trip_activate)(void *, int, |
||
323 | + enum thermal_trip_activation_mode); |
||
324 | }; |
||
325 | |||
326 | /** |
||
327 | @@ -76,11 +85,13 @@ struct tsens_context { |
||
328 | struct tsens_device { |
||
329 | struct device *dev; |
||
330 | u32 num_sensors; |
||
331 | + u32 tsens_irq; |
||
332 | struct regmap *map; |
||
333 | struct regmap_field *status_field; |
||
334 | struct tsens_context ctx; |
||
335 | bool trdy; |
||
336 | const struct tsens_ops *ops; |
||
337 | + struct work_struct tsens_work; |
||
338 | struct tsens_sensor sensor[0]; |
||
339 | }; |
||
340 | |||
341 | --- a/drivers/thermal/thermal_sysfs.c |
||
342 | +++ b/drivers/thermal/thermal_sysfs.c |
||
343 | @@ -115,12 +115,48 @@ trip_point_type_show(struct device *dev, |
||
344 | return sprintf(buf, "passive\n"); |
||
345 | case THERMAL_TRIP_ACTIVE: |
||
346 | return sprintf(buf, "active\n"); |
||
347 | + case THERMAL_TRIP_CONFIGURABLE_HI: |
||
348 | + return sprintf(buf, "configurable_hi\n"); |
||
349 | + case THERMAL_TRIP_CONFIGURABLE_LOW: |
||
350 | + return sprintf(buf, "configurable_low\n"); |
||
351 | + case THERMAL_TRIP_CRITICAL_LOW: |
||
352 | + return sprintf(buf, "critical_low\n"); |
||
353 | default: |
||
354 | return sprintf(buf, "unknown\n"); |
||
355 | } |
||
356 | } |
||
357 | |||
358 | static ssize_t |
||
359 | +trip_point_type_activate(struct device *dev, struct device_attribute *attr, |
||
360 | + const char *buf, size_t count) |
||
361 | +{ |
||
362 | + struct thermal_zone_device *tz = to_thermal_zone(dev); |
||
363 | + int trip, ret; |
||
364 | + char *enabled = "enabled"; |
||
365 | + char *disabled = "disabled"; |
||
366 | + |
||
367 | + if (!tz->ops->set_trip_activate) |
||
368 | + return -EPERM; |
||
369 | + |
||
370 | + if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) |
||
371 | + return -EINVAL; |
||
372 | + |
||
373 | + if (!strncmp(buf, enabled, strlen(enabled))) |
||
374 | + ret = tz->ops->set_trip_activate(tz, trip, |
||
375 | + THERMAL_TRIP_ACTIVATION_ENABLED); |
||
376 | + else if (!strncmp(buf, disabled, strlen(disabled))) |
||
377 | + ret = tz->ops->set_trip_activate(tz, trip, |
||
378 | + THERMAL_TRIP_ACTIVATION_DISABLED); |
||
379 | + else |
||
380 | + ret = -EINVAL; |
||
381 | + |
||
382 | + if (ret) |
||
383 | + return ret; |
||
384 | + |
||
385 | + return count; |
||
386 | +} |
||
387 | + |
||
388 | +static ssize_t |
||
389 | trip_point_temp_store(struct device *dev, struct device_attribute *attr, |
||
390 | const char *buf, size_t count) |
||
391 | { |
||
392 | @@ -562,6 +598,12 @@ static int create_trip_attrs(struct ther |
||
393 | tz->trip_type_attrs[indx].attr.show = trip_point_type_show; |
||
394 | attrs[indx] = &tz->trip_type_attrs[indx].attr.attr; |
||
395 | |||
396 | + if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS)) { |
||
397 | + tz->trip_type_attrs[indx].attr.store |
||
398 | + = trip_point_type_activate; |
||
399 | + tz->trip_type_attrs[indx].attr.attr.mode |= S_IWUSR; |
||
400 | + } |
||
401 | + |
||
402 | /* create trip temp attribute */ |
||
403 | snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH, |
||
404 | "trip_point_%d_temp", indx); |
||
405 | --- a/include/linux/thermal.h |
||
406 | +++ b/include/linux/thermal.h |
||
407 | @@ -78,11 +78,19 @@ enum thermal_device_mode { |
||
408 | THERMAL_DEVICE_ENABLED, |
||
409 | }; |
||
410 | |||
411 | +enum thermal_trip_activation_mode { |
||
412 | + THERMAL_TRIP_ACTIVATION_DISABLED = 0, |
||
413 | + THERMAL_TRIP_ACTIVATION_ENABLED, |
||
414 | +}; |
||
415 | + |
||
416 | enum thermal_trip_type { |
||
417 | THERMAL_TRIP_ACTIVE = 0, |
||
418 | THERMAL_TRIP_PASSIVE, |
||
419 | THERMAL_TRIP_HOT, |
||
420 | THERMAL_TRIP_CRITICAL, |
||
421 | + THERMAL_TRIP_CONFIGURABLE_HI, |
||
422 | + THERMAL_TRIP_CONFIGURABLE_LOW, |
||
423 | + THERMAL_TRIP_CRITICAL_LOW, |
||
424 | }; |
||
425 | |||
426 | enum thermal_trend { |
||
427 | @@ -120,6 +128,8 @@ struct thermal_zone_device_ops { |
||
428 | enum thermal_trip_type *); |
||
429 | int (*get_trip_temp) (struct thermal_zone_device *, int, int *); |
||
430 | int (*set_trip_temp) (struct thermal_zone_device *, int, int); |
||
431 | + int (*set_trip_activate) (struct thermal_zone_device *, int, |
||
432 | + enum thermal_trip_activation_mode); |
||
433 | int (*get_trip_hyst) (struct thermal_zone_device *, int, int *); |
||
434 | int (*set_trip_hyst) (struct thermal_zone_device *, int, int); |
||
435 | int (*get_crit_temp) (struct thermal_zone_device *, int *); |
||
436 | @@ -363,6 +373,8 @@ struct thermal_genl_event { |
||
437 | * temperature. |
||
438 | * @set_trip_temp: a pointer to a function that sets the trip temperature on |
||
439 | * hardware. |
||
440 | + * @activate_trip_type: a pointer to a function to enable/disable trip |
||
441 | + * temperature interrupts |
||
442 | */ |
||
443 | struct thermal_zone_of_device_ops { |
||
444 | int (*get_temp)(void *, int *); |
||
445 | @@ -370,6 +382,8 @@ struct thermal_zone_of_device_ops { |
||
446 | int (*set_trips)(void *, int, int); |
||
447 | int (*set_emul_temp)(void *, int); |
||
448 | int (*set_trip_temp)(void *, int, int); |
||
449 | + int (*set_trip_activate)(void *, int, |
||
450 | + enum thermal_trip_activation_mode); |
||
451 | }; |
||
452 | |||
453 | /** |