summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra3_thermal.c
diff options
context:
space:
mode:
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;