xref: /openbmc/linux/drivers/thermal/imx_thermal.c (revision 5f32c314)
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 
10 #include <linux/clk.h>
11 #include <linux/cpu_cooling.h>
12 #include <linux/cpufreq.h>
13 #include <linux/delay.h>
14 #include <linux/device.h>
15 #include <linux/init.h>
16 #include <linux/interrupt.h>
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>
22 #include <linux/platform_device.h>
23 #include <linux/regmap.h>
24 #include <linux/slab.h>
25 #include <linux/thermal.h>
26 #include <linux/types.h>
27 
28 #define REG_SET		0x4
29 #define REG_CLR		0x8
30 #define REG_TOG		0xc
31 
32 #define MISC0				0x0150
33 #define MISC0_REFTOP_SELBIASOFF		(1 << 3)
34 
35 #define TEMPSENSE0			0x0180
36 #define TEMPSENSE0_ALARM_VALUE_SHIFT	20
37 #define TEMPSENSE0_ALARM_VALUE_MASK	(0xfff << TEMPSENSE0_ALARM_VALUE_SHIFT)
38 #define TEMPSENSE0_TEMP_CNT_SHIFT	8
39 #define TEMPSENSE0_TEMP_CNT_MASK	(0xfff << TEMPSENSE0_TEMP_CNT_SHIFT)
40 #define TEMPSENSE0_FINISHED		(1 << 2)
41 #define TEMPSENSE0_MEASURE_TEMP		(1 << 1)
42 #define TEMPSENSE0_POWER_DOWN		(1 << 0)
43 
44 #define TEMPSENSE1			0x0190
45 #define TEMPSENSE1_MEASURE_FREQ		0xffff
46 
47 #define OCOTP_ANA1			0x04e0
48 
49 /* The driver supports 1 passive trip point and 1 critical trip point */
50 enum imx_thermal_trip {
51 	IMX_TRIP_PASSIVE,
52 	IMX_TRIP_CRITICAL,
53 	IMX_TRIP_NUM,
54 };
55 
56 /*
57  * It defines the temperature in millicelsius for passive trip point
58  * that will trigger cooling action when crossed.
59  */
60 #define IMX_TEMP_PASSIVE		85000
61 
62 #define IMX_POLLING_DELAY		2000 /* millisecond */
63 #define IMX_PASSIVE_DELAY		1000
64 
65 struct imx_thermal_data {
66 	struct thermal_zone_device *tz;
67 	struct thermal_cooling_device *cdev;
68 	enum thermal_device_mode mode;
69 	struct regmap *tempmon;
70 	int c1, c2; /* See formula in imx_get_sensor_data() */
71 	unsigned long temp_passive;
72 	unsigned long temp_critical;
73 	unsigned long alarm_temp;
74 	unsigned long last_temp;
75 	bool irq_enabled;
76 	int irq;
77 	struct clk *thermal_clk;
78 };
79 
80 static void imx_set_alarm_temp(struct imx_thermal_data *data,
81 			       signed long alarm_temp)
82 {
83 	struct regmap *map = data->tempmon;
84 	int alarm_value;
85 
86 	data->alarm_temp = alarm_temp;
87 	alarm_value = (alarm_temp - data->c2) / data->c1;
88 	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK);
89 	regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value <<
90 			TEMPSENSE0_ALARM_VALUE_SHIFT);
91 }
92 
93 static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
94 {
95 	struct imx_thermal_data *data = tz->devdata;
96 	struct regmap *map = data->tempmon;
97 	unsigned int n_meas;
98 	bool wait;
99 	u32 val;
100 
101 	if (data->mode == THERMAL_DEVICE_ENABLED) {
102 		/* Check if a measurement is currently in progress */
103 		regmap_read(map, TEMPSENSE0, &val);
104 		wait = !(val & TEMPSENSE0_FINISHED);
105 	} else {
106 		/*
107 		 * Every time we measure the temperature, we will power on the
108 		 * temperature sensor, enable measurements, take a reading,
109 		 * disable measurements, power off the temperature sensor.
110 		 */
111 		regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
112 		regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
113 
114 		wait = true;
115 	}
116 
117 	/*
118 	 * According to the temp sensor designers, it may require up to ~17us
119 	 * to complete a measurement.
120 	 */
121 	if (wait)
122 		usleep_range(20, 50);
123 
124 	regmap_read(map, TEMPSENSE0, &val);
125 
126 	if (data->mode != THERMAL_DEVICE_ENABLED) {
127 		regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
128 		regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
129 	}
130 
131 	if ((val & TEMPSENSE0_FINISHED) == 0) {
132 		dev_dbg(&tz->device, "temp measurement never finished\n");
133 		return -EAGAIN;
134 	}
135 
136 	n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
137 
138 	/* See imx_get_sensor_data() for formula derivation */
139 	*temp = data->c2 + data->c1 * n_meas;
140 
141 	/* Update alarm value to next higher trip point */
142 	if (data->alarm_temp == data->temp_passive && *temp >= data->temp_passive)
143 		imx_set_alarm_temp(data, data->temp_critical);
144 	if (data->alarm_temp == data->temp_critical && *temp < data->temp_passive) {
145 		imx_set_alarm_temp(data, data->temp_passive);
146 		dev_dbg(&tz->device, "thermal alarm off: T < %lu\n",
147 			data->alarm_temp / 1000);
148 	}
149 
150 	if (*temp != data->last_temp) {
151 		dev_dbg(&tz->device, "millicelsius: %ld\n", *temp);
152 		data->last_temp = *temp;
153 	}
154 
155 	/* Reenable alarm IRQ if temperature below alarm temperature */
156 	if (!data->irq_enabled && *temp < data->alarm_temp) {
157 		data->irq_enabled = true;
158 		enable_irq(data->irq);
159 	}
160 
161 	return 0;
162 }
163 
164 static int imx_get_mode(struct thermal_zone_device *tz,
165 			enum thermal_device_mode *mode)
166 {
167 	struct imx_thermal_data *data = tz->devdata;
168 
169 	*mode = data->mode;
170 
171 	return 0;
172 }
173 
174 static int imx_set_mode(struct thermal_zone_device *tz,
175 			enum thermal_device_mode mode)
176 {
177 	struct imx_thermal_data *data = tz->devdata;
178 	struct regmap *map = data->tempmon;
179 
180 	if (mode == THERMAL_DEVICE_ENABLED) {
181 		tz->polling_delay = IMX_POLLING_DELAY;
182 		tz->passive_delay = IMX_PASSIVE_DELAY;
183 
184 		regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
185 		regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
186 
187 		if (!data->irq_enabled) {
188 			data->irq_enabled = true;
189 			enable_irq(data->irq);
190 		}
191 	} else {
192 		regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
193 		regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
194 
195 		tz->polling_delay = 0;
196 		tz->passive_delay = 0;
197 
198 		if (data->irq_enabled) {
199 			disable_irq(data->irq);
200 			data->irq_enabled = false;
201 		}
202 	}
203 
204 	data->mode = mode;
205 	thermal_zone_device_update(tz);
206 
207 	return 0;
208 }
209 
210 static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
211 			     enum thermal_trip_type *type)
212 {
213 	*type = (trip == IMX_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE :
214 					     THERMAL_TRIP_CRITICAL;
215 	return 0;
216 }
217 
218 static int imx_get_crit_temp(struct thermal_zone_device *tz,
219 			     unsigned long *temp)
220 {
221 	struct imx_thermal_data *data = tz->devdata;
222 
223 	*temp = data->temp_critical;
224 	return 0;
225 }
226 
227 static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
228 			     unsigned long *temp)
229 {
230 	struct imx_thermal_data *data = tz->devdata;
231 
232 	*temp = (trip == IMX_TRIP_PASSIVE) ? data->temp_passive :
233 					     data->temp_critical;
234 	return 0;
235 }
236 
237 static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
238 			     unsigned long temp)
239 {
240 	struct imx_thermal_data *data = tz->devdata;
241 
242 	if (trip == IMX_TRIP_CRITICAL)
243 		return -EPERM;
244 
245 	if (temp > IMX_TEMP_PASSIVE)
246 		return -EINVAL;
247 
248 	data->temp_passive = temp;
249 
250 	imx_set_alarm_temp(data, temp);
251 
252 	return 0;
253 }
254 
255 static int imx_bind(struct thermal_zone_device *tz,
256 		    struct thermal_cooling_device *cdev)
257 {
258 	int ret;
259 
260 	ret = thermal_zone_bind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev,
261 					       THERMAL_NO_LIMIT,
262 					       THERMAL_NO_LIMIT);
263 	if (ret) {
264 		dev_err(&tz->device,
265 			"binding zone %s with cdev %s failed:%d\n",
266 			tz->type, cdev->type, ret);
267 		return ret;
268 	}
269 
270 	return 0;
271 }
272 
273 static int imx_unbind(struct thermal_zone_device *tz,
274 		      struct thermal_cooling_device *cdev)
275 {
276 	int ret;
277 
278 	ret = thermal_zone_unbind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev);
279 	if (ret) {
280 		dev_err(&tz->device,
281 			"unbinding zone %s with cdev %s failed:%d\n",
282 			tz->type, cdev->type, ret);
283 		return ret;
284 	}
285 
286 	return 0;
287 }
288 
289 static struct thermal_zone_device_ops imx_tz_ops = {
290 	.bind = imx_bind,
291 	.unbind = imx_unbind,
292 	.get_temp = imx_get_temp,
293 	.get_mode = imx_get_mode,
294 	.set_mode = imx_set_mode,
295 	.get_trip_type = imx_get_trip_type,
296 	.get_trip_temp = imx_get_trip_temp,
297 	.get_crit_temp = imx_get_crit_temp,
298 	.set_trip_temp = imx_set_trip_temp,
299 };
300 
301 static int imx_get_sensor_data(struct platform_device *pdev)
302 {
303 	struct imx_thermal_data *data = platform_get_drvdata(pdev);
304 	struct regmap *map;
305 	int t1, t2, n1, n2;
306 	int ret;
307 	u32 val;
308 
309 	map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
310 					      "fsl,tempmon-data");
311 	if (IS_ERR(map)) {
312 		ret = PTR_ERR(map);
313 		dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
314 		return ret;
315 	}
316 
317 	ret = regmap_read(map, OCOTP_ANA1, &val);
318 	if (ret) {
319 		dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
320 		return ret;
321 	}
322 
323 	if (val == 0 || val == ~0) {
324 		dev_err(&pdev->dev, "invalid sensor calibration data\n");
325 		return -EINVAL;
326 	}
327 
328 	/*
329 	 * Sensor data layout:
330 	 *   [31:20] - sensor value @ 25C
331 	 *    [19:8] - sensor value of hot
332 	 *     [7:0] - hot temperature value
333 	 */
334 	n1 = val >> 20;
335 	n2 = (val & 0xfff00) >> 8;
336 	t2 = val & 0xff;
337 	t1 = 25; /* t1 always 25C */
338 
339 	/*
340 	 * Derived from linear interpolation,
341 	 * Tmeas = T2 + (Nmeas - N2) * (T1 - T2) / (N1 - N2)
342 	 * We want to reduce this down to the minimum computation necessary
343 	 * for each temperature read.  Also, we want Tmeas in millicelsius
344 	 * and we don't want to lose precision from integer division. So...
345 	 * milli_Tmeas = 1000 * T2 + 1000 * (Nmeas - N2) * (T1 - T2) / (N1 - N2)
346 	 * Let constant c1 = 1000 * (T1 - T2) / (N1 - N2)
347 	 * milli_Tmeas = (1000 * T2) + c1 * (Nmeas - N2)
348 	 * milli_Tmeas = (1000 * T2) + (c1 * Nmeas) - (c1 * N2)
349 	 * Let constant c2 = (1000 * T2) - (c1 * N2)
350 	 * milli_Tmeas = c2 + (c1 * Nmeas)
351 	 */
352 	data->c1 = 1000 * (t1 - t2) / (n1 - n2);
353 	data->c2 = 1000 * t2 - data->c1 * n2;
354 
355 	/*
356 	 * Set the default passive cooling trip point to 20 °C below the
357 	 * maximum die temperature. Can be changed from userspace.
358 	 */
359 	data->temp_passive = 1000 * (t2 - 20);
360 
361 	/*
362 	 * The maximum die temperature is t2, let's give 5 °C cushion
363 	 * for noise and possible temperature rise between measurements.
364 	 */
365 	data->temp_critical = 1000 * (t2 - 5);
366 
367 	return 0;
368 }
369 
370 static irqreturn_t imx_thermal_alarm_irq(int irq, void *dev)
371 {
372 	struct imx_thermal_data *data = dev;
373 
374 	disable_irq_nosync(irq);
375 	data->irq_enabled = false;
376 
377 	return IRQ_WAKE_THREAD;
378 }
379 
380 static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
381 {
382 	struct imx_thermal_data *data = dev;
383 
384 	dev_dbg(&data->tz->device, "THERMAL ALARM: T > %lu\n",
385 		data->alarm_temp / 1000);
386 
387 	thermal_zone_device_update(data->tz);
388 
389 	return IRQ_HANDLED;
390 }
391 
392 static int imx_thermal_probe(struct platform_device *pdev)
393 {
394 	struct imx_thermal_data *data;
395 	struct cpumask clip_cpus;
396 	struct regmap *map;
397 	int measure_freq;
398 	int ret;
399 
400 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
401 	if (!data)
402 		return -ENOMEM;
403 
404 	map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
405 	if (IS_ERR(map)) {
406 		ret = PTR_ERR(map);
407 		dev_err(&pdev->dev, "failed to get tempmon regmap: %d\n", ret);
408 		return ret;
409 	}
410 	data->tempmon = map;
411 
412 	data->irq = platform_get_irq(pdev, 0);
413 	if (data->irq < 0)
414 		return data->irq;
415 
416 	ret = devm_request_threaded_irq(&pdev->dev, data->irq,
417 			imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
418 			0, "imx_thermal", data);
419 	if (ret < 0) {
420 		dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
421 		return ret;
422 	}
423 
424 	platform_set_drvdata(pdev, data);
425 
426 	ret = imx_get_sensor_data(pdev);
427 	if (ret) {
428 		dev_err(&pdev->dev, "failed to get sensor data\n");
429 		return ret;
430 	}
431 
432 	/* Make sure sensor is in known good state for measurements */
433 	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
434 	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
435 	regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
436 	regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
437 	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
438 
439 	cpumask_set_cpu(0, &clip_cpus);
440 	data->cdev = cpufreq_cooling_register(&clip_cpus);
441 	if (IS_ERR(data->cdev)) {
442 		ret = PTR_ERR(data->cdev);
443 		dev_err(&pdev->dev,
444 			"failed to register cpufreq cooling device: %d\n", ret);
445 		return ret;
446 	}
447 
448 	data->tz = thermal_zone_device_register("imx_thermal_zone",
449 						IMX_TRIP_NUM,
450 						BIT(IMX_TRIP_PASSIVE), data,
451 						&imx_tz_ops, NULL,
452 						IMX_PASSIVE_DELAY,
453 						IMX_POLLING_DELAY);
454 	if (IS_ERR(data->tz)) {
455 		ret = PTR_ERR(data->tz);
456 		dev_err(&pdev->dev,
457 			"failed to register thermal zone device %d\n", ret);
458 		cpufreq_cooling_unregister(data->cdev);
459 		return ret;
460 	}
461 
462 	data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
463 	if (IS_ERR(data->thermal_clk)) {
464 		dev_warn(&pdev->dev, "failed to get thermal clk!\n");
465 	} else {
466 		/*
467 		 * Thermal sensor needs clk on to get correct value, normally
468 		 * we should enable its clk before taking measurement and disable
469 		 * clk after measurement is done, but if alarm function is enabled,
470 		 * hardware will auto measure the temperature periodically, so we
471 		 * need to keep the clk always on for alarm function.
472 		 */
473 		ret = clk_prepare_enable(data->thermal_clk);
474 		if (ret)
475 			dev_warn(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
476 	}
477 
478 	/* Enable measurements at ~ 10 Hz */
479 	regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
480 	measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
481 	regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
482 	imx_set_alarm_temp(data, data->temp_passive);
483 	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
484 	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
485 
486 	data->irq_enabled = true;
487 	data->mode = THERMAL_DEVICE_ENABLED;
488 
489 	return 0;
490 }
491 
492 static int imx_thermal_remove(struct platform_device *pdev)
493 {
494 	struct imx_thermal_data *data = platform_get_drvdata(pdev);
495 	struct regmap *map = data->tempmon;
496 
497 	/* Disable measurements */
498 	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
499 	if (!IS_ERR(data->thermal_clk))
500 		clk_disable_unprepare(data->thermal_clk);
501 
502 	thermal_zone_device_unregister(data->tz);
503 	cpufreq_cooling_unregister(data->cdev);
504 
505 	return 0;
506 }
507 
508 #ifdef CONFIG_PM_SLEEP
509 static int imx_thermal_suspend(struct device *dev)
510 {
511 	struct imx_thermal_data *data = dev_get_drvdata(dev);
512 	struct regmap *map = data->tempmon;
513 
514 	/*
515 	 * Need to disable thermal sensor, otherwise, when thermal core
516 	 * try to get temperature before thermal sensor resume, a wrong
517 	 * temperature will be read as the thermal sensor is powered
518 	 * down.
519 	 */
520 	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
521 	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
522 	data->mode = THERMAL_DEVICE_DISABLED;
523 
524 	return 0;
525 }
526 
527 static int imx_thermal_resume(struct device *dev)
528 {
529 	struct imx_thermal_data *data = dev_get_drvdata(dev);
530 	struct regmap *map = data->tempmon;
531 
532 	/* Enabled thermal sensor after resume */
533 	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
534 	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
535 	data->mode = THERMAL_DEVICE_ENABLED;
536 
537 	return 0;
538 }
539 #endif
540 
541 static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
542 			 imx_thermal_suspend, imx_thermal_resume);
543 
544 static const struct of_device_id of_imx_thermal_match[] = {
545 	{ .compatible = "fsl,imx6q-tempmon", },
546 	{ /* end */ }
547 };
548 MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
549 
550 static struct platform_driver imx_thermal = {
551 	.driver = {
552 		.name	= "imx_thermal",
553 		.owner  = THIS_MODULE,
554 		.pm	= &imx_thermal_pm_ops,
555 		.of_match_table = of_imx_thermal_match,
556 	},
557 	.probe		= imx_thermal_probe,
558 	.remove		= imx_thermal_remove,
559 };
560 module_platform_driver(imx_thermal);
561 
562 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
563 MODULE_DESCRIPTION("Thermal driver for Freescale i.MX SoCs");
564 MODULE_LICENSE("GPL v2");
565 MODULE_ALIAS("platform:imx-thermal");
566