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