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