]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/thermal/imx_thermal.c
KARO: cleanup after merge of Freescale 3.10.17 stuff
[karo-tx-linux.git] / drivers / thermal / imx_thermal.c
index a99c63152b8dc4f9aa73b6d4ff26e3867721e9b0..1143db7a97ad23240554b36f710e5f6c64e27edb 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/device_cooling.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -58,6 +59,13 @@ enum imx_thermal_trip {
  * that will trigger cooling action when crossed.
  */
 #define IMX_TEMP_PASSIVE               85000
+#define IMX_TEMP_PASSIVE_COOL_DELTA    10000
+
+/*
+ * The maximum die temperature on imx parts is 105C, let's give some cushion
+ * for noise and possible temperature rise between measurements.
+ */
+#define IMX_TEMP_CRITICAL              100000
 
 #define IMX_POLLING_DELAY              2000 /* millisecond */
 #define IMX_PASSIVE_DELAY              1000
@@ -68,7 +76,7 @@ enum imx_thermal_trip {
 
 struct imx_thermal_data {
        struct thermal_zone_device *tz;
-       struct thermal_cooling_device *cdev;
+       struct thermal_cooling_device *cdev[2];
        enum thermal_device_mode mode;
        struct regmap *tempmon;
        u32 c1, c2; /* See formula in imx_get_sensor_data() */
@@ -290,6 +298,24 @@ static int imx_unbind(struct thermal_zone_device *tz,
        return 0;
 }
 
+static int imx_get_trend(struct thermal_zone_device *tz,
+               int trip, enum thermal_trend *trend)
+{
+       int ret;
+       unsigned long trip_temp;
+
+       ret = imx_get_trip_temp(tz, trip, &trip_temp);
+       if (ret < 0)
+               return ret;
+
+       if (tz->temperature >= (trip_temp - IMX_TEMP_PASSIVE_COOL_DELTA))
+               *trend = THERMAL_TREND_RAISE_FULL;
+       else
+               *trend = THERMAL_TREND_DROP_FULL;
+
+       return 0;
+}
+
 static struct thermal_zone_device_ops imx_tz_ops = {
        .bind = imx_bind,
        .unbind = imx_unbind,
@@ -299,6 +325,7 @@ static struct thermal_zone_device_ops imx_tz_ops = {
        .get_trip_type = imx_get_trip_type,
        .get_trip_temp = imx_get_trip_temp,
        .get_crit_temp = imx_get_crit_temp,
+       .get_trend = imx_get_trend,
        .set_trip_temp = imx_set_trip_temp,
 };
 
@@ -306,7 +333,7 @@ static int imx_get_sensor_data(struct platform_device *pdev)
 {
        struct imx_thermal_data *data = platform_get_drvdata(pdev);
        struct regmap *map;
-       int t1, t2, n1, n2;
+       int t1, n1;
        int ret;
        u32 val;
        u64 temp64;
@@ -333,14 +360,10 @@ static int imx_get_sensor_data(struct platform_device *pdev)
        /*
         * Sensor data layout:
         *   [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;
-       t2 = val & 0xff;
        t1 = 25; /* t1 always 25C */
 
        /*
@@ -366,16 +389,16 @@ static int imx_get_sensor_data(struct platform_device *pdev)
        data->c2 = n1 * data->c1 + 1000 * t1;
 
        /*
-        * Set the default passive cooling trip point to 20 °C below the
-        * maximum die temperature. Can be changed from userspace.
+        * Set the default passive cooling trip point,
+        * can be changed from userspace.
         */
-       data->temp_passive = 1000 * (t2 - 20);
+       data->temp_passive = IMX_TEMP_PASSIVE;
 
        /*
-        * The maximum die temperature is t2, let's give 5 °C cushion
-        * for noise and possible temperature rise between measurements.
+        * The maximum die temperature set to 20 C higher than
+        * IMX_TEMP_PASSIVE.
         */
-       data->temp_critical = 1000 * (t2 - 5);
+       data->temp_critical = 1000 * 20 + data->temp_passive;
 
        return 0;
 }
@@ -450,14 +473,24 @@ static int imx_thermal_probe(struct platform_device *pdev)
        regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
 
        cpumask_set_cpu(0, &clip_cpus);
-       data->cdev = cpufreq_cooling_register(&clip_cpus);
-       if (IS_ERR(data->cdev)) {
-               ret = PTR_ERR(data->cdev);
+       data->cdev[0] = cpufreq_cooling_register(&clip_cpus);
+       if (IS_ERR(data->cdev[0])) {
+               ret = PTR_ERR(data->cdev[0]);
                dev_err(&pdev->dev,
                        "failed to register cpufreq cooling device: %d\n", ret);
                return ret;
        }
 
+       data->cdev[1] = devfreq_cooling_register();
+       if (IS_ERR(data->cdev[1])) {
+               ret = PTR_ERR(data->cdev[1]);
+               dev_err(&pdev->dev,
+                       "failed to register devfreq cooling device: %d\n", ret);
+               return ret;
+       }
+
+       data->temp_passive = IMX_TEMP_PASSIVE;
+       data->temp_critical = IMX_TEMP_CRITICAL;
        data->tz = thermal_zone_device_register("imx_thermal_zone",
                                                IMX_TRIP_NUM,
                                                BIT(IMX_TRIP_PASSIVE), data,
@@ -468,7 +501,8 @@ static int imx_thermal_probe(struct platform_device *pdev)
                ret = PTR_ERR(data->tz);
                dev_err(&pdev->dev,
                        "failed to register thermal zone device %d\n", ret);
-               cpufreq_cooling_unregister(data->cdev);
+               cpufreq_cooling_unregister(data->cdev[0]);
+               devfreq_cooling_unregister(data->cdev[1]);
                return ret;
        }
 
@@ -513,7 +547,8 @@ static int imx_thermal_remove(struct platform_device *pdev)
                clk_disable_unprepare(data->thermal_clk);
 
        thermal_zone_device_unregister(data->tz);
-       cpufreq_cooling_unregister(data->cdev);
+       cpufreq_cooling_unregister(data->cdev[0]);
+       devfreq_cooling_unregister(data->cdev[1]);
 
        return 0;
 }