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