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