kernel: update kernel 4.9 to 4.9.20
[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 --- 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);
82 @@ -286,7 +290,9 @@ static int of_thermal_set_mode(struct th
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 }
93 @@ -296,7 +302,8 @@ static int of_thermal_get_trip_type(stru
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;
103 @@ -304,12 +311,39 @@ static int of_thermal_get_trip_type(stru
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;
144 @@ -322,7 +356,8 @@ static int of_thermal_set_trip_temp(stru
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) {
154 @@ -344,7 +379,8 @@ static int of_thermal_get_trip_hyst(stru
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;
164 @@ -357,7 +393,8 @@ static int of_thermal_set_trip_hyst(stru
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) */
174 @@ -432,6 +469,9 @@ thermal_zone_of_add_sensor(struct device
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;
184 @@ -726,7 +766,10 @@ static const char * const trip_types[] =
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_core.c
342 +++ b/drivers/thermal/thermal_core.c
343 @@ -732,12 +732,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 @@ -1321,7 +1357,7 @@ thermal_cooling_device_weight_store(stru
393 */
394 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
395 int trip,
396 - struct thermal_cooling_device *cdev,
397 + struct thermal_cooling_device *cdev,
398 unsigned long upper, unsigned long lower,
399 unsigned int weight)
400 {
401 @@ -1772,6 +1808,12 @@ static int create_trip_attrs(struct ther
402 tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO;
403 tz->trip_type_attrs[indx].attr.show = trip_point_type_show;
404
405 + if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS)) {
406 + tz->trip_type_attrs[indx].attr.store
407 + = trip_point_type_activate;
408 + tz->trip_type_attrs[indx].attr.attr.mode |= S_IWUSR;
409 + }
410 +
411 device_create_file(&tz->device,
412 &tz->trip_type_attrs[indx].attr);
413
414 --- a/include/linux/thermal.h
415 +++ b/include/linux/thermal.h
416 @@ -77,11 +77,19 @@ enum thermal_device_mode {
417 THERMAL_DEVICE_ENABLED,
418 };
419
420 +enum thermal_trip_activation_mode {
421 + THERMAL_TRIP_ACTIVATION_DISABLED = 0,
422 + THERMAL_TRIP_ACTIVATION_ENABLED,
423 +};
424 +
425 enum thermal_trip_type {
426 THERMAL_TRIP_ACTIVE = 0,
427 THERMAL_TRIP_PASSIVE,
428 THERMAL_TRIP_HOT,
429 THERMAL_TRIP_CRITICAL,
430 + THERMAL_TRIP_CONFIGURABLE_HI,
431 + THERMAL_TRIP_CONFIGURABLE_LOW,
432 + THERMAL_TRIP_CRITICAL_LOW,
433 };
434
435 enum thermal_trend {
436 @@ -118,6 +126,8 @@ struct thermal_zone_device_ops {
437 enum thermal_trip_type *);
438 int (*get_trip_temp) (struct thermal_zone_device *, int, int *);
439 int (*set_trip_temp) (struct thermal_zone_device *, int, int);
440 + int (*set_trip_activate) (struct thermal_zone_device *, int,
441 + enum thermal_trip_activation_mode);
442 int (*get_trip_hyst) (struct thermal_zone_device *, int, int *);
443 int (*set_trip_hyst) (struct thermal_zone_device *, int, int);
444 int (*get_crit_temp) (struct thermal_zone_device *, int *);
445 @@ -360,6 +370,8 @@ struct thermal_genl_event {
446 * temperature.
447 * @set_trip_temp: a pointer to a function that sets the trip temperature on
448 * hardware.
449 + * @activate_trip_type: a pointer to a function to enable/disable trip
450 + * temperature interrupts
451 */
452 struct thermal_zone_of_device_ops {
453 int (*get_temp)(void *, int *);
454 @@ -367,6 +379,8 @@ struct thermal_zone_of_device_ops {
455 int (*set_trips)(void *, int, int);
456 int (*set_emul_temp)(void *, int);
457 int (*set_trip_temp)(void *, int, int);
458 + int (*set_trip_activate)(void *, int,
459 + enum thermal_trip_activation_mode);
460 };
461
462 /**