root/drivers/thermal/imx_thermal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. imx_set_panic_temp
  2. imx_set_alarm_temp
  3. imx_get_temp
  4. imx_get_mode
  5. imx_set_mode
  6. imx_get_trip_type
  7. imx_get_crit_temp
  8. imx_get_trip_temp
  9. imx_set_trip_temp
  10. imx_bind
  11. imx_unbind
  12. imx_init_calib
  13. imx_init_temp_grade
  14. imx_init_from_tempmon_data
  15. imx_init_from_nvmem_cells
  16. imx_thermal_alarm_irq
  17. imx_thermal_alarm_irq_thread
  18. imx_thermal_register_legacy_cooling
  19. imx_thermal_unregister_legacy_cooling
  20. imx_thermal_register_legacy_cooling
  21. imx_thermal_unregister_legacy_cooling
  22. imx_thermal_probe
  23. imx_thermal_remove
  24. imx_thermal_suspend
  25. imx_thermal_resume

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

/* [<][>][^][v][top][bottom][index][help] */