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