thermal: qcom-spmi-temp-alarm: add support for GEN2 PMIC peripherals
[linux-block.git] / drivers / thermal / imx_thermal.c
CommitLineData
ca3de46b
SG
1/*
2 * Copyright 2013 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
9
329fe7b1 10#include <linux/clk.h>
4d753aa7 11#include <linux/cpufreq.h>
ca3de46b 12#include <linux/cpu_cooling.h>
ca3de46b
SG
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/init.h>
37713a1e 16#include <linux/interrupt.h>
ca3de46b
SG
17#include <linux/io.h>
18#include <linux/kernel.h>
19#include <linux/mfd/syscon.h>
20#include <linux/module.h>
21#include <linux/of.h>
3c94f17e 22#include <linux/of_device.h>
ca3de46b
SG
23#include <linux/platform_device.h>
24#include <linux/regmap.h>
25#include <linux/slab.h>
26#include <linux/thermal.h>
27#include <linux/types.h>
ae621557 28#include <linux/nvmem-consumer.h>
ca3de46b
SG
29
30#define REG_SET 0x4
31#define REG_CLR 0x8
32#define REG_TOG 0xc
33
f085f672
AH
34/* i.MX6 specific */
35#define IMX6_MISC0 0x0150
36#define IMX6_MISC0_REFTOP_SELBIASOFF (1 << 3)
37#define IMX6_MISC1 0x0160
38#define IMX6_MISC1_IRQ_TEMPHIGH (1 << 29)
3c94f17e 39/* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */
f085f672
AH
40#define IMX6_MISC1_IRQ_TEMPLOW (1 << 28)
41#define IMX6_MISC1_IRQ_TEMPPANIC (1 << 27)
42
43#define IMX6_TEMPSENSE0 0x0180
44#define IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT 20
45#define IMX6_TEMPSENSE0_ALARM_VALUE_MASK (0xfff << 20)
46#define IMX6_TEMPSENSE0_TEMP_CNT_SHIFT 8
47#define IMX6_TEMPSENSE0_TEMP_CNT_MASK (0xfff << 8)
48#define IMX6_TEMPSENSE0_FINISHED (1 << 2)
49#define IMX6_TEMPSENSE0_MEASURE_TEMP (1 << 1)
50#define IMX6_TEMPSENSE0_POWER_DOWN (1 << 0)
51
52#define IMX6_TEMPSENSE1 0x0190
53#define IMX6_TEMPSENSE1_MEASURE_FREQ 0xffff
54#define IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT 0
ca3de46b 55
a2291bad 56#define OCOTP_MEM0 0x0480
ca3de46b
SG
57#define OCOTP_ANA1 0x04e0
58
f085f672
AH
59/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
60#define IMX6_TEMPSENSE2 0x0290
61#define IMX6_TEMPSENSE2_LOW_VALUE_SHIFT 0
62#define IMX6_TEMPSENSE2_LOW_VALUE_MASK 0xfff
63#define IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT 16
64#define IMX6_TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000
65
66/* i.MX7 specific */
67#define IMX7_ANADIG_DIGPROG 0x800
68#define IMX7_TEMPSENSE0 0x300
69#define IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT 18
70#define IMX7_TEMPSENSE0_PANIC_ALARM_MASK (0x1ff << 18)
71#define IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT 9
72#define IMX7_TEMPSENSE0_HIGH_ALARM_MASK (0x1ff << 9)
73#define IMX7_TEMPSENSE0_LOW_ALARM_SHIFT 0
74#define IMX7_TEMPSENSE0_LOW_ALARM_MASK 0x1ff
75
76#define IMX7_TEMPSENSE1 0x310
77#define IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT 16
78#define IMX7_TEMPSENSE1_MEASURE_FREQ_MASK (0xffff << 16)
79#define IMX7_TEMPSENSE1_FINISHED (1 << 11)
80#define IMX7_TEMPSENSE1_MEASURE_TEMP (1 << 10)
81#define IMX7_TEMPSENSE1_POWER_DOWN (1 << 9)
82#define IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT 0
83#define IMX7_TEMPSENSE1_TEMP_VALUE_MASK 0x1ff
84
ca3de46b
SG
85/* The driver supports 1 passive trip point and 1 critical trip point */
86enum imx_thermal_trip {
87 IMX_TRIP_PASSIVE,
88 IMX_TRIP_CRITICAL,
89 IMX_TRIP_NUM,
90};
91
ca3de46b
SG
92#define IMX_POLLING_DELAY 2000 /* millisecond */
93#define IMX_PASSIVE_DELAY 1000
94
3c94f17e
AH
95#define TEMPMON_IMX6Q 1
96#define TEMPMON_IMX6SX 2
f085f672 97#define TEMPMON_IMX7D 3
3c94f17e
AH
98
99struct thermal_soc_data {
100 u32 version;
f085f672
AH
101
102 u32 sensor_ctrl;
103 u32 power_down_mask;
104 u32 measure_temp_mask;
105
106 u32 measure_freq_ctrl;
107 u32 measure_freq_mask;
108 u32 measure_freq_shift;
109
110 u32 temp_data;
111 u32 temp_value_mask;
112 u32 temp_value_shift;
113 u32 temp_valid_mask;
114
115 u32 panic_alarm_ctrl;
116 u32 panic_alarm_mask;
117 u32 panic_alarm_shift;
118
119 u32 high_alarm_ctrl;
120 u32 high_alarm_mask;
121 u32 high_alarm_shift;
122
123 u32 low_alarm_ctrl;
124 u32 low_alarm_mask;
125 u32 low_alarm_shift;
3c94f17e
AH
126};
127
128static struct thermal_soc_data thermal_imx6q_data = {
129 .version = TEMPMON_IMX6Q,
f085f672
AH
130
131 .sensor_ctrl = IMX6_TEMPSENSE0,
132 .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
133 .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
134
135 .measure_freq_ctrl = IMX6_TEMPSENSE1,
136 .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
137 .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
138
139 .temp_data = IMX6_TEMPSENSE0,
140 .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
141 .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
142 .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
143
144 .high_alarm_ctrl = IMX6_TEMPSENSE0,
145 .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
146 .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
3c94f17e
AH
147};
148
149static struct thermal_soc_data thermal_imx6sx_data = {
150 .version = TEMPMON_IMX6SX,
f085f672
AH
151
152 .sensor_ctrl = IMX6_TEMPSENSE0,
153 .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
154 .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
155
156 .measure_freq_ctrl = IMX6_TEMPSENSE1,
157 .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
158 .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
159
160 .temp_data = IMX6_TEMPSENSE0,
161 .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
162 .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
163 .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
164
165 .high_alarm_ctrl = IMX6_TEMPSENSE0,
166 .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
167 .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
168
169 .panic_alarm_ctrl = IMX6_TEMPSENSE2,
170 .panic_alarm_mask = IMX6_TEMPSENSE2_PANIC_VALUE_MASK,
171 .panic_alarm_shift = IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT,
172
173 .low_alarm_ctrl = IMX6_TEMPSENSE2,
174 .low_alarm_mask = IMX6_TEMPSENSE2_LOW_VALUE_MASK,
175 .low_alarm_shift = IMX6_TEMPSENSE2_LOW_VALUE_SHIFT,
176};
177
178static struct thermal_soc_data thermal_imx7d_data = {
179 .version = TEMPMON_IMX7D,
180
181 .sensor_ctrl = IMX7_TEMPSENSE1,
182 .power_down_mask = IMX7_TEMPSENSE1_POWER_DOWN,
183 .measure_temp_mask = IMX7_TEMPSENSE1_MEASURE_TEMP,
184
185 .measure_freq_ctrl = IMX7_TEMPSENSE1,
186 .measure_freq_shift = IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT,
187 .measure_freq_mask = IMX7_TEMPSENSE1_MEASURE_FREQ_MASK,
188
189 .temp_data = IMX7_TEMPSENSE1,
190 .temp_value_mask = IMX7_TEMPSENSE1_TEMP_VALUE_MASK,
191 .temp_value_shift = IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT,
192 .temp_valid_mask = IMX7_TEMPSENSE1_FINISHED,
193
194 .panic_alarm_ctrl = IMX7_TEMPSENSE1,
195 .panic_alarm_mask = IMX7_TEMPSENSE0_PANIC_ALARM_MASK,
196 .panic_alarm_shift = IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT,
197
198 .high_alarm_ctrl = IMX7_TEMPSENSE0,
199 .high_alarm_mask = IMX7_TEMPSENSE0_HIGH_ALARM_MASK,
200 .high_alarm_shift = IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT,
201
202 .low_alarm_ctrl = IMX7_TEMPSENSE0,
203 .low_alarm_mask = IMX7_TEMPSENSE0_LOW_ALARM_MASK,
204 .low_alarm_shift = IMX7_TEMPSENSE0_LOW_ALARM_SHIFT,
3c94f17e
AH
205};
206
ca3de46b 207struct imx_thermal_data {
4d753aa7 208 struct cpufreq_policy *policy;
ca3de46b
SG
209 struct thermal_zone_device *tz;
210 struct thermal_cooling_device *cdev;
211 enum thermal_device_mode mode;
212 struct regmap *tempmon;
ae621557 213 u32 c1, c2; /* See formula in imx_init_calib() */
17e8351a
SH
214 int temp_passive;
215 int temp_critical;
a2291bad 216 int temp_max;
17e8351a
SH
217 int alarm_temp;
218 int last_temp;
37713a1e
PZ
219 bool irq_enabled;
220 int irq;
329fe7b1 221 struct clk *thermal_clk;
3c94f17e 222 const struct thermal_soc_data *socdata;
a2291bad 223 const char *temp_grade;
ca3de46b
SG
224};
225
3c94f17e 226static void imx_set_panic_temp(struct imx_thermal_data *data,
17e8351a 227 int panic_temp)
3c94f17e 228{
f085f672 229 const struct thermal_soc_data *soc_data = data->socdata;
3c94f17e
AH
230 struct regmap *map = data->tempmon;
231 int critical_value;
232
233 critical_value = (data->c2 - panic_temp) / data->c1;
f085f672
AH
234
235 regmap_write(map, soc_data->panic_alarm_ctrl + REG_CLR,
236 soc_data->panic_alarm_mask);
237 regmap_write(map, soc_data->panic_alarm_ctrl + REG_SET,
238 critical_value << soc_data->panic_alarm_shift);
3c94f17e
AH
239}
240
37713a1e 241static void imx_set_alarm_temp(struct imx_thermal_data *data,
17e8351a 242 int alarm_temp)
37713a1e
PZ
243{
244 struct regmap *map = data->tempmon;
f085f672 245 const struct thermal_soc_data *soc_data = data->socdata;
37713a1e
PZ
246 int alarm_value;
247
248 data->alarm_temp = alarm_temp;
f085f672
AH
249
250 if (data->socdata->version == TEMPMON_IMX7D)
251 alarm_value = alarm_temp / 1000 + data->c1 - 25;
252 else
253 alarm_value = (data->c2 - alarm_temp) / data->c1;
254
255 regmap_write(map, soc_data->high_alarm_ctrl + REG_CLR,
256 soc_data->high_alarm_mask);
257 regmap_write(map, soc_data->high_alarm_ctrl + REG_SET,
258 alarm_value << soc_data->high_alarm_shift);
37713a1e
PZ
259}
260
17e8351a 261static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
ca3de46b
SG
262{
263 struct imx_thermal_data *data = tz->devdata;
f085f672 264 const struct thermal_soc_data *soc_data = data->socdata;
ca3de46b 265 struct regmap *map = data->tempmon;
ca3de46b 266 unsigned int n_meas;
37713a1e 267 bool wait;
ca3de46b
SG
268 u32 val;
269
37713a1e
PZ
270 if (data->mode == THERMAL_DEVICE_ENABLED) {
271 /* Check if a measurement is currently in progress */
f085f672
AH
272 regmap_read(map, soc_data->temp_data, &val);
273 wait = !(val & soc_data->temp_valid_mask);
37713a1e
PZ
274 } else {
275 /*
276 * Every time we measure the temperature, we will power on the
277 * temperature sensor, enable measurements, take a reading,
278 * disable measurements, power off the temperature sensor.
279 */
f085f672
AH
280 regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
281 soc_data->power_down_mask);
282 regmap_write(map, soc_data->sensor_ctrl + REG_SET,
283 soc_data->measure_temp_mask);
37713a1e
PZ
284
285 wait = true;
286 }
ca3de46b
SG
287
288 /*
289 * According to the temp sensor designers, it may require up to ~17us
290 * to complete a measurement.
291 */
37713a1e
PZ
292 if (wait)
293 usleep_range(20, 50);
ca3de46b 294
f085f672 295 regmap_read(map, soc_data->temp_data, &val);
37713a1e
PZ
296
297 if (data->mode != THERMAL_DEVICE_ENABLED) {
f085f672
AH
298 regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
299 soc_data->measure_temp_mask);
300 regmap_write(map, soc_data->sensor_ctrl + REG_SET,
301 soc_data->power_down_mask);
37713a1e 302 }
ca3de46b 303
f085f672 304 if ((val & soc_data->temp_valid_mask) == 0) {
ca3de46b
SG
305 dev_dbg(&tz->device, "temp measurement never finished\n");
306 return -EAGAIN;
307 }
308
f085f672
AH
309 n_meas = (val & soc_data->temp_value_mask)
310 >> soc_data->temp_value_shift;
ca3de46b 311
ae621557 312 /* See imx_init_calib() for formula derivation */
f085f672
AH
313 if (data->socdata->version == TEMPMON_IMX7D)
314 *temp = (n_meas - data->c1 + 25) * 1000;
315 else
316 *temp = data->c2 - n_meas * data->c1;
ca3de46b 317
3c94f17e
AH
318 /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
319 if (data->socdata->version == TEMPMON_IMX6Q) {
320 if (data->alarm_temp == data->temp_passive &&
321 *temp >= data->temp_passive)
322 imx_set_alarm_temp(data, data->temp_critical);
323 if (data->alarm_temp == data->temp_critical &&
324 *temp < data->temp_passive) {
325 imx_set_alarm_temp(data, data->temp_passive);
17e8351a 326 dev_dbg(&tz->device, "thermal alarm off: T < %d\n",
3c94f17e
AH
327 data->alarm_temp / 1000);
328 }
37713a1e
PZ
329 }
330
331 if (*temp != data->last_temp) {
17e8351a 332 dev_dbg(&tz->device, "millicelsius: %d\n", *temp);
37713a1e
PZ
333 data->last_temp = *temp;
334 }
335
336 /* Reenable alarm IRQ if temperature below alarm temperature */
337 if (!data->irq_enabled && *temp < data->alarm_temp) {
338 data->irq_enabled = true;
339 enable_irq(data->irq);
ca3de46b
SG
340 }
341
342 return 0;
343}
344
345static int imx_get_mode(struct thermal_zone_device *tz,
346 enum thermal_device_mode *mode)
347{
348 struct imx_thermal_data *data = tz->devdata;
349
350 *mode = data->mode;
351
352 return 0;
353}
354
355static int imx_set_mode(struct thermal_zone_device *tz,
356 enum thermal_device_mode mode)
357{
358 struct imx_thermal_data *data = tz->devdata;
37713a1e 359 struct regmap *map = data->tempmon;
f085f672 360 const struct thermal_soc_data *soc_data = data->socdata;
ca3de46b
SG
361
362 if (mode == THERMAL_DEVICE_ENABLED) {
363 tz->polling_delay = IMX_POLLING_DELAY;
364 tz->passive_delay = IMX_PASSIVE_DELAY;
37713a1e 365
f085f672
AH
366 regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
367 soc_data->power_down_mask);
368 regmap_write(map, soc_data->sensor_ctrl + REG_SET,
369 soc_data->measure_temp_mask);
37713a1e
PZ
370
371 if (!data->irq_enabled) {
372 data->irq_enabled = true;
373 enable_irq(data->irq);
374 }
ca3de46b 375 } else {
f085f672
AH
376 regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
377 soc_data->measure_temp_mask);
378 regmap_write(map, soc_data->sensor_ctrl + REG_SET,
379 soc_data->power_down_mask);
37713a1e 380
ca3de46b
SG
381 tz->polling_delay = 0;
382 tz->passive_delay = 0;
37713a1e
PZ
383
384 if (data->irq_enabled) {
385 disable_irq(data->irq);
386 data->irq_enabled = false;
387 }
ca3de46b
SG
388 }
389
390 data->mode = mode;
0e70f466 391 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
ca3de46b
SG
392
393 return 0;
394}
395
396static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
397 enum thermal_trip_type *type)
398{
399 *type = (trip == IMX_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE :
400 THERMAL_TRIP_CRITICAL;
401 return 0;
402}
403
17e8351a 404static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp)
ca3de46b 405{
017e5142
PZ
406 struct imx_thermal_data *data = tz->devdata;
407
408 *temp = data->temp_critical;
ca3de46b
SG
409 return 0;
410}
411
412static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
17e8351a 413 int *temp)
ca3de46b 414{
017e5142
PZ
415 struct imx_thermal_data *data = tz->devdata;
416
417 *temp = (trip == IMX_TRIP_PASSIVE) ? data->temp_passive :
418 data->temp_critical;
419 return 0;
420}
421
422static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
17e8351a 423 int temp)
017e5142
PZ
424{
425 struct imx_thermal_data *data = tz->devdata;
426
a2291bad 427 /* do not allow changing critical threshold */
017e5142
PZ
428 if (trip == IMX_TRIP_CRITICAL)
429 return -EPERM;
430
a2291bad
TH
431 /* do not allow passive to be set higher than critical */
432 if (temp < 0 || temp > data->temp_critical)
017e5142
PZ
433 return -EINVAL;
434
435 data->temp_passive = temp;
436
37713a1e
PZ
437 imx_set_alarm_temp(data, temp);
438
ca3de46b
SG
439 return 0;
440}
441
442static int imx_bind(struct thermal_zone_device *tz,
443 struct thermal_cooling_device *cdev)
444{
445 int ret;
446
447 ret = thermal_zone_bind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev,
448 THERMAL_NO_LIMIT,
6cd9e9f6
KS
449 THERMAL_NO_LIMIT,
450 THERMAL_WEIGHT_DEFAULT);
ca3de46b
SG
451 if (ret) {
452 dev_err(&tz->device,
453 "binding zone %s with cdev %s failed:%d\n",
454 tz->type, cdev->type, ret);
455 return ret;
456 }
457
458 return 0;
459}
460
461static int imx_unbind(struct thermal_zone_device *tz,
462 struct thermal_cooling_device *cdev)
463{
464 int ret;
465
466 ret = thermal_zone_unbind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev);
467 if (ret) {
468 dev_err(&tz->device,
469 "unbinding zone %s with cdev %s failed:%d\n",
470 tz->type, cdev->type, ret);
471 return ret;
472 }
473
474 return 0;
475}
476
cbb07bb3 477static struct thermal_zone_device_ops imx_tz_ops = {
ca3de46b
SG
478 .bind = imx_bind,
479 .unbind = imx_unbind,
480 .get_temp = imx_get_temp,
481 .get_mode = imx_get_mode,
482 .set_mode = imx_set_mode,
483 .get_trip_type = imx_get_trip_type,
484 .get_trip_temp = imx_get_trip_temp,
485 .get_crit_temp = imx_get_crit_temp,
017e5142 486 .set_trip_temp = imx_set_trip_temp,
ca3de46b
SG
487};
488
e4bb2240 489static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1)
ca3de46b
SG
490{
491 struct imx_thermal_data *data = platform_get_drvdata(pdev);
4e5f61ca 492 int n1;
749e8be7 493 u64 temp64;
ca3de46b 494
e4bb2240 495 if (ocotp_ana1 == 0 || ocotp_ana1 == ~0) {
ca3de46b
SG
496 dev_err(&pdev->dev, "invalid sensor calibration data\n");
497 return -EINVAL;
498 }
499
f085f672
AH
500 /*
501 * On i.MX7D, we only use the calibration data at 25C to get the temp,
502 * Tmeas = ( Nmeas - n1) + 25; n1 is the fuse value for 25C.
503 */
504 if (data->socdata->version == TEMPMON_IMX7D) {
505 data->c1 = (ocotp_ana1 >> 9) & 0x1ff;
506 return 0;
507 }
508
ca3de46b 509 /*
c5bbdb4b
UKK
510 * The sensor is calibrated at 25 °C (aka T1) and the value measured
511 * (aka N1) at this temperature is provided in bits [31:20] in the
512 * i.MX's OCOTP value ANA1.
513 * To find the actual temperature T, the following formula has to be used
514 * when reading value n from the sensor:
515 *
4e5f61ca
UKK
516 * T = T1 + (N - N1) / (0.4148468 - 0.0015423 * N1) °C + 3.580661 °C
517 * = [T1' - N1 / (0.4148468 - 0.0015423 * N1) °C] + N / (0.4148468 - 0.0015423 * N1) °C
518 * = [T1' + N1 / (0.0015423 * N1 - 0.4148468) °C] - N / (0.0015423 * N1 - 0.4148468) °C
c5bbdb4b
UKK
519 * = c2 - c1 * N
520 *
521 * with
522 *
4e5f61ca
UKK
523 * T1' = 28.580661 °C
524 * c1 = 1 / (0.0015423 * N1 - 0.4297157) °C
525 * c2 = T1' + N1 / (0.0015423 * N1 - 0.4148468) °C
526 * = T1' + N1 * c1
ca3de46b 527 */
e4bb2240 528 n1 = ocotp_ana1 >> 20;
ca3de46b 529
4e5f61ca 530 temp64 = 10000000; /* use 10^7 as fixed point constant for values in formula */
c5bbdb4b 531 temp64 *= 1000; /* to get result in °mC */
4e5f61ca 532 do_div(temp64, 15423 * n1 - 4148468);
749e8be7 533 data->c1 = temp64;
4e5f61ca 534 data->c2 = n1 * data->c1 + 28581;
ca3de46b 535
ae621557
LC
536 return 0;
537}
538
e4bb2240 539static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0)
ae621557
LC
540{
541 struct imx_thermal_data *data = platform_get_drvdata(pdev);
a2291bad
TH
542
543 /* The maximum die temp is specified by the Temperature Grade */
e4bb2240 544 switch ((ocotp_mem0 >> 6) & 0x3) {
339d7492 545 case 0: /* Commercial (0 to 95 °C) */
a2291bad
TH
546 data->temp_grade = "Commercial";
547 data->temp_max = 95000;
548 break;
339d7492 549 case 1: /* Extended Commercial (-20 °C to 105 °C) */
a2291bad
TH
550 data->temp_grade = "Extended Commercial";
551 data->temp_max = 105000;
552 break;
339d7492 553 case 2: /* Industrial (-40 °C to 105 °C) */
a2291bad
TH
554 data->temp_grade = "Industrial";
555 data->temp_max = 105000;
556 break;
339d7492 557 case 3: /* Automotive (-40 °C to 125 °C) */
a2291bad
TH
558 data->temp_grade = "Automotive";
559 data->temp_max = 125000;
560 break;
561 }
017e5142
PZ
562
563 /*
339d7492
UKK
564 * Set the critical trip point at 5 °C under max
565 * Set the passive trip point at 10 °C under max (changeable via sysfs)
017e5142 566 */
a2291bad
TH
567 data->temp_critical = data->temp_max - (1000 * 5);
568 data->temp_passive = data->temp_max - (1000 * 10);
ae621557
LC
569}
570
571static int imx_init_from_tempmon_data(struct platform_device *pdev)
572{
573 struct regmap *map;
574 int ret;
575 u32 val;
576
577 map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
578 "fsl,tempmon-data");
579 if (IS_ERR(map)) {
580 ret = PTR_ERR(map);
581 dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
582 return ret;
583 }
584
585 ret = regmap_read(map, OCOTP_ANA1, &val);
586 if (ret) {
587 dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
588 return ret;
589 }
590 ret = imx_init_calib(pdev, val);
591 if (ret)
592 return ret;
593
594 ret = regmap_read(map, OCOTP_MEM0, &val);
595 if (ret) {
596 dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
597 return ret;
598 }
599 imx_init_temp_grade(pdev, val);
600
601 return 0;
602}
603
604static int imx_init_from_nvmem_cells(struct platform_device *pdev)
605{
606 int ret;
607 u32 val;
608
609 ret = nvmem_cell_read_u32(&pdev->dev, "calib", &val);
610 if (ret)
611 return ret;
612 imx_init_calib(pdev, val);
613
614 ret = nvmem_cell_read_u32(&pdev->dev, "temp_grade", &val);
615 if (ret)
616 return ret;
617 imx_init_temp_grade(pdev, val);
017e5142 618
ca3de46b
SG
619 return 0;
620}
621
37713a1e
PZ
622static irqreturn_t imx_thermal_alarm_irq(int irq, void *dev)
623{
624 struct imx_thermal_data *data = dev;
625
626 disable_irq_nosync(irq);
627 data->irq_enabled = false;
628
629 return IRQ_WAKE_THREAD;
630}
631
632static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
633{
634 struct imx_thermal_data *data = dev;
635
17e8351a 636 dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n",
37713a1e
PZ
637 data->alarm_temp / 1000);
638
0e70f466 639 thermal_zone_device_update(data->tz, THERMAL_EVENT_UNSPECIFIED);
37713a1e
PZ
640
641 return IRQ_HANDLED;
642}
643
3c94f17e
AH
644static const struct of_device_id of_imx_thermal_match[] = {
645 { .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },
646 { .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },
f085f672 647 { .compatible = "fsl,imx7d-tempmon", .data = &thermal_imx7d_data, },
3c94f17e
AH
648 { /* end */ }
649};
650MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
651
ca3de46b
SG
652static int imx_thermal_probe(struct platform_device *pdev)
653{
654 struct imx_thermal_data *data;
ca3de46b 655 struct regmap *map;
37713a1e 656 int measure_freq;
ca3de46b
SG
657 int ret;
658
659 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
660 if (!data)
661 return -ENOMEM;
662
663 map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
664 if (IS_ERR(map)) {
665 ret = PTR_ERR(map);
666 dev_err(&pdev->dev, "failed to get tempmon regmap: %d\n", ret);
667 return ret;
668 }
669 data->tempmon = map;
670
829bc78a 671 data->socdata = of_device_get_match_data(&pdev->dev);
8b051ec3
SV
672 if (!data->socdata) {
673 dev_err(&pdev->dev, "no device match found\n");
674 return -ENODEV;
675 }
3c94f17e
AH
676
677 /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
678 if (data->socdata->version == TEMPMON_IMX6SX) {
f085f672
AH
679 regmap_write(map, IMX6_MISC1 + REG_CLR,
680 IMX6_MISC1_IRQ_TEMPHIGH | IMX6_MISC1_IRQ_TEMPLOW
681 | IMX6_MISC1_IRQ_TEMPPANIC);
3c94f17e
AH
682 /*
683 * reset value of LOW ALARM is incorrect, set it to lowest
684 * value to avoid false trigger of low alarm.
685 */
f085f672
AH
686 regmap_write(map, data->socdata->low_alarm_ctrl + REG_SET,
687 data->socdata->low_alarm_mask);
3c94f17e
AH
688 }
689
37713a1e
PZ
690 data->irq = platform_get_irq(pdev, 0);
691 if (data->irq < 0)
692 return data->irq;
693
ca3de46b
SG
694 platform_set_drvdata(pdev, data);
695
ae621557
LC
696 if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) {
697 ret = imx_init_from_nvmem_cells(pdev);
698 if (ret == -EPROBE_DEFER)
699 return ret;
700 if (ret) {
701 dev_err(&pdev->dev, "failed to init from nvmem: %d\n",
702 ret);
703 return ret;
704 }
705 } else {
706 ret = imx_init_from_tempmon_data(pdev);
707 if (ret) {
708 dev_err(&pdev->dev, "failed to init from from fsl,tempmon-data\n");
709 return ret;
710 }
ca3de46b
SG
711 }
712
713 /* Make sure sensor is in known good state for measurements */
f085f672
AH
714 regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
715 data->socdata->power_down_mask);
716 regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
717 data->socdata->measure_temp_mask);
718 regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
719 data->socdata->measure_freq_mask);
720 if (data->socdata->version != TEMPMON_IMX7D)
721 regmap_write(map, IMX6_MISC0 + REG_SET,
722 IMX6_MISC0_REFTOP_SELBIASOFF);
723 regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
724 data->socdata->power_down_mask);
ca3de46b 725
4d753aa7
VK
726 data->policy = cpufreq_cpu_get(0);
727 if (!data->policy) {
728 pr_debug("%s: CPUFreq policy not found\n", __func__);
729 return -EPROBE_DEFER;
730 }
731
732 data->cdev = cpufreq_cooling_register(data->policy);
ca3de46b
SG
733 if (IS_ERR(data->cdev)) {
734 ret = PTR_ERR(data->cdev);
4d753aa7
VK
735 dev_err(&pdev->dev,
736 "failed to register cpufreq cooling device: %d\n", ret);
737 cpufreq_cpu_put(data->policy);
ca3de46b
SG
738 return ret;
739 }
740
90a21ff5
HK
741 data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
742 if (IS_ERR(data->thermal_clk)) {
743 ret = PTR_ERR(data->thermal_clk);
744 if (ret != -EPROBE_DEFER)
745 dev_err(&pdev->dev,
746 "failed to get thermal clk: %d\n", ret);
747 cpufreq_cooling_unregister(data->cdev);
4d753aa7 748 cpufreq_cpu_put(data->policy);
90a21ff5
HK
749 return ret;
750 }
751
752 /*
753 * Thermal sensor needs clk on to get correct value, normally
754 * we should enable its clk before taking measurement and disable
755 * clk after measurement is done, but if alarm function is enabled,
756 * hardware will auto measure the temperature periodically, so we
757 * need to keep the clk always on for alarm function.
758 */
759 ret = clk_prepare_enable(data->thermal_clk);
760 if (ret) {
761 dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
762 cpufreq_cooling_unregister(data->cdev);
4d753aa7 763 cpufreq_cpu_put(data->policy);
90a21ff5
HK
764 return ret;
765 }
766
ca3de46b 767 data->tz = thermal_zone_device_register("imx_thermal_zone",
017e5142
PZ
768 IMX_TRIP_NUM,
769 BIT(IMX_TRIP_PASSIVE), data,
ca3de46b
SG
770 &imx_tz_ops, NULL,
771 IMX_PASSIVE_DELAY,
772 IMX_POLLING_DELAY);
773 if (IS_ERR(data->tz)) {
774 ret = PTR_ERR(data->tz);
775 dev_err(&pdev->dev,
776 "failed to register thermal zone device %d\n", ret);
90a21ff5 777 clk_disable_unprepare(data->thermal_clk);
ca3de46b 778 cpufreq_cooling_unregister(data->cdev);
4d753aa7 779 cpufreq_cpu_put(data->policy);
ca3de46b
SG
780 return ret;
781 }
782
a2291bad
TH
783 dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC"
784 " critical:%dC passive:%dC\n", data->temp_grade,
785 data->temp_max / 1000, data->temp_critical / 1000,
786 data->temp_passive / 1000);
787
37713a1e 788 /* Enable measurements at ~ 10 Hz */
f085f672
AH
789 regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
790 data->socdata->measure_freq_mask);
37713a1e 791 measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
f085f672
AH
792 regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET,
793 measure_freq << data->socdata->measure_freq_shift);
37713a1e 794 imx_set_alarm_temp(data, data->temp_passive);
3c94f17e
AH
795
796 if (data->socdata->version == TEMPMON_IMX6SX)
797 imx_set_panic_temp(data, data->temp_critical);
798
f085f672
AH
799 regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
800 data->socdata->power_down_mask);
801 regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
802 data->socdata->measure_temp_mask);
37713a1e 803
cf1ba1d7
ML
804 data->irq_enabled = true;
805 data->mode = THERMAL_DEVICE_ENABLED;
806
84866ee5
BP
807 ret = devm_request_threaded_irq(&pdev->dev, data->irq,
808 imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
809 0, "imx_thermal", data);
810 if (ret < 0) {
811 dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
812 clk_disable_unprepare(data->thermal_clk);
813 thermal_zone_device_unregister(data->tz);
814 cpufreq_cooling_unregister(data->cdev);
4d753aa7 815 cpufreq_cpu_put(data->policy);
84866ee5
BP
816 return ret;
817 }
818
ca3de46b
SG
819 return 0;
820}
821
822static int imx_thermal_remove(struct platform_device *pdev)
823{
824 struct imx_thermal_data *data = platform_get_drvdata(pdev);
37713a1e
PZ
825 struct regmap *map = data->tempmon;
826
827 /* Disable measurements */
f085f672
AH
828 regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
829 data->socdata->power_down_mask);
329fe7b1
AH
830 if (!IS_ERR(data->thermal_clk))
831 clk_disable_unprepare(data->thermal_clk);
ca3de46b
SG
832
833 thermal_zone_device_unregister(data->tz);
834 cpufreq_cooling_unregister(data->cdev);
4d753aa7 835 cpufreq_cpu_put(data->policy);
ca3de46b
SG
836
837 return 0;
838}
839
840#ifdef CONFIG_PM_SLEEP
841static int imx_thermal_suspend(struct device *dev)
842{
843 struct imx_thermal_data *data = dev_get_drvdata(dev);
844 struct regmap *map = data->tempmon;
ca3de46b 845
b46cce59
AH
846 /*
847 * Need to disable thermal sensor, otherwise, when thermal core
848 * try to get temperature before thermal sensor resume, a wrong
849 * temperature will be read as the thermal sensor is powered
850 * down.
851 */
f085f672
AH
852 regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
853 data->socdata->measure_temp_mask);
854 regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
855 data->socdata->power_down_mask);
b46cce59 856 data->mode = THERMAL_DEVICE_DISABLED;
d26eef8b 857 clk_disable_unprepare(data->thermal_clk);
ca3de46b
SG
858
859 return 0;
860}
861
862static int imx_thermal_resume(struct device *dev)
863{
b46cce59
AH
864 struct imx_thermal_data *data = dev_get_drvdata(dev);
865 struct regmap *map = data->tempmon;
e3bdc8d7 866 int ret;
b46cce59 867
e3bdc8d7
AY
868 ret = clk_prepare_enable(data->thermal_clk);
869 if (ret)
870 return ret;
b46cce59 871 /* Enabled thermal sensor after resume */
f085f672
AH
872 regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
873 data->socdata->power_down_mask);
874 regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
875 data->socdata->measure_temp_mask);
b46cce59
AH
876 data->mode = THERMAL_DEVICE_ENABLED;
877
ca3de46b
SG
878 return 0;
879}
880#endif
881
882static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
883 imx_thermal_suspend, imx_thermal_resume);
884
ca3de46b
SG
885static struct platform_driver imx_thermal = {
886 .driver = {
887 .name = "imx_thermal",
ca3de46b
SG
888 .pm = &imx_thermal_pm_ops,
889 .of_match_table = of_imx_thermal_match,
890 },
891 .probe = imx_thermal_probe,
892 .remove = imx_thermal_remove,
893};
894module_platform_driver(imx_thermal);
895
896MODULE_AUTHOR("Freescale Semiconductor, Inc.");
897MODULE_DESCRIPTION("Thermal driver for Freescale i.MX SoCs");
898MODULE_LICENSE("GPL v2");
899MODULE_ALIAS("platform:imx-thermal");