summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Primero <jprimero@nvidia.com>2011-10-13 17:49:20 -0700
committerVarun Wadekar <vwadekar@nvidia.com>2011-12-08 17:03:38 +0530
commit0a892e234ce77f94973afbf2d00ea4239ee6b677 (patch)
tree60a1d541af0d8e03c93376f778caa1d9b71abf2d
parent99cd63f81e09e6dafcba8cb5e61a5b56b258fad5 (diff)
arm: tegra: power: Tegra Thermal refactoring
Refactored Thermal module so that thermal device drivers themselves are agnostic of the thermal framework. Also separated throttle limit constraints from EDP table. Reviewed-on: http://git-master/r/57990 Reviewed-on: http://git-master/r/63338 Cherry-picked from 8d0610bdd03c3490b718f11bc2108f45cd868533. Change-Id: I4f87889c9cdc88daac1e6173043bab1f2e7cebfd Signed-off-by: Joshua Primero <jprimero@nvidia.com> Reviewed-on: http://git-master/r/66551 Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/board-cardhu-sensors.c57
-rw-r--r--arch/arm/mach-tegra/board-cardhu.c14
-rw-r--r--arch/arm/mach-tegra/board-cardhu.h2
-rw-r--r--arch/arm/mach-tegra/board-enterprise-sensors.c61
-rw-r--r--arch/arm/mach-tegra/board-enterprise.c14
-rw-r--r--arch/arm/mach-tegra/board-enterprise.h2
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c5
-rw-r--r--arch/arm/mach-tegra/include/mach/thermal.h48
-rw-r--r--arch/arm/mach-tegra/tegra3_thermal.c301
9 files changed, 332 insertions, 172 deletions
diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c
index 055cd88395b0..1177d4b6ccba 100644
--- a/arch/arm/mach-tegra/board-cardhu-sensors.c
+++ b/arch/arm/mach-tegra/board-cardhu-sensors.c
@@ -51,6 +51,7 @@
#include <linux/bq27x00.h>
#include <mach/gpio.h>
#include <mach/edp.h>
+#include <mach/thermal.h>
#include "gpio-names.h"
#include "board-cardhu.h"
@@ -569,6 +570,58 @@ static struct i2c_board_info cardhu_i2c8_board_info[] = {
},
};
+#ifndef CONFIG_TEGRA_INTERNAL_TSENSOR_EDP_SUPPORT
+static int nct_get_temp(void *_data, long *temp)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_get_temp(data, temp);
+}
+
+static int nct_set_limits(void *_data,
+ long lo_limit_milli,
+ long hi_limit_milli)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_set_limits(data,
+ lo_limit_milli,
+ hi_limit_milli);
+}
+
+static int nct_set_alert(void *_data,
+ void (*alert_func)(void *),
+ void *alert_data)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_set_alert(data, alert_func, alert_data);
+}
+
+static int nct_set_shutdown_temp(void *_data, long shutdown_temp)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_set_shutdown_temp(data, shutdown_temp);
+}
+static void nct1008_probe_callback(struct nct1008_data *data)
+{
+ struct tegra_thermal_device *thermal_device;
+
+ thermal_device = kzalloc(sizeof(struct tegra_thermal_device),
+ GFP_KERNEL);
+ if (!thermal_device) {
+ pr_err("unable to allocate thermal device\n");
+ return;
+ }
+
+ thermal_device->data = data;
+ thermal_device->offset = TDIODE_OFFSET;
+ thermal_device->get_temp = nct_get_temp;
+ thermal_device->set_limits = nct_set_limits;
+ thermal_device->set_alert = nct_set_alert;
+ thermal_device->set_shutdown_temp = nct_set_shutdown_temp;
+
+ tegra_thermal_set_device(thermal_device);
+}
+#endif
+
static struct nct1008_platform_data cardhu_nct1008_pdata = {
.supported_hwrev = true,
.ext_range = true,
@@ -579,6 +632,9 @@ static struct nct1008_platform_data cardhu_nct1008_pdata = {
.shutdown_local_limit = 90,
.throttling_ext_limit = 85,
.alarm_fn = tegra_throttling_enable,
+#ifndef CONFIG_TEGRA_INTERNAL_TSENSOR_EDP_SUPPORT
+ .probe_callback = nct1008_probe_callback,
+#endif
};
static struct i2c_board_info cardhu_i2c4_bq27510_board_info[] = {
@@ -595,7 +651,6 @@ static struct i2c_board_info cardhu_i2c4_nct1008_board_info[] = {
}
};
-
static int cardhu_nct1008_init(void)
{
int nct1008_port = -1;
diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c
index a63e32186080..3fc0420c57c1 100644
--- a/arch/arm/mach-tegra/board-cardhu.c
+++ b/arch/arm/mach-tegra/board-cardhu.c
@@ -53,6 +53,7 @@
#include <asm/mach/arch.h>
#include <mach/usb_phy.h>
#include <linux/nfc/pn544.h>
+#include <mach/thermal.h>
#include "board.h"
#include "clock.h"
@@ -63,6 +64,18 @@
#include "pm.h"
#include "baseband-xmm-power.h"
+/* All units are in millicelsius */
+static struct tegra_thermal_data thermal_data = {
+ .temp_throttle = 85000,
+ .temp_shutdown = 90000,
+ .temp_offset = TDIODE_OFFSET, /* temps based on tdiode */
+ .edp_offset = TDIODE_OFFSET, /* edp based on tdiode */
+#ifndef CONFIG_TEGRA_THERMAL_SYSFS
+ .hysteresis_throttle = 1000,
+#endif
+ .hysteresis_edp = 3000,
+};
+
/* !!!TODO: Change for cardhu (Taken from Ventana) */
static struct tegra_utmip_config utmi_phy_config[] = {
[0] = {
@@ -914,6 +927,7 @@ static void cardhu_sata_init(void) { }
static void __init tegra_cardhu_init(void)
{
+ tegra_thermal_init(&thermal_data);
tegra_clk_init_from_table(cardhu_clk_init_table);
cardhu_pinmux_init();
cardhu_i2c_init();
diff --git a/arch/arm/mach-tegra/board-cardhu.h b/arch/arm/mach-tegra/board-cardhu.h
index 15641a0c35db..5c8dcb4aab34 100644
--- a/arch/arm/mach-tegra/board-cardhu.h
+++ b/arch/arm/mach-tegra/board-cardhu.h
@@ -226,4 +226,6 @@ void __init cardhu_tsensor_init(void);
#define XMM_GPIO_IPC_BB_WAKE BB_GPIO_AWR
#define XMM_GPIO_IPC_AP_WAKE BB_GPIO_CWR
+#define TDIODE_OFFSET (10000) /* in millicelsius */
+
#endif
diff --git a/arch/arm/mach-tegra/board-enterprise-sensors.c b/arch/arm/mach-tegra/board-enterprise-sensors.c
index 3ab93348571a..a0583e906b0f 100644
--- a/arch/arm/mach-tegra/board-enterprise-sensors.c
+++ b/arch/arm/mach-tegra/board-enterprise-sensors.c
@@ -34,20 +34,76 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/i2c/pca954x.h>
+#include <linux/nct1008.h>
#include <linux/err.h>
#include <linux/mpu.h>
-#include <linux/nct1008.h>
#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
#include <mach/gpio.h>
#include <media/ar0832_main.h>
#include <media/tps61050.h>
#include <media/ov9726.h>
#include <mach/edp.h>
+#include <mach/thermal.h>
#include "cpu-tegra.h"
#include "gpio-names.h"
#include "board-enterprise.h"
#include "board.h"
+#ifndef CONFIG_TEGRA_INTERNAL_TSENSOR_EDP_SUPPORT
+static int nct_get_temp(void *_data, long *temp)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_get_temp(data, temp);
+}
+
+static int nct_set_limits(void *_data,
+ long lo_limit_milli,
+ long hi_limit_milli)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_set_limits(data,
+ lo_limit_milli,
+ hi_limit_milli);
+}
+
+static int nct_set_alert(void *_data,
+ void (*alert_func)(void *),
+ void *alert_data)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_set_alert(data, alert_func, alert_data);
+}
+
+static int nct_set_shutdown_temp(void *_data, long shutdown_temp)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_set_shutdown_temp(data,
+ shutdown_temp);
+}
+
+static void nct1008_probe_callback(struct nct1008_data *data)
+{
+ struct tegra_thermal_device *thermal_device;
+
+ thermal_device = kzalloc(sizeof(struct tegra_thermal_device),
+ GFP_KERNEL);
+ if (!thermal_device) {
+ pr_err("unable to allocate thermal device\n");
+ return;
+ }
+
+ thermal_device->data = data;
+ thermal_device->offset = TDIODE_OFFSET;
+ thermal_device->get_temp = nct_get_temp;
+ thermal_device->set_limits = nct_set_limits;
+ thermal_device->set_alert = nct_set_alert;
+ thermal_device->set_shutdown_temp = nct_set_shutdown_temp;
+
+ tegra_thermal_set_device(thermal_device);
+}
+#endif
+
static struct nct1008_platform_data enterprise_nct1008_pdata = {
.supported_hwrev = true,
.ext_range = true,
@@ -58,6 +114,9 @@ static struct nct1008_platform_data enterprise_nct1008_pdata = {
.shutdown_local_limit = 90,
.throttling_ext_limit = 85,
.alarm_fn = tegra_throttling_enable,
+#ifndef CONFIG_TEGRA_INTERNAL_TSENSOR_EDP_SUPPORT
+ .probe_callback = nct1008_probe_callback,
+#endif
};
static struct i2c_board_info enterprise_i2c4_nct1008_board_info[] = {
diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c
index f3b10467f8e7..952ffc2f4c97 100644
--- a/arch/arm/mach-tegra/board-enterprise.c
+++ b/arch/arm/mach-tegra/board-enterprise.c
@@ -52,6 +52,7 @@
#include <mach/usb_phy.h>
#include <mach/i2s.h>
#include <mach/tegra_max98088_pdata.h>
+#include <mach/thermal.h>
#include "board.h"
#include "clock.h"
@@ -62,6 +63,18 @@
#include "fuse.h"
#include "pm.h"
+/* All units are in millicelsius */
+static struct tegra_thermal_data thermal_data = {
+ .temp_throttle = 85000,
+ .temp_shutdown = 90000,
+ .temp_offset = TDIODE_OFFSET, /* temps based on tdiode */
+ .edp_offset = TDIODE_OFFSET, /* edp based on tdiode */
+#ifndef CONFIG_TEGRA_THERMAL_SYSFS
+ .hysteresis_throttle = 1000,
+#endif
+ .hysteresis_edp = 3000,
+};
+
/* !!!TODO: Change for enterprise (Taken from Cardhu) */
static struct tegra_utmip_config utmi_phy_config[] = {
[0] = {
@@ -805,6 +818,7 @@ static void enterprise_nfc_init(void)
static void __init tegra_enterprise_init(void)
{
+ tegra_thermal_init(&thermal_data);
tegra_clk_init_from_table(enterprise_clk_init_table);
enterprise_pinmux_init();
enterprise_i2c_init();
diff --git a/arch/arm/mach-tegra/board-enterprise.h b/arch/arm/mach-tegra/board-enterprise.h
index 398d1336deae..fff519381f38 100644
--- a/arch/arm/mach-tegra/board-enterprise.h
+++ b/arch/arm/mach-tegra/board-enterprise.h
@@ -109,4 +109,6 @@ void __init enterprise_tsensor_init(void);
#define XMM_GPIO_IPC_BB_WAKE BB_GPIO_HS1_AP2BB
#define XMM_GPIO_IPC_AP_WAKE BB_GPIO_HS1_BB2AP
+#define TDIODE_OFFSET (9000) /* in millicelsius */
+
#endif
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index 598c6b0408a9..d6793f87cc5f 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -38,7 +38,6 @@
#include <mach/clk.h>
#include <mach/edp.h>
-#include <mach/thermal.h>
#include "clock.h"
#include "cpu-tegra.h"
@@ -648,10 +647,6 @@ static int __init tegra_cpufreq_init(void)
suspend_index = table_data->suspend_index;
- ret = tegra_thermal_init();
- if (ret)
- return ret;
-
ret = tegra_throttle_init(&tegra_cpu_lock);
if (ret)
return ret;
diff --git a/arch/arm/mach-tegra/include/mach/thermal.h b/arch/arm/mach-tegra/include/mach/thermal.h
index 0d25c307f94e..6b5e74bf4bfb 100644
--- a/arch/arm/mach-tegra/include/mach/thermal.h
+++ b/arch/arm/mach-tegra/include/mach/thermal.h
@@ -17,44 +17,38 @@
#ifndef __MACH_THERMAL_H
#define __MACH_THERMAL_H
-struct tegra_thermal_ops {
- int (*get_temp) (void *, long *);
- int (*set_limits) (void *, long, long);
+/* All units in millicelsius */
+struct tegra_thermal_data {
+ long temp_throttle;
+ long temp_shutdown;
+ long temp_offset;
+ long edp_offset;
+#ifndef CONFIG_TEGRA_THERMAL_SYSFS
+ long hysteresis_throttle;
+#endif
+ long hysteresis_edp;
};
-struct tegra_thermal {
+struct tegra_thermal_device {
void *data;
- struct tegra_thermal_ops *ops;
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- struct thermal_zone_device *thz;
-#endif
+ long offset;
+ int (*get_temp) (void *, long *);
+ int (*set_limits) (void *, long, long);
+ int (*set_alert)(void *, void (*)(void *), void *);
+ int (*set_shutdown_temp)(void *, long);
};
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
-int tegra_thermal_init(void);
+int tegra_thermal_init(struct tegra_thermal_data *data);
+int tegra_thermal_set_device(struct tegra_thermal_device *device);
int tegra_thermal_exit(void);
-
-struct tegra_thermal
- *tegra_thermal_register(void *data, struct tegra_thermal_ops *ops);
-int tegra_thermal_unregister(struct tegra_thermal *thermal);
-int tegra_thermal_alert(struct tegra_thermal *thermal);
#else
-static inline int tegra_thermal_init(void)
+static inline int tegra_thermal_init(struct tegra_thermal_data *data)
{ return 0; }
-static inline int tegra_thermal_exit(void)
-{ return 0; }
-static inline struct tegra_thermal
- *tegra_thermal_register(void *data, struct tegra_thermal_ops *ops)
-{ return NULL; }
-static inline int tegra_thermal_unregister(struct tegra_thermal *thermal)
+static inline int tegra_thermal_set_device(struct tegra_thermal_device *dev)
{ return 0; }
-static inline int tegra_thermal_alert(struct tegra_thermal *thermal)
+static inline int tegra_thermal_exit(void)
{ return 0; }
#endif
-#define CELSIUS_TO_MILLICELSIUS(x) ((x)*1000)
-#define MILLICELSIUS_TO_CELSIUS(x) ((x)/1000)
-
-
-
#endif /* __MACH_THERMAL_H */
diff --git a/arch/arm/mach-tegra/tegra3_thermal.c b/arch/arm/mach-tegra/tegra3_thermal.c
index 30f8d7d8d800..f6f3c40007e6 100644
--- a/arch/arm/mach-tegra/tegra3_thermal.c
+++ b/arch/arm/mach-tegra/tegra3_thermal.c
@@ -29,54 +29,35 @@
#include <mach/edp.h>
#include <linux/slab.h>
-
#include "clock.h"
#include "cpu-tegra.h"
#include "dvfs.h"
#define MAX_ZONES (16)
-/* Thermal sysfs handles hysteresis */
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
-#define ALERT_HYSTERESIS_THROTTLE 1
+struct tegra_thermal {
+ struct tegra_thermal_data data;
+ struct tegra_thermal_device *device;
+#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+ struct thermal_zone_device *thz;
#endif
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+ int edp_thermal_zone_val;
+#endif
+};
-#define ALERT_HYSTERESIS_EDP 3
-
-#define THROTTLING_LIMIT (85000)
-#define MAX_LIMIT (90000)
-
-u8 thermal_zones[MAX_ZONES];
-int thermal_zones_sz;
-static int edp_thermal_zone_val = -1;
+static struct tegra_thermal thermal_state = {
+ .device = NULL,
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+ .edp_thermal_zone_val = -1,
+#endif
+};
#ifndef CONFIG_TEGRA_THERMAL_SYSFS
static bool throttle_enb;
struct mutex mutex;
#endif
-
-int __init tegra_thermal_init()
-{
- const struct tegra_edp_limits *z;
- int zones_sz;
- int i;
-
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
- mutex_init(&mutex);
-#endif
- tegra_get_cpu_edp_limits(&z, &zones_sz);
- zones_sz = min(zones_sz, MAX_ZONES);
-
- for (i = 0; i < zones_sz; i++)
- thermal_zones[i] = z[i].temperature;
-
- thermal_zones_sz = zones_sz;
-
- return 0;
-}
-
-
#ifdef CONFIG_TEGRA_THERMAL_SYSFS
static int tegra_thermal_zone_bind(struct thermal_zone_device *thermal,
@@ -95,7 +76,7 @@ static int tegra_thermal_zone_get_temp(struct thermal_zone_device *thz,
long *temp)
{
struct tegra_thermal *thermal = thz->devdata;
- thermal->ops->get_temp(thermal->data, temp);
+ thermal->device->get_temp(thermal->device_client, temp);
return 0;
}
@@ -121,7 +102,9 @@ static int tegra_thermal_zone_get_trip_temp(struct thermal_zone_device *thermal,
if (trip != 0)
return -EINVAL;
- *temp = THROTTLING_LIMIT;
+ *temp = thermal->data.temp_throttle +
+ thermal->data.temp_offset -
+ thermal->device->offset;
return 0;
}
@@ -135,61 +118,6 @@ static struct thermal_zone_device_ops tegra_thermal_zone_ops = {
};
#endif
-
-
-struct tegra_thermal
-*tegra_thermal_register(void *data, struct tegra_thermal_ops *thermal_ops)
-{
- long temp_milli;
- struct tegra_thermal *thermal;
-#ifdef CONFIG_THERMAL_SYSFS
- struct thermal_zone_device *thz;
-#endif
-
- thermal = kzalloc(sizeof(struct tegra_thermal), GFP_KERNEL);
- if (!thermal)
- return ERR_PTR(-ENOMEM);
-
- thermal->ops = thermal_ops;
- thermal->data = data;
-
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- thz = thermal_zone_device_register("nct1008",
- 1, /* trips */
- thermal,
- &tegra_thermal_zone_ops,
- 2, /* tc1 */
- 1, /* tc2 */
- 2000, /* passive delay */
- 0); /* polling delay */
-
- if (IS_ERR(thz)) {
- thz = NULL;
- kfree(thermal);
- return ERR_PTR(-ENODEV);
- }
-
- thermal->thz = thz;
-#endif
-
- thermal->ops->get_temp(thermal->data, &temp_milli);
- tegra_edp_update_thermal_zone(MILLICELSIUS_TO_CELSIUS(temp_milli));
-
- return thermal;
-}
-
-int tegra_thermal_unregister(struct tegra_thermal *thermal)
-{
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- if (thermal->thz)
- thermal_zone_device_unregister(thermal->thz);
-#endif
-
- kfree(thermal);
-
- return 0;
-}
-
/* The thermal sysfs handles notifying the throttling
* cooling device */
#ifndef CONFIG_TEGRA_THERMAL_SYSFS
@@ -204,83 +132,180 @@ static void tegra_therm_throttle(bool enable)
}
#endif
-int tegra_thermal_alert(struct tegra_thermal *thermal)
+void tegra_thermal_alert(void *data)
{
+ struct tegra_thermal *thermal = data;
int err;
- int hysteresis;
- long temp, tzone1, tzone2;
+ 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;
+ int lo_limit_tj = 0, hi_limit_tj = 0;
int lo_limit = 0, hi_limit = 0;
- int nentries = thermal_zones_sz;
+ const struct tegra_edp_limits *z;
+ int zones_sz;
int i;
- err = thermal->ops->get_temp(thermal->data, &temp);
+
+ if (thermal != &thermal_state)
+ BUG();
+
+#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+ if (thermal->thz) {
+ if (!thermal->thz->passive)
+ thermal_zone_device_update(thermal->thz);
+ }
+#endif
+
+ err = thermal->device->get_temp(thermal->device->data, &temp);
if (err) {
pr_err("%s: get temp fail(%d)", __func__, err);
- return err;
+ return;
}
- hysteresis = ALERT_HYSTERESIS_EDP;
-
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
- if (temp >= THROTTLING_LIMIT) {
- /* start throttling */
- tegra_therm_throttle(true);
- hysteresis = ALERT_HYSTERESIS_THROTTLE;
- } else if (temp <=
- (THROTTLING_LIMIT -
- ALERT_HYSTERESIS_THROTTLE)) {
- /* switch off throttling */
- tegra_therm_throttle(false);
+ 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;
+
+ 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;
}
-#endif
- if (temp < CELSIUS_TO_MILLICELSIUS(thermal_zones[0])) {
- lo_limit = 0;
- hi_limit = thermal_zones[0];
- } else if (temp >=
- CELSIUS_TO_MILLICELSIUS(thermal_zones[nentries-1])) {
- lo_limit = thermal_zones[nentries-1] - hysteresis;
- hi_limit = MILLICELSIUS_TO_CELSIUS(MAX_LIMIT);
+#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;
} else {
- for (i = 0; (i + 1) < nentries; i++) {
- tzone1 = thermal_zones[i];
- tzone2 = thermal_zones[i + 1];
-
- if (temp >= CELSIUS_TO_MILLICELSIUS(tzone1) &&
- temp < CELSIUS_TO_MILLICELSIUS(tzone2)) {
- lo_limit = tzone1 - hysteresis;
- hi_limit = tzone2;
+ 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);
break;
}
}
}
+#undef EDP_TEMP
+#else
+ lo_limit_edp = 0;
+ hi_limit_edp = tj_shutdown_temp;
+#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;
- err = thermal->ops->set_limits(thermal->data, lo_limit, hi_limit);
+ thermal->device->set_limits(thermal->device->data, lo_limit, hi_limit);
- if (err)
- return err;
+#ifndef CONFIG_TEGRA_THERMAL_SYSFS
+ if (tj_temp >= tj_throttle_temp) {
+ /* start throttling */
+ if (!tegra_is_throttling())
+ tegra_therm_throttle(true);
+ } else if (tj_temp <=
+ (tj_throttle_temp -
+ thermal->data.hysteresis_throttle)) {
+ /* switch off throttling */
+ if (tegra_is_throttling())
+ tegra_therm_throttle(false);
+ }
+#endif
+#ifdef CONFIG_TEGRA_EDP_LIMITS
/* inform edp governor */
- if (edp_thermal_zone_val != temp)
- /*
- * FIXME: Move this direct tegra_ function call to be called
- * via a pointer in 'struct nct1008_data' (like 'alarm_fn')
- */
- tegra_edp_update_thermal_zone(MILLICELSIUS_TO_CELSIUS(temp));
+ if (thermal->edp_thermal_zone_val != tj_temp)
+ tegra_edp_update_thermal_zone(
+ (tj_temp - thermal->data.edp_offset)/1000);
+
+ thermal->edp_thermal_zone_val = tj_temp;
+#endif
+}
- edp_thermal_zone_val = temp;
+int tegra_thermal_set_device(struct tegra_thermal_device *device)
+{
+#ifdef CONFIG_THERMAL_SYSFS
+ struct thermal_zone_device *thz;
+#endif
+
+ /* only support one device */
+ if (thermal_state.device)
+ return -EINVAL;
+
+ thermal_state.device = device;
#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- if (thermal->thz) {
- if (!thermal->thz->passive)
- thermal_zone_device_update(thermal->thz);
+ thz = thermal_zone_device_register("thermal",
+ 1, /* trips */
+ &thermal_state,
+ &tegra_thermal_zone_ops,
+ 2, /* tc1 */
+ 1, /* tc2 */
+ 2000, /* 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);
+ /* initialize limits */
+ tegra_thermal_alert(&thermal_state);
+
+ return 0;
+}
+
+int __init tegra_thermal_init(struct tegra_thermal_data *data)
+{
+#ifndef CONFIG_TEGRA_THERMAL_SYSFS
+ mutex_init(&mutex);
#endif
+ memcpy(&thermal_state.data, data, sizeof(struct tegra_thermal_data));
+
return 0;
}
int tegra_thermal_exit(void)
{
+#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+ if (thermal->thz)
+ thermal_zone_device_unregister(thermal->thz);
+#endif
+
return 0;
}