arm: tegra: thermal: Thermal cleanup
Joshua Primero [Tue, 22 Nov 2011 22:37:06 +0000 (14:37 -0800)]
Added tc1, tc2, and passive delay to thermal framework
parameters.

Made thermal offsets more explicit and clean.

In throttling code, instead of using one 10 second 640000 entry,
split this into five 2 second entries.  This will give better
temperature stability.

bug 877359

Change-Id: Idc463ab18bdabb7a0472f4f6572195bf76067bd4
Signed-off-by: Joshua Primero <jprimero@nvidia.com>
Reviewed-on: http://git-master/r/68029
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>

Rebase-Id: R68a2bb662fe81636defdaa88da75cffb11712cf7

arch/arm/mach-tegra/include/mach/thermal.h
arch/arm/mach-tegra/tegra3_thermal.c
arch/arm/mach-tegra/tegra3_throttle.c

index 6b5e74b..714b633 100644 (file)
@@ -22,11 +22,17 @@ struct tegra_thermal_data {
        long temp_throttle;
        long temp_shutdown;
        long temp_offset;
+#ifdef CONFIG_TEGRA_EDP_LIMITS
        long edp_offset;
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
+       long hysteresis_edp;
+#endif
+#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+       int tc1;
+       int tc2;
+       long passive_delay;
+#else
        long hysteresis_throttle;
 #endif
-       long hysteresis_edp;
 };
 
 struct tegra_thermal_device {
index f6f3c40..27e0954 100644 (file)
 #define MAX_ZONES (16)
 
 struct tegra_thermal {
-       struct tegra_thermal_data data;
        struct tegra_thermal_device *device;
+       long temp_throttle_tj;
+       long temp_shutdown_tj;
 #ifdef CONFIG_TEGRA_THERMAL_SYSFS
        struct thermal_zone_device *thz;
+       int tc1;
+       int tc2;
+       long passive_delay;
+#else
+       long temp_throttle_low_tj;
 #endif
 #ifdef CONFIG_TEGRA_EDP_LIMITS
        int edp_thermal_zone_val;
+       long edp_offset;
+       long hysteresis_edp;
 #endif
 };
 
@@ -58,6 +66,32 @@ static bool throttle_enb;
 struct mutex mutex;
 #endif
 
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+static inline long edp2tj(struct tegra_thermal *thermal,
+                               long edp_temp)
+{
+       return edp_temp + thermal->edp_offset;
+}
+
+static inline long tj2edp(struct tegra_thermal *thermal,
+                               long temp_tj)
+{
+       return temp_tj - thermal->edp_offset;
+}
+#endif
+
+static inline long dev2tj(struct tegra_thermal_device *dev,
+                               long dev_temp)
+{
+       return dev_temp + dev->offset;
+}
+
+static inline long tj2dev(struct tegra_thermal_device *dev,
+                               long tj_temp)
+{
+       return tj_temp - dev->offset;
+}
+
 #ifdef CONFIG_TEGRA_THERMAL_SYSFS
 
 static int tegra_thermal_zone_bind(struct thermal_zone_device *thermal,
@@ -76,7 +110,7 @@ static int tegra_thermal_zone_get_temp(struct thermal_zone_device *thz,
                                                long *temp)
 {
        struct tegra_thermal *thermal = thz->devdata;
-       thermal->device->get_temp(thermal->device_client, temp);
+       thermal->device->get_temp(thermal->device->data, temp);
 
        return 0;
 }
@@ -95,16 +129,16 @@ static int tegra_thermal_zone_get_trip_type(
        return 0;
 }
 
-static int tegra_thermal_zone_get_trip_temp(struct thermal_zone_device *thermal,
+static int tegra_thermal_zone_get_trip_temp(struct thermal_zone_device *thz,
                                                int trip,
                                                long *temp) {
+       struct tegra_thermal *thermal = thz->devdata;
+
        /* Support only Thermal Throttling (1 trip) for now */
        if (trip != 0)
                return -EINVAL;
 
-       *temp = thermal->data.temp_throttle +
-               thermal->data.temp_offset -
-               thermal->device->offset;
+       *temp = tj2dev(thermal->device, thermal->temp_throttle_tj);
 
        return 0;
 }
@@ -132,20 +166,20 @@ static void tegra_therm_throttle(bool enable)
 }
 #endif
 
+/* Make sure this function remains stateless */
 void tegra_thermal_alert(void *data)
 {
        struct tegra_thermal *thermal = data;
        int err;
-       long temp;
-       long lo_limit_throttle, hi_limit_throttle;
-       long lo_limit_edp = 0, hi_limit_edp = 0;
-       long tj_temp, tj_throttle_temp, tj_shutdown_temp;
+       long temp_dev, temp_tj;
+       long lo_limit_throttle_tj, hi_limit_throttle_tj;
+       long lo_limit_edp_tj = 0, hi_limit_edp_tj = 0;
        int lo_limit_tj = 0, hi_limit_tj = 0;
-       int lo_limit = 0, hi_limit = 0;
+#ifdef CONFIG_TEGRA_EDP_LIMITS
        const struct tegra_edp_limits *z;
        int zones_sz;
        int i;
-
+#endif
 
        if (thermal != &thermal_state)
                BUG();
@@ -157,78 +191,73 @@ void tegra_thermal_alert(void *data)
        }
 #endif
 
-       err = thermal->device->get_temp(thermal->device->data, &temp);
+       err = thermal->device->get_temp(thermal->device->data, &temp_dev);
        if (err) {
                pr_err("%s: get temp fail(%d)", __func__, err);
                return;
        }
 
-       tj_temp = temp + thermal->device->offset;
-       tj_throttle_temp = thermal->data.temp_throttle
-                               + thermal->data.temp_offset;
-       tj_shutdown_temp = thermal->data.temp_shutdown
-                               + thermal->data.temp_offset;
+       /* Convert all temps to tj and then do all work/logic in terms of
+          tj in order to avoid confusion */
+       temp_tj = dev2tj(thermal->device, temp_dev);
+
+       lo_limit_throttle_tj = dev2tj(thermal->device, 0);
+       hi_limit_throttle_tj = thermal->temp_throttle_tj;
 
+#ifndef CONFIG_TEGRA_THERMAL_SYSFS
+       /* Check to see if we are currently throttling */
        if ((tegra_is_throttling() &&
-               (tj_temp >
-                       (tj_throttle_temp - thermal->data.hysteresis_throttle)))
-               || (tj_temp >= tj_throttle_temp)) {
-               lo_limit_throttle = tj_throttle_temp -
-                                       thermal->data.hysteresis_throttle;
-               hi_limit_throttle = tj_shutdown_temp;
-       } else {
-               lo_limit_throttle = 0;
-               hi_limit_throttle = tj_throttle_temp;
+               (temp_tj > thermal->temp_throttle_low_tj))
+               || (temp_tj >= thermal->temp_throttle_tj)) {
+               lo_limit_throttle_tj = thermal->temp_throttle_low_tj;
+               hi_limit_throttle_tj = thermal->temp_shutdown_tj;
        }
+#endif
 
 #ifdef CONFIG_TEGRA_EDP_LIMITS
        tegra_get_cpu_edp_limits(&z, &zones_sz);
 
 /* edp table based off of tdiode measurements */
-#define EDP_TEMP(_index)       ((z[_index].temperature * 1000)\
-                               + thermal->data.edp_offset)
-       if (tj_temp < EDP_TEMP(0)) {
-               lo_limit_edp = 0;
-               hi_limit_edp = EDP_TEMP(0);
-       } else if (tj_temp >= EDP_TEMP(zones_sz-1)) {
-               lo_limit_edp = EDP_TEMP(zones_sz-1) -
-                               thermal->data.hysteresis_edp;
-               hi_limit_edp = tj_shutdown_temp;
+#define EDP_TEMP_TJ(_index)    edp2tj(thermal, z[_index].temperature * 1000)
+
+       if (temp_tj < EDP_TEMP_TJ(0)) {
+               lo_limit_edp_tj = dev2tj(thermal->device, 0);
+               hi_limit_edp_tj = EDP_TEMP_TJ(0);
+       } else if (temp_tj >= EDP_TEMP_TJ(zones_sz-1)) {
+               lo_limit_edp_tj = EDP_TEMP_TJ(zones_sz-1) -
+                                       thermal->hysteresis_edp;
+               hi_limit_edp_tj = thermal->temp_shutdown_tj;
        } else {
                for (i = 0; (i + 1) < zones_sz; i++) {
-                       if ((tj_temp >= EDP_TEMP(i)) &&
-                               (tj_temp < EDP_TEMP(i+1))) {
-                               lo_limit_edp = EDP_TEMP(i) -
-                                               thermal->data.hysteresis_edp;
-                               hi_limit_edp = EDP_TEMP(i+1);
+                       if ((temp_tj >= EDP_TEMP_TJ(i)) &&
+                               (temp_tj < EDP_TEMP_TJ(i+1))) {
+                               lo_limit_edp_tj = EDP_TEMP_TJ(i) -
+                                                       thermal->hysteresis_edp;
+                               hi_limit_edp_tj = EDP_TEMP_TJ(i+1);
                                break;
                        }
                }
        }
-#undef EDP_TEMP
+#undef EDP_TEMP_TJ
 #else
-       lo_limit_edp = 0;
-       hi_limit_edp = tj_shutdown_temp;
+       lo_limit_edp_tj = 0;
+       hi_limit_edp_tj = thermal->temp_shutdown_tj;
 #endif
 
        /* Get smallest window size */
-       lo_limit_tj = max(lo_limit_throttle, lo_limit_edp);
-       hi_limit_tj = min(hi_limit_throttle, hi_limit_edp);
-
-       /* Get corresponding device temps */
-       lo_limit = lo_limit_tj ? (lo_limit_tj - thermal->device->offset) : 0;
-       hi_limit = hi_limit_tj ? (hi_limit_tj - thermal->device->offset) : 0;
+       lo_limit_tj = max(lo_limit_throttle_tj, lo_limit_edp_tj);
+       hi_limit_tj = min(hi_limit_throttle_tj, hi_limit_edp_tj);
 
-       thermal->device->set_limits(thermal->device->data, lo_limit, hi_limit);
+       thermal->device->set_limits(thermal->device->data,
+                                       tj2dev(thermal->device, lo_limit_tj),
+                                       tj2dev(thermal->device, hi_limit_tj));
 
 #ifndef CONFIG_TEGRA_THERMAL_SYSFS
-       if (tj_temp >= tj_throttle_temp) {
+       if (temp_tj >= thermal->temp_throttle_tj) {
                /* start throttling */
                if (!tegra_is_throttling())
                        tegra_therm_throttle(true);
-       } else if (tj_temp <=
-                       (tj_throttle_temp -
-                       thermal->data.hysteresis_throttle)) {
+       } else if (temp_tj <= thermal->temp_throttle_low_tj) {
                /* switch off throttling */
                if (tegra_is_throttling())
                        tegra_therm_throttle(false);
@@ -237,17 +266,16 @@ void tegra_thermal_alert(void *data)
 
 #ifdef CONFIG_TEGRA_EDP_LIMITS
        /* inform edp governor */
-       if (thermal->edp_thermal_zone_val != tj_temp)
-               tegra_edp_update_thermal_zone(
-                       (tj_temp - thermal->data.edp_offset)/1000);
+       if (thermal->edp_thermal_zone_val != temp_tj)
+               tegra_edp_update_thermal_zone(tj2edp(thermal, temp_tj)/1000);
 
-       thermal->edp_thermal_zone_val = tj_temp;
+       thermal->edp_thermal_zone_val = temp_tj;
 #endif
 }
 
 int tegra_thermal_set_device(struct tegra_thermal_device *device)
 {
-#ifdef CONFIG_THERMAL_SYSFS
+#ifdef CONFIG_TEGRA_THERMAL_SYSFS
        struct thermal_zone_device *thz;
 #endif
 
@@ -262,27 +290,25 @@ int tegra_thermal_set_device(struct tegra_thermal_device *device)
                                        1, /* trips */
                                        &thermal_state,
                                        &tegra_thermal_zone_ops,
-                                       2, /* tc1 */
-                                       1, /* tc2 */
-                                       2000, /* passive delay */
+                                       thermal_state.tc1, /* dT/dt */
+                                       thermal_state.tc2, /* throttle */
+                                       thermal_state.passive_delay,
                                        0); /* polling delay */
 
        if (IS_ERR(thz)) {
                thz = NULL;
-               kfree(thermal);
                return -ENODEV;
        }
 
        thermal_state.thz = thz;
 #endif
-
        thermal_state.device->set_alert(thermal_state.device->data,
                                        tegra_thermal_alert,
                                        &thermal_state);
+
        thermal_state.device->set_shutdown_temp(thermal_state.device->data,
-                                       thermal_state.data.temp_shutdown +
-                                       thermal_state.data.temp_offset -
-                                       thermal_state.device->offset);
+                               tj2dev(device, thermal_state.temp_shutdown_tj));
+
        /* initialize limits */
        tegra_thermal_alert(&thermal_state);
 
@@ -291,11 +317,24 @@ int tegra_thermal_set_device(struct tegra_thermal_device *device)
 
 int __init tegra_thermal_init(struct tegra_thermal_data *data)
 {
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
+#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+       thermal_state.tc1 = data->tc1;
+       thermal_state.tc2 = data->tc2;
+       thermal_state.passive_delay = data->passive_delay;
+#else
        mutex_init(&mutex);
+       thermal_state.temp_throttle_low_tj = data->temp_throttle +
+                                               data->temp_offset -
+                                               data->hysteresis_throttle;
 #endif
-
-       memcpy(&thermal_state.data, data, sizeof(struct tegra_thermal_data));
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+       thermal_state.edp_offset = data->edp_offset;
+       thermal_state.hysteresis_edp = data->hysteresis_edp;
+#endif
+       thermal_state.temp_throttle_tj = data->temp_throttle +
+                                               data->temp_offset;
+       thermal_state.temp_shutdown_tj = data->temp_shutdown +
+                                               data->temp_offset;
 
        return 0;
 }
@@ -303,8 +342,8 @@ int __init tegra_thermal_init(struct tegra_thermal_data *data)
 int tegra_thermal_exit(void)
 {
 #ifdef CONFIG_TEGRA_THERMAL_SYSFS
-       if (thermal->thz)
-               thermal_zone_device_unregister(thermal->thz);
+       if (thermal_state.thz)
+               thermal_zone_device_unregister(thermal_state.thz);
 #endif
 
        return 0;
index 6f4a3bc..f927be7 100644 (file)
@@ -42,7 +42,11 @@ static struct {
        int ms;
 } throttle_table[] = {
        {      0, 1000, 2000 }, /* placeholder for cpu floor rate */
-       { 640000, 1000, 10000 },
+       { 640000, 1000, 2000 },
+       { 640000, 1000, 2000 },
+       { 640000, 1000, 2000 },
+       { 640000, 1000, 2000 },
+       { 640000, 1000, 2000 },
        { 760000, 1000, 2000 },
        { 760000, 1050, 2000 },
        {1000000, 1050, 2000 },