Merge branch 'perf-core-for-mingo' into perf/urgent
[firefly-linux-kernel-4.4.55.git] / drivers / thermal / imx_thermal.c
index 45af765a3198c4b0e55e96c878d609f8b6b34d8e..a99c63152b8dc4f9aa73b6d4ff26e3867721e9b0 100644 (file)
@@ -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