diff options
author | Joshua Primero <jprimero@nvidia.com> | 2011-10-13 17:49:20 -0700 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2011-12-08 17:03:38 +0530 |
commit | 0a892e234ce77f94973afbf2d00ea4239ee6b677 (patch) | |
tree | 60a1d541af0d8e03c93376f778caa1d9b71abf2d | |
parent | 99cd63f81e09e6dafcba8cb5e61a5b56b258fad5 (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.c | 57 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-cardhu.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-cardhu.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-enterprise-sensors.c | 61 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-enterprise.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-enterprise.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/thermal.h | 48 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_thermal.c | 301 |
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; } |