diff options
-rw-r--r-- | drivers/thermal/imx_thermal.c | 39 |
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 { #define IMX_POLLING_DELAY 2000 /* millisecond */ #define IMX_PASSIVE_DELAY 1000 +#define FACTOR0 10000000 +#define FACTOR1 15976 +#define FACTOR2 4297157 + struct imx_thermal_data { struct thermal_zone_device *tz; struct thermal_cooling_device *cdev; enum thermal_device_mode mode; struct regmap *tempmon; - int c1, c2; /* See formula in imx_get_sensor_data() */ + u32 c1, c2; /* See formula in imx_get_sensor_data() */ unsigned long temp_passive; unsigned long temp_critical; unsigned long alarm_temp; @@ -84,7 +88,7 @@ static void imx_set_alarm_temp(struct imx_thermal_data *data, int alarm_value; data->alarm_temp = alarm_temp; - alarm_value = (alarm_temp - data->c2) / data->c1; + alarm_value = (data->c2 - alarm_temp) / data->c1; regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK); regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value << TEMPSENSE0_ALARM_VALUE_SHIFT); @@ -136,7 +140,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp) n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT; /* See imx_get_sensor_data() for formula derivation */ - *temp = data->c2 + data->c1 * n_meas; + *temp = data->c2 - n_meas * data->c1; /* Update alarm value to next higher trip point */ 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) int t1, t2, n1, n2; int ret; u32 val; + u64 temp64; map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon-data"); @@ -330,6 +335,8 @@ static int imx_get_sensor_data(struct platform_device *pdev) * [31:20] - sensor value @ 25C * [19:8] - sensor value of hot * [7:0] - hot temperature value + * Use universal formula now and only need sensor value @ 25C + * slope = 0.4297157 - (0.0015976 * 25C fuse) */ n1 = val >> 20; n2 = (val & 0xfff00) >> 8; @@ -337,20 +344,26 @@ static int imx_get_sensor_data(struct platform_device *pdev) t1 = 25; /* t1 always 25C */ /* - * Derived from linear interpolation, - * Tmeas = T2 + (Nmeas - N2) * (T1 - T2) / (N1 - N2) + * Derived from linear interpolation: + * slope = 0.4297157 - (0.0015976 * 25C fuse) + * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0 + * (Nmeas - n1) / (Tmeas - t1) = slope * We want to reduce this down to the minimum computation necessary * for each temperature read. Also, we want Tmeas in millicelsius * and we don't want to lose precision from integer division. So... - * milli_Tmeas = 1000 * T2 + 1000 * (Nmeas - N2) * (T1 - T2) / (N1 - N2) - * Let constant c1 = 1000 * (T1 - T2) / (N1 - N2) - * milli_Tmeas = (1000 * T2) + c1 * (Nmeas - N2) - * milli_Tmeas = (1000 * T2) + (c1 * Nmeas) - (c1 * N2) - * Let constant c2 = (1000 * T2) - (c1 * N2) - * milli_Tmeas = c2 + (c1 * Nmeas) + * Tmeas = (Nmeas - n1) / slope + t1 + * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1 + * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1 + * Let constant c1 = (-1000 / slope) + * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1 + * Let constant c2 = n1 *c1 + 1000 * t1 + * milli_Tmeas = c2 - Nmeas * c1 */ - data->c1 = 1000 * (t1 - t2) / (n1 - n2); - data->c2 = 1000 * t2 - data->c1 * n2; + temp64 = FACTOR0; + temp64 *= 1000; + do_div(temp64, FACTOR1 * n1 - FACTOR2); + data->c1 = temp64; + data->c2 = n1 * data->c1 + 1000 * t1; /* * Set the default passive cooling trip point to 20 °C below the |