Commit 749e8be71d6126b9219f17230e6d0c3eef5191a7

Authored by Anson Huang
Committed by Zhang Rui
1 parent 455c6fdbd2

thermal: imx: update formula for thermal sensor

Thermal sensor used to need two calibration points which are
in fuse map to get a slope for converting thermal sensor's raw
data to real temperature in degree C. Due to the chip calibration
limitation, hardware team provides an universal formula to get
real temperature from internal thermal sensor raw data:

Slope = 0.4297157 - (0.0015976 * 25C fuse);

Update the formula, as there will be no hot point calibration
data in fuse map from now on.

Signed-off-by: Anson Huang <b20788@freescale.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>

Showing 1 changed file with 26 additions and 13 deletions Side-by-side Diff

drivers/thermal/imx_thermal.c
... ... @@ -62,12 +62,16 @@
62 62 #define IMX_POLLING_DELAY 2000 /* millisecond */
63 63 #define IMX_PASSIVE_DELAY 1000
64 64  
  65 +#define FACTOR0 10000000
  66 +#define FACTOR1 15976
  67 +#define FACTOR2 4297157
  68 +
65 69 struct imx_thermal_data {
66 70 struct thermal_zone_device *tz;
67 71 struct thermal_cooling_device *cdev;
68 72 enum thermal_device_mode mode;
69 73 struct regmap *tempmon;
70   - int c1, c2; /* See formula in imx_get_sensor_data() */
  74 + u32 c1, c2; /* See formula in imx_get_sensor_data() */
71 75 unsigned long temp_passive;
72 76 unsigned long temp_critical;
73 77 unsigned long alarm_temp;
... ... @@ -84,7 +88,7 @@
84 88 int alarm_value;
85 89  
86 90 data->alarm_temp = alarm_temp;
87   - alarm_value = (alarm_temp - data->c2) / data->c1;
  91 + alarm_value = (data->c2 - alarm_temp) / data->c1;
88 92 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK);
89 93 regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value <<
90 94 TEMPSENSE0_ALARM_VALUE_SHIFT);
... ... @@ -136,7 +140,7 @@
136 140 n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
137 141  
138 142 /* See imx_get_sensor_data() for formula derivation */
139   - *temp = data->c2 + data->c1 * n_meas;
  143 + *temp = data->c2 - n_meas * data->c1;
140 144  
141 145 /* Update alarm value to next higher trip point */
142 146 if (data->alarm_temp == data->temp_passive && *temp >= data->temp_passive)
... ... @@ -305,6 +309,7 @@
305 309 int t1, t2, n1, n2;
306 310 int ret;
307 311 u32 val;
  312 + u64 temp64;
308 313  
309 314 map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
310 315 "fsl,tempmon-data");
... ... @@ -330,6 +335,8 @@
330 335 * [31:20] - sensor value @ 25C
331 336 * [19:8] - sensor value of hot
332 337 * [7:0] - hot temperature value
  338 + * Use universal formula now and only need sensor value @ 25C
  339 + * slope = 0.4297157 - (0.0015976 * 25C fuse)
333 340 */
334 341 n1 = val >> 20;
335 342 n2 = (val & 0xfff00) >> 8;
336 343  
337 344  
... ... @@ -337,20 +344,26 @@
337 344 t1 = 25; /* t1 always 25C */
338 345  
339 346 /*
340   - * Derived from linear interpolation,
341   - * Tmeas = T2 + (Nmeas - N2) * (T1 - T2) / (N1 - N2)
  347 + * Derived from linear interpolation:
  348 + * slope = 0.4297157 - (0.0015976 * 25C fuse)
  349 + * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0
  350 + * (Nmeas - n1) / (Tmeas - t1) = slope
342 351 * We want to reduce this down to the minimum computation necessary
343 352 * for each temperature read. Also, we want Tmeas in millicelsius
344 353 * 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)
  354 + * Tmeas = (Nmeas - n1) / slope + t1
  355 + * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1
  356 + * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1
  357 + * Let constant c1 = (-1000 / slope)
  358 + * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1
  359 + * Let constant c2 = n1 *c1 + 1000 * t1
  360 + * milli_Tmeas = c2 - Nmeas * c1
351 361 */
352   - data->c1 = 1000 * (t1 - t2) / (n1 - n2);
353   - data->c2 = 1000 * t2 - data->c1 * n2;
  362 + temp64 = FACTOR0;
  363 + temp64 *= 1000;
  364 + do_div(temp64, FACTOR1 * n1 - FACTOR2);
  365 + data->c1 = temp64;
  366 + data->c2 = n1 * data->c1 + 1000 * t1;
354 367  
355 368 /*
356 369 * Set the default passive cooling trip point to 20 °C below the