aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal/imx_thermal.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thermal/imx_thermal.c')
-rw-r--r--drivers/thermal/imx_thermal.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 45af765a3198..a99c63152b8d 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -62,12 +62,16 @@ enum imx_thermal_trip {
62#define IMX_POLLING_DELAY 2000 /* millisecond */ 62#define IMX_POLLING_DELAY 2000 /* millisecond */
63#define IMX_PASSIVE_DELAY 1000 63#define IMX_PASSIVE_DELAY 1000
64 64
65#define FACTOR0 10000000
66#define FACTOR1 15976
67#define FACTOR2 4297157
68
65struct imx_thermal_data { 69struct imx_thermal_data {
66 struct thermal_zone_device *tz; 70 struct thermal_zone_device *tz;
67 struct thermal_cooling_device *cdev; 71 struct thermal_cooling_device *cdev;
68 enum thermal_device_mode mode; 72 enum thermal_device_mode mode;
69 struct regmap *tempmon; 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 unsigned long temp_passive; 75 unsigned long temp_passive;
72 unsigned long temp_critical; 76 unsigned long temp_critical;
73 unsigned long alarm_temp; 77 unsigned long alarm_temp;
@@ -84,7 +88,7 @@ static void imx_set_alarm_temp(struct imx_thermal_data *data,
84 int alarm_value; 88 int alarm_value;
85 89
86 data->alarm_temp = alarm_temp; 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 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK); 92 regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK);
89 regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value << 93 regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value <<
90 TEMPSENSE0_ALARM_VALUE_SHIFT); 94 TEMPSENSE0_ALARM_VALUE_SHIFT);
@@ -136,7 +140,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
136 n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT; 140 n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
137 141
138 /* See imx_get_sensor_data() for formula derivation */ 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 /* Update alarm value to next higher trip point */ 145 /* Update alarm value to next higher trip point */
142 if (data->alarm_temp == data->temp_passive && *temp >= data->temp_passive) 146 if (data->alarm_temp == data->temp_passive && *temp >= data->temp_passive)
@@ -305,6 +309,7 @@ static int imx_get_sensor_data(struct platform_device *pdev)
305 int t1, t2, n1, n2; 309 int t1, t2, n1, n2;
306 int ret; 310 int ret;
307 u32 val; 311 u32 val;
312 u64 temp64;
308 313
309 map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 314 map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
310 "fsl,tempmon-data"); 315 "fsl,tempmon-data");
@@ -330,6 +335,8 @@ static int imx_get_sensor_data(struct platform_device *pdev)
330 * [31:20] - sensor value @ 25C 335 * [31:20] - sensor value @ 25C
331 * [19:8] - sensor value of hot 336 * [19:8] - sensor value of hot
332 * [7:0] - hot temperature value 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 n1 = val >> 20; 341 n1 = val >> 20;
335 n2 = (val & 0xfff00) >> 8; 342 n2 = (val & 0xfff00) >> 8;
@@ -337,20 +344,26 @@ static int imx_get_sensor_data(struct platform_device *pdev)
337 t1 = 25; /* t1 always 25C */ 344 t1 = 25; /* t1 always 25C */
338 345
339 /* 346 /*
340 * Derived from linear interpolation, 347 * Derived from linear interpolation:
341 * Tmeas = T2 + (Nmeas - N2) * (T1 - T2) / (N1 - N2) 348 * slope = 0.4297157 - (0.0015976 * 25C fuse)
349 * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0
350 * (Nmeas - n1) / (Tmeas - t1) = slope
342 * We want to reduce this down to the minimum computation necessary 351 * We want to reduce this down to the minimum computation necessary
343 * for each temperature read. Also, we want Tmeas in millicelsius 352 * for each temperature read. Also, we want Tmeas in millicelsius
344 * and we don't want to lose precision from integer division. So... 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) 354 * Tmeas = (Nmeas - n1) / slope + t1
346 * Let constant c1 = 1000 * (T1 - T2) / (N1 - N2) 355 * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1
347 * milli_Tmeas = (1000 * T2) + c1 * (Nmeas - N2) 356 * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1
348 * milli_Tmeas = (1000 * T2) + (c1 * Nmeas) - (c1 * N2) 357 * Let constant c1 = (-1000 / slope)
349 * Let constant c2 = (1000 * T2) - (c1 * N2) 358 * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1
350 * milli_Tmeas = c2 + (c1 * Nmeas) 359 * Let constant c2 = n1 *c1 + 1000 * t1
360 * milli_Tmeas = c2 - Nmeas * c1
351 */ 361 */
352 data->c1 = 1000 * (t1 - t2) / (n1 - n2); 362 temp64 = FACTOR0;
353 data->c2 = 1000 * t2 - data->c1 * n2; 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 * Set the default passive cooling trip point to 20 °C below the 369 * Set the default passive cooling trip point to 20 °C below the