ramips: refresh patches
[oweals/openwrt.git] / target / linux / ipq806x / patches-4.19 / 0063-1-ipq806x-tsens-driver.patch
1 From 3302e1e1a3cfa4e67fda2a61d6f0c42205d40932 Mon Sep 17 00:00:00 2001
2 From: Rajith Cherian <rajith@codeaurora.org>
3 Date: Tue, 14 Feb 2017 18:30:43 +0530
4 Subject: [PATCH] ipq8064: tsens: Base tsens driver for IPQ8064
5
6 Add TSENS driver template to support IPQ8064.
7 This is a base file copied from tsens-8960.c
8
9 Change-Id: I47c573fdfa2d898243c6a6ba952d1632f91391f7
10 Signed-off-by: Rajith Cherian <rajith@codeaurora.org>
11
12 ipq8064: tsens: TSENS driver support for IPQ8064
13
14 Support for IPQ8064 tsens driver. The driver works
15 with the thermal framework. The driver overrides the
16 following fucntionalities:
17
18 1. Get current temperature.
19 2. Get/Set trip temperatures.
20 3. Enabled/Disable trip points.
21 4. ISR for threshold generated interrupt.
22 5. Notify userspace when trip points are hit.
23
24 Change-Id: I8bc7204fd627d10875ab13fc1de8cb6c2ed7a918
25 Signed-off-by: Rajith Cherian <rajith@codeaurora.org>
26 ---
27
28 --- a/drivers/thermal/qcom/Makefile
29 +++ b/drivers/thermal/qcom/Makefile
30 @@ -1,2 +1,3 @@
31  obj-$(CONFIG_QCOM_TSENS)       += qcom_tsens.o
32 -qcom_tsens-y                   += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o
33 +qcom_tsens-y                   += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o \
34 +                               tsens-ipq8064.o
35 --- /dev/null
36 +++ b/drivers/thermal/qcom/tsens-ipq8064.c
37 @@ -0,0 +1,551 @@
38 +/*
39 + * Copyright (c) 2015, The Linux Foundation. All rights reserved.
40 + *
41 + * This program is free software; you can redistribute it and/or modify
42 + * it under the terms of the GNU General Public License version 2 and
43 + * only version 2 as published by the Free Software Foundation.
44 + *
45 + * This program is distributed in the hope that it will be useful,
46 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
47 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
48 + * GNU General Public License for more details.
49 + *
50 + */
51 +
52 +#include <linux/platform_device.h>
53 +#include <linux/delay.h>
54 +#include <linux/bitops.h>
55 +#include <linux/regmap.h>
56 +#include <linux/thermal.h>
57 +#include <linux/nvmem-consumer.h>
58 +#include <linux/io.h>
59 +#include <linux/interrupt.h>
60 +#include "tsens.h"
61 +
62 +#define CAL_MDEGC              30000
63 +
64 +#define CONFIG_ADDR            0x3640
65 +/* CONFIG_ADDR bitmasks */
66 +#define CONFIG                 0x9b
67 +#define CONFIG_MASK            0xf
68 +#define CONFIG_SHIFT           0
69 +
70 +#define STATUS_CNTL_8064       0x3660
71 +#define CNTL_ADDR              0x3620
72 +/* CNTL_ADDR bitmasks */
73 +#define EN                     BIT(0)
74 +#define SW_RST                 BIT(1)
75 +#define SENSOR0_EN             BIT(3)
76 +#define SLP_CLK_ENA            BIT(26)
77 +#define MEASURE_PERIOD         1
78 +#define SENSOR0_SHIFT          3
79 +
80 +/* INT_STATUS_ADDR bitmasks */
81 +#define MIN_STATUS_MASK                BIT(0)
82 +#define LOWER_STATUS_CLR       BIT(1)
83 +#define UPPER_STATUS_CLR       BIT(2)
84 +#define MAX_STATUS_MASK                BIT(3)
85 +
86 +#define THRESHOLD_ADDR         0x3624
87 +/* THRESHOLD_ADDR bitmasks */
88 +#define THRESHOLD_MAX_CODE             0x20000
89 +#define THRESHOLD_MIN_CODE             0
90 +#define THRESHOLD_MAX_LIMIT_SHIFT      24
91 +#define THRESHOLD_MIN_LIMIT_SHIFT      16
92 +#define THRESHOLD_UPPER_LIMIT_SHIFT    8
93 +#define THRESHOLD_LOWER_LIMIT_SHIFT    0
94 +#define THRESHOLD_MAX_LIMIT_MASK       (THRESHOLD_MAX_CODE << \
95 +                                               THRESHOLD_MAX_LIMIT_SHIFT)
96 +#define THRESHOLD_MIN_LIMIT_MASK       (THRESHOLD_MAX_CODE << \
97 +                                               THRESHOLD_MIN_LIMIT_SHIFT)
98 +#define THRESHOLD_UPPER_LIMIT_MASK     (THRESHOLD_MAX_CODE << \
99 +                                               THRESHOLD_UPPER_LIMIT_SHIFT)
100 +#define THRESHOLD_LOWER_LIMIT_MASK     (THRESHOLD_MAX_CODE << \
101 +                                               THRESHOLD_LOWER_LIMIT_SHIFT)
102 +
103 +/* Initial temperature threshold values */
104 +#define LOWER_LIMIT_TH         0x9d /* 95C */
105 +#define UPPER_LIMIT_TH         0xa6 /* 105C */
106 +#define MIN_LIMIT_TH           0x0
107 +#define MAX_LIMIT_TH           0xff
108 +
109 +#define S0_STATUS_ADDR         0x3628
110 +#define STATUS_ADDR_OFFSET     2
111 +#define SENSOR_STATUS_SIZE     4
112 +#define INT_STATUS_ADDR                0x363c
113 +#define TRDY_MASK              BIT(7)
114 +#define TIMEOUT_US             100
115 +
116 +#define TSENS_EN               BIT(0)
117 +#define TSENS_SW_RST           BIT(1)
118 +#define TSENS_ADC_CLK_SEL      BIT(2)
119 +#define SENSOR0_EN             BIT(3)
120 +#define SENSOR1_EN             BIT(4)
121 +#define SENSOR2_EN             BIT(5)
122 +#define SENSOR3_EN             BIT(6)
123 +#define SENSOR4_EN             BIT(7)
124 +#define SENSORS_EN             (SENSOR0_EN | SENSOR1_EN | \
125 +                               SENSOR2_EN | SENSOR3_EN | SENSOR4_EN)
126 +#define TSENS_8064_SENSOR5_EN                          BIT(8)
127 +#define TSENS_8064_SENSOR6_EN                          BIT(9)
128 +#define TSENS_8064_SENSOR7_EN                          BIT(10)
129 +#define TSENS_8064_SENSOR8_EN                          BIT(11)
130 +#define TSENS_8064_SENSOR9_EN                          BIT(12)
131 +#define TSENS_8064_SENSOR10_EN                         BIT(13)
132 +#define TSENS_8064_SENSORS_EN                          (SENSORS_EN | \
133 +                                               TSENS_8064_SENSOR5_EN | \
134 +                                               TSENS_8064_SENSOR6_EN | \
135 +                                               TSENS_8064_SENSOR7_EN | \
136 +                                               TSENS_8064_SENSOR8_EN | \
137 +                                               TSENS_8064_SENSOR9_EN | \
138 +                                               TSENS_8064_SENSOR10_EN)
139 +
140 +#define TSENS_8064_SEQ_SENSORS 5
141 +#define TSENS_8064_S4_S5_OFFSET        40
142 +#define TSENS_FACTOR           1
143 +
144 +/* Trips: from very hot to very cold */
145 +enum tsens_trip_type {
146 +       TSENS_TRIP_STAGE3 = 0,
147 +       TSENS_TRIP_STAGE2,
148 +       TSENS_TRIP_STAGE1,
149 +       TSENS_TRIP_STAGE0,
150 +       TSENS_TRIP_NUM,
151 +};
152 +
153 +u32 tsens_8064_slope[] = {
154 +                       1176, 1176, 1154, 1176,
155 +                       1111, 1132, 1132, 1199,
156 +                       1132, 1199, 1132
157 +                       };
158 +
159 +/* Temperature on y axis and ADC-code on x-axis */
160 +static inline int code_to_degC(u32 adc_code, const struct tsens_sensor *s)
161 +{
162 +       int degcbeforefactor, degc;
163 +
164 +       degcbeforefactor = (adc_code * s->slope) + s->offset;
165 +
166 +       if (degcbeforefactor == 0)
167 +               degc = degcbeforefactor;
168 +       else if (degcbeforefactor > 0)
169 +               degc = (degcbeforefactor + TSENS_FACTOR/2)
170 +                       / TSENS_FACTOR;
171 +       else
172 +               degc = (degcbeforefactor - TSENS_FACTOR/2)
173 +                       / TSENS_FACTOR;
174 +
175 +       return degc;
176 +}
177 +
178 +static int degC_to_code(int degC, const struct tsens_sensor *s)
179 +{
180 +       int code = ((degC * TSENS_FACTOR - s->offset) + (s->slope/2))
181 +                       / s->slope;
182 +
183 +       if (code > THRESHOLD_MAX_CODE)
184 +               code = THRESHOLD_MAX_CODE;
185 +       else if (code < THRESHOLD_MIN_CODE)
186 +               code = THRESHOLD_MIN_CODE;
187 +       return code;
188 +}
189 +
190 +static int suspend_ipq8064(struct tsens_device *tmdev)
191 +{
192 +       int ret;
193 +       unsigned int mask;
194 +       struct regmap *map = tmdev->map;
195 +
196 +       ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
197 +       if (ret)
198 +               return ret;
199 +
200 +       ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
201 +       if (ret)
202 +               return ret;
203 +
204 +       mask = SLP_CLK_ENA | EN;
205 +
206 +       ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
207 +       if (ret)
208 +               return ret;
209 +
210 +       return 0;
211 +}
212 +
213 +static int resume_ipq8064(struct tsens_device *tmdev)
214 +{
215 +       int ret;
216 +       struct regmap *map = tmdev->map;
217 +
218 +       ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
219 +       if (ret)
220 +               return ret;
221 +
222 +       ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
223 +       if (ret)
224 +               return ret;
225 +
226 +       ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
227 +       if (ret)
228 +               return ret;
229 +
230 +       ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
231 +       if (ret)
232 +               return ret;
233 +
234 +       return 0;
235 +}
236 +
237 +static void notify_uspace_tsens_fn(struct work_struct *work)
238 +{
239 +       struct tsens_sensor *s = container_of(work, struct tsens_sensor,
240 +                                                               notify_work);
241 +
242 +       sysfs_notify(&s->tzd->device.kobj, NULL, "type");
243 +}
244 +
245 +static void tsens_scheduler_fn(struct work_struct *work)
246 +{
247 +       struct tsens_device *tmdev = container_of(work, struct tsens_device,
248 +                                       tsens_work);
249 +       unsigned int threshold, threshold_low, code, reg, sensor, mask;
250 +       unsigned int sensor_addr;
251 +       bool upper_th_x, lower_th_x;
252 +       int adc_code, ret;
253 +
254 +       ret = regmap_read(tmdev->map, STATUS_CNTL_8064, &reg);
255 +       if (ret)
256 +               return;
257 +       reg = reg | LOWER_STATUS_CLR | UPPER_STATUS_CLR;
258 +       ret = regmap_write(tmdev->map, STATUS_CNTL_8064, reg);
259 +       if (ret)
260 +               return;
261 +
262 +       mask = ~(LOWER_STATUS_CLR | UPPER_STATUS_CLR);
263 +       ret = regmap_read(tmdev->map, THRESHOLD_ADDR, &threshold);
264 +       if (ret)
265 +               return;
266 +       threshold_low = (threshold & THRESHOLD_LOWER_LIMIT_MASK)
267 +                               >> THRESHOLD_LOWER_LIMIT_SHIFT;
268 +       threshold = (threshold & THRESHOLD_UPPER_LIMIT_MASK)
269 +                               >> THRESHOLD_UPPER_LIMIT_SHIFT;
270 +
271 +       ret = regmap_read(tmdev->map, STATUS_CNTL_8064, &reg);
272 +       if (ret)
273 +               return;
274 +
275 +       ret = regmap_read(tmdev->map, CNTL_ADDR, &sensor);
276 +       if (ret)
277 +               return;
278 +       sensor &= (uint32_t) TSENS_8064_SENSORS_EN;
279 +       sensor >>= SENSOR0_SHIFT;
280 +
281 +       /* Constraint: There is only 1 interrupt control register for all
282 +        * 11 temperature sensor. So monitoring more than 1 sensor based
283 +        * on interrupts will yield inconsistent result. To overcome this
284 +        * issue we will monitor only sensor 0 which is the master sensor.
285 +        */
286 +
287 +       /* Skip if the sensor is disabled */
288 +       if (sensor & 1) {
289 +               ret = regmap_read(tmdev->map, tmdev->sensor[0].status, &code);
290 +               if (ret)
291 +                       return;
292 +               upper_th_x = code >= threshold;
293 +               lower_th_x = code <= threshold_low;
294 +               if (upper_th_x)
295 +                       mask |= UPPER_STATUS_CLR;
296 +               if (lower_th_x)
297 +                       mask |= LOWER_STATUS_CLR;
298 +               if (upper_th_x || lower_th_x) {
299 +                       /* Notify user space */
300 +                       schedule_work(&tmdev->sensor[0].notify_work);
301 +                       regmap_read(tmdev->map, sensor_addr, &adc_code);
302 +                       pr_debug("Trigger (%d degrees) for sensor %d\n",
303 +                               code_to_degC(adc_code, &tmdev->sensor[0]), 0);
304 +               }
305 +       }
306 +       regmap_write(tmdev->map, STATUS_CNTL_8064, reg & mask);
307 +
308 +       /* force memory to sync */
309 +       mb();
310 +}
311 +
312 +static irqreturn_t tsens_isr(int irq, void *data)
313 +{
314 +       struct tsens_device *tmdev = data;
315 +
316 +       schedule_work(&tmdev->tsens_work);
317 +       return IRQ_HANDLED;
318 +}
319 +
320 +static void hw_init(struct tsens_device *tmdev)
321 +{
322 +       int ret;
323 +       unsigned int reg_cntl = 0, reg_cfg = 0, reg_thr = 0;
324 +       unsigned int reg_status_cntl = 0;
325 +
326 +       regmap_read(tmdev->map, CNTL_ADDR, &reg_cntl);
327 +       regmap_write(tmdev->map, CNTL_ADDR, reg_cntl | TSENS_SW_RST);
328 +
329 +       reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18)
330 +               | (((1 << tmdev->num_sensors) - 1) << SENSOR0_SHIFT);
331 +       regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
332 +       regmap_read(tmdev->map, STATUS_CNTL_8064, &reg_status_cntl);
333 +       reg_status_cntl |= LOWER_STATUS_CLR | UPPER_STATUS_CLR
334 +                       | MIN_STATUS_MASK | MAX_STATUS_MASK;
335 +       regmap_write(tmdev->map, STATUS_CNTL_8064, reg_status_cntl);
336 +       reg_cntl |= TSENS_EN;
337 +       regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
338 +
339 +       regmap_read(tmdev->map, CONFIG_ADDR, &reg_cfg);
340 +       reg_cfg = (reg_cfg & ~CONFIG_MASK) | (CONFIG << CONFIG_SHIFT);
341 +       regmap_write(tmdev->map, CONFIG_ADDR, reg_cfg);
342 +
343 +       reg_thr |= (LOWER_LIMIT_TH << THRESHOLD_LOWER_LIMIT_SHIFT)
344 +               | (UPPER_LIMIT_TH << THRESHOLD_UPPER_LIMIT_SHIFT)
345 +               | (MIN_LIMIT_TH << THRESHOLD_MIN_LIMIT_SHIFT)
346 +               | (MAX_LIMIT_TH << THRESHOLD_MAX_LIMIT_SHIFT);
347 +
348 +       regmap_write(tmdev->map, THRESHOLD_ADDR, reg_thr);
349 +
350 +       ret = devm_request_irq(tmdev->dev, tmdev->tsens_irq, tsens_isr,
351 +                       IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev);
352 +       if (ret < 0) {
353 +               pr_err("%s: request_irq FAIL: %d\n", __func__, ret);
354 +               return;
355 +       }
356 +
357 +       INIT_WORK(&tmdev->tsens_work, tsens_scheduler_fn);
358 +}
359 +
360 +static int init_ipq8064(struct tsens_device *tmdev)
361 +{
362 +       int ret, i;
363 +       u32 reg_cntl, offset = 0;
364 +
365 +       init_common(tmdev);
366 +       if (!tmdev->map)
367 +               return -ENODEV;
368 +
369 +       /*
370 +        * The status registers for each sensor are discontiguous
371 +        * because some SoCs have 5 sensors while others have more
372 +        * but the control registers stay in the same place, i.e
373 +        * directly after the first 5 status registers.
374 +        */
375 +       for (i = 0; i < tmdev->num_sensors; i++) {
376 +               if (i >= TSENS_8064_SEQ_SENSORS)
377 +                       offset = TSENS_8064_S4_S5_OFFSET;
378 +
379 +               tmdev->sensor[i].status = S0_STATUS_ADDR + offset
380 +                                       + (i << STATUS_ADDR_OFFSET);
381 +               tmdev->sensor[i].slope = tsens_8064_slope[i];
382 +               INIT_WORK(&tmdev->sensor[i].notify_work,
383 +                                               notify_uspace_tsens_fn);
384 +       }
385 +
386 +       reg_cntl = SW_RST;
387 +       ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl);
388 +       if (ret)
389 +               return ret;
390 +
391 +       reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
392 +       reg_cntl &= ~SW_RST;
393 +       ret = regmap_update_bits(tmdev->map, CONFIG_ADDR,
394 +                                        CONFIG_MASK, CONFIG);
395 +
396 +       reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
397 +       ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
398 +       if (ret)
399 +               return ret;
400 +
401 +       reg_cntl |= EN;
402 +       ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
403 +       if (ret)
404 +               return ret;
405 +
406 +       return 0;
407 +}
408 +
409 +static int calibrate_ipq8064(struct tsens_device *tmdev)
410 +{
411 +       int i;
412 +       char *data, *data_backup;
413 +
414 +       ssize_t num_read = tmdev->num_sensors;
415 +       struct tsens_sensor *s = tmdev->sensor;
416 +
417 +       data = qfprom_read(tmdev->dev, "calib");
418 +       if (IS_ERR(data)) {
419 +               pr_err("Calibration not found.\n");
420 +               return PTR_ERR(data);
421 +       }
422 +
423 +       data_backup = qfprom_read(tmdev->dev, "calib_backup");
424 +       if (IS_ERR(data_backup)) {
425 +               pr_err("Backup calibration not found.\n");
426 +               return PTR_ERR(data_backup);
427 +       }
428 +
429 +       for (i = 0; i < num_read; i++) {
430 +               s[i].calib_data = readb_relaxed(data + i);
431 +               s[i].calib_data_backup = readb_relaxed(data_backup + i);
432 +
433 +               if (s[i].calib_data_backup)
434 +                       s[i].calib_data = s[i].calib_data_backup;
435 +               if (!s[i].calib_data) {
436 +                       pr_err("QFPROM TSENS calibration data not present\n");
437 +                       return -ENODEV;
438 +               }
439 +               s[i].slope = tsens_8064_slope[i];
440 +               s[i].offset = CAL_MDEGC - (s[i].calib_data * s[i].slope);
441 +       }
442 +
443 +       hw_init(tmdev);
444 +
445 +       return 0;
446 +}
447 +
448 +static int get_temp_ipq8064(struct tsens_device *tmdev, int id, int *temp)
449 +{
450 +       int ret;
451 +       u32 code, trdy;
452 +       const struct tsens_sensor *s = &tmdev->sensor[id];
453 +       unsigned long timeout;
454 +
455 +       timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
456 +       do {
457 +               ret = regmap_read(tmdev->map, INT_STATUS_ADDR, &trdy);
458 +               if (ret)
459 +                       return ret;
460 +               if (!(trdy & TRDY_MASK))
461 +                       continue;
462 +               ret = regmap_read(tmdev->map, s->status, &code);
463 +               if (ret)
464 +                       return ret;
465 +               *temp = code_to_degC(code, s);
466 +               return 0;
467 +       } while (time_before(jiffies, timeout));
468 +
469 +       return -ETIMEDOUT;
470 +}
471 +
472 +static int set_trip_temp_ipq8064(void *data, int trip, int temp)
473 +{
474 +       unsigned int reg_th, reg_cntl;
475 +       int ret, code, code_chk, hi_code, lo_code;
476 +       const struct tsens_sensor *s = data;
477 +       struct tsens_device *tmdev = s->tmdev;
478 +
479 +       code_chk = code = degC_to_code(temp, s);
480 +
481 +       if (code < THRESHOLD_MIN_CODE || code > THRESHOLD_MAX_CODE)
482 +               return -EINVAL;
483 +
484 +       ret = regmap_read(tmdev->map, STATUS_CNTL_8064, &reg_cntl);
485 +       if (ret)
486 +               return ret;
487 +
488 +       ret = regmap_read(tmdev->map, THRESHOLD_ADDR, &reg_th);
489 +       if (ret)
490 +               return ret;
491 +
492 +       hi_code = (reg_th & THRESHOLD_UPPER_LIMIT_MASK)
493 +                       >> THRESHOLD_UPPER_LIMIT_SHIFT;
494 +       lo_code = (reg_th & THRESHOLD_LOWER_LIMIT_MASK)
495 +                       >> THRESHOLD_LOWER_LIMIT_SHIFT;
496 +
497 +       switch (trip) {
498 +       case TSENS_TRIP_STAGE3:
499 +               code <<= THRESHOLD_MAX_LIMIT_SHIFT;
500 +               reg_th &= ~THRESHOLD_MAX_LIMIT_MASK;
501 +               break;
502 +       case TSENS_TRIP_STAGE2:
503 +               if (code_chk <= lo_code)
504 +                       return -EINVAL;
505 +               code <<= THRESHOLD_UPPER_LIMIT_SHIFT;
506 +               reg_th &= ~THRESHOLD_UPPER_LIMIT_MASK;
507 +               break;
508 +       case TSENS_TRIP_STAGE1:
509 +               if (code_chk >= hi_code)
510 +                       return -EINVAL;
511 +               code <<= THRESHOLD_LOWER_LIMIT_SHIFT;
512 +               reg_th &= ~THRESHOLD_LOWER_LIMIT_MASK;
513 +               break;
514 +       case TSENS_TRIP_STAGE0:
515 +               code <<= THRESHOLD_MIN_LIMIT_SHIFT;
516 +               reg_th &= ~THRESHOLD_MIN_LIMIT_MASK;
517 +               break;
518 +       default:
519 +               return -EINVAL;
520 +       }
521 +
522 +       ret = regmap_write(tmdev->map, THRESHOLD_ADDR, reg_th | code);
523 +       if (ret)
524 +               return ret;
525 +
526 +       return 0;
527 +}
528 +
529 +static int set_trip_activate_ipq8064(void *data, int trip,
530 +                                       enum thermal_trip_activation_mode mode)
531 +{
532 +       unsigned int reg_cntl, mask, val;
533 +       const struct tsens_sensor *s = data;
534 +       struct tsens_device *tmdev = s->tmdev;
535 +       int ret;
536 +
537 +       if (!tmdev || trip < 0)
538 +               return -EINVAL;
539 +
540 +       ret = regmap_read(tmdev->map, STATUS_CNTL_8064, &reg_cntl);
541 +       if (ret)
542 +               return ret;
543 +
544 +       switch (trip) {
545 +       case TSENS_TRIP_STAGE3:
546 +               mask = MAX_STATUS_MASK;
547 +               break;
548 +       case TSENS_TRIP_STAGE2:
549 +               mask = UPPER_STATUS_CLR;
550 +               break;
551 +       case TSENS_TRIP_STAGE1:
552 +               mask = LOWER_STATUS_CLR;
553 +               break;
554 +       case TSENS_TRIP_STAGE0:
555 +               mask = MIN_STATUS_MASK;
556 +               break;
557 +       default:
558 +               return -EINVAL;
559 +       }
560 +
561 +       if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
562 +               val = reg_cntl | mask;
563 +       else
564 +               val = reg_cntl & ~mask;
565 +
566 +       ret = regmap_write(tmdev->map, STATUS_CNTL_8064, val);
567 +       if (ret)
568 +               return ret;
569 +
570 +       /* force memory to sync */
571 +       mb();
572 +       return 0;
573 +}
574 +
575 +const struct tsens_ops ops_ipq8064 = {
576 +       .init           = init_ipq8064,
577 +       .calibrate      = calibrate_ipq8064,
578 +       .get_temp       = get_temp_ipq8064,
579 +       .suspend        = suspend_ipq8064,
580 +       .resume         = resume_ipq8064,
581 +       .set_trip_temp  = set_trip_temp_ipq8064,
582 +       .set_trip_activate = set_trip_activate_ipq8064,
583 +};
584 +
585 +const struct tsens_data data_ipq8064 = {
586 +       .num_sensors    = 11,
587 +       .ops            = &ops_ipq8064,
588 +};
589 --- a/drivers/thermal/qcom/tsens.c
590 +++ b/drivers/thermal/qcom/tsens.c
591 @@ -75,8 +75,11 @@ static const struct of_device_id tsens_t
592         }, {
593                 .compatible = "qcom,tsens-v2",
594                 .data = &data_tsens_v2,
595 +       }, {
596 +               .compatible = "qcom,ipq8064-tsens",
597 +               .data = &data_ipq8064,
598         },
599 -       {}
600 +       {}
601  };
602  MODULE_DEVICE_TABLE(of, tsens_table);
603  
604 --- a/drivers/thermal/qcom/tsens.h
605 +++ b/drivers/thermal/qcom/tsens.h
606 @@ -89,7 +89,7 @@ int init_common(struct tsens_device *);
607  int get_temp_common(struct tsens_device *, int, int *);
608  
609  /* TSENS v1 targets */
610 -extern const struct tsens_data data_8916, data_8974, data_8960;
611 +extern const struct tsens_data data_8916, data_8974, data_8960, data_ipq8064;
612  /* TSENS v2 targets */
613  extern const struct tsens_data data_8996, data_tsens_v2;
614