summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra3_thermal.c
diff options
context:
space:
mode:
authorJoshua Primero <jprimero@nvidia.com>2011-11-22 14:37:06 -0800
committerVarun Wadekar <vwadekar@nvidia.com>2011-12-08 18:02:40 +0530
commit9490e1fe92863b57a333dcb713d900966ced1f3b (patch)
tree5c84d22e254583a6cff04ad6e084031a5f6545c8 /arch/arm/mach-tegra/tegra3_thermal.c
parente6a55a17395f87509338e73278924f9c7bd45f06 (diff)
arm: tegra: thermal: Thermal cleanup
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>
Diffstat (limited to 'arch/arm/mach-tegra/tegra3_thermal.c')
-rw-r--r--arch/arm/mach-tegra/tegra3_thermal.c185
1 files changed, 112 insertions, 73 deletions
diff --git a/arch/arm/mach-tegra/tegra3_thermal.c b/arch/arm/mach-tegra/tegra3_thermal.c
index f6f3c40007e6..27e09545806d 100644
--- a/arch/arm/mach-tegra/tegra3_thermal.c
+++ b/arch/arm/mach-tegra/tegra3_thermal.c
@@ -36,13 +36,21 @@
#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;