From 5b1fcd1355485d347b3f15807561500ec06224ca Mon Sep 17 00:00:00 2001 From: Joshua Primero Date: Fri, 25 May 2012 15:54:13 -0700 Subject: drivers: skin: Skin prediction algorithm Added skin prediction algorithm. bug 1007726 Change-Id: Ia76f73cb818aa02e608e1fc69ab4d8277a5825eb Signed-off-by: Joshua Primero Reviewed-on: http://git-master/r/104814 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Sachin Nikam --- arch/arm/mach-tegra/board-cardhu-sensors.c | 54 ++- arch/arm/mach-tegra/board-cardhu.c | 78 +++- arch/arm/mach-tegra/board-enterprise-sensors.c | 5 +- arch/arm/mach-tegra/board-enterprise.c | 46 +- arch/arm/mach-tegra/board-kai-sensors.c | 3 +- arch/arm/mach-tegra/board-kai.c | 46 +- arch/arm/mach-tegra/include/mach/thermal.h | 72 ++- arch/arm/mach-tegra/tegra3_thermal.c | 605 +++++++++++++------------ arch/arm/mach-tegra/tegra3_throttle.c | 80 ++-- arch/arm/mach-tegra/tegra3_tsensor.c | 6 +- 10 files changed, 638 insertions(+), 357 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c index e4035f5f5e9b..bb6a2ae5774d 100644 --- a/arch/arm/mach-tegra/board-cardhu-sensors.c +++ b/arch/arm/mach-tegra/board-cardhu-sensors.c @@ -54,6 +54,7 @@ #include #include #include +#include #include "gpio-names.h" #include "board-cardhu.h" @@ -770,27 +771,56 @@ static int nct_set_shutdown_temp(void *_data, long shutdown_temp) return nct1008_thermal_set_shutdown_temp(data, shutdown_temp); } +#ifdef CONFIG_TEGRA_SKIN_THROTTLE +static int nct_get_itemp(void *dev_data, long *temp) +{ + struct nct1008_data *data = dev_data; + return nct1008_thermal_get_temps(data, NULL, temp); +} +#endif + static void nct1008_probe_callback(struct nct1008_data *data) { - struct tegra_thermal_device *thermal_device; + struct tegra_thermal_device *ext_nct; - thermal_device = kzalloc(sizeof(struct tegra_thermal_device), + ext_nct = kzalloc(sizeof(struct tegra_thermal_device), GFP_KERNEL); - if (!thermal_device) { + if (!ext_nct) { pr_err("unable to allocate thermal device\n"); return; } - thermal_device->name = "nct1008"; - thermal_device->data = data; - thermal_device->offset = TDIODE_OFFSET; - thermal_device->get_temp = nct_get_temp; - thermal_device->get_temp_low = nct_get_temp_low; - thermal_device->set_limits = nct_set_limits; - thermal_device->set_alert = nct_set_alert; - thermal_device->set_shutdown_temp = nct_set_shutdown_temp; + ext_nct->name = "nct_ext"; + ext_nct->id = THERMAL_DEVICE_ID_NCT_EXT; + ext_nct->data = data; + ext_nct->offset = TDIODE_OFFSET; + ext_nct->get_temp = nct_get_temp; + ext_nct->get_temp_low = nct_get_temp_low; + ext_nct->set_limits = nct_set_limits; + ext_nct->set_alert = nct_set_alert; + ext_nct->set_shutdown_temp = nct_set_shutdown_temp; + + tegra_thermal_device_register(ext_nct); - tegra_thermal_set_device(thermal_device); +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + { + struct tegra_thermal_device *int_nct; + int_nct = kzalloc(sizeof(struct tegra_thermal_device), + GFP_KERNEL); + if (!int_nct) { + kfree(int_nct); + pr_err("unable to allocate thermal device\n"); + return; + } + + int_nct->name = "nct_int"; + int_nct->id = THERMAL_DEVICE_ID_NCT_INT; + int_nct->data = data; + int_nct->get_temp = nct_get_itemp; + + tegra_thermal_device_register(int_nct); + } +#endif } static struct nct1008_platform_data cardhu_nct1008_pdata = { diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c index be1aeec820ff..4e33be32bf2d 100644 --- a/arch/arm/mach-tegra/board-cardhu.c +++ b/arch/arm/mach-tegra/board-cardhu.c @@ -71,10 +71,49 @@ #include "baseband-xmm-power.h" #include "wdt-recovery.h" +static struct balanced_throttle throttle_list[] = { +#ifdef CONFIG_TEGRA_THERMAL_THROTTLE + { + .id = BALANCED_THROTTLE_ID_TJ, + .throt_tab_size = 10, + .throt_tab = { + { 0, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 760000, 1000 }, + { 760000, 1050 }, + {1000000, 1050 }, + {1000000, 1100 }, + }, + }, +#endif +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + { + .id = BALANCED_THROTTLE_ID_SKIN, + .throt_tab_size = 6, + .throt_tab = { + { 640000, 1200 }, + { 640000, 1200 }, + { 760000, 1200 }, + { 760000, 1200 }, + {1000000, 1200 }, + {1000000, 1200 }, + }, + }, +#endif +}; + /* All units are in millicelsius */ static struct tegra_thermal_data thermal_data = { + .shutdown_device_id = THERMAL_DEVICE_ID_NCT_EXT, .temp_shutdown = 90000, - .temp_offset = TDIODE_OFFSET, /* temps based on tdiode */ + +#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE) + .throttle_edp_device_id = THERMAL_DEVICE_ID_NCT_EXT, +#endif #ifdef CONFIG_TEGRA_EDP_LIMITS .edp_offset = TDIODE_OFFSET, /* edp based on tdiode */ .hysteresis_edp = 3000, @@ -85,6 +124,39 @@ static struct tegra_thermal_data thermal_data = { .tc2 = 1, .passive_delay = 2000, #endif +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + .skin_device_id = THERMAL_DEVICE_ID_SKIN, + .temp_throttle_skin = 43000, + .tc1_skin = 0, + .tc2_skin = 1, + .passive_delay_skin = 5000, + + .skin_temp_offset = 9793, + .skin_period = 1100, + .skin_devs_size = 2, + .skin_devs = { + { + THERMAL_DEVICE_ID_NCT_EXT, + { + 2, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 0, + 1, 1, 0, 0, + 0, 0, -1, -7 + } + }, + { + THERMAL_DEVICE_ID_NCT_INT, + { + -11, -7, -5, -3, + -3, -2, -1, 0, + 0, 0, 1, 1, + 1, 2, 2, 3, + 4, 6, 11, 18 + } + }, + }, +#endif }; static struct rfkill_gpio_platform_data cardhu_bt_rfkill_pdata[] = { @@ -1295,7 +1367,9 @@ static void cardhu_sata_init(void) { } static void __init tegra_cardhu_init(void) { - tegra_thermal_init(&thermal_data); + tegra_thermal_init(&thermal_data, + throttle_list, + ARRAY_SIZE(throttle_list)); tegra_clk_init_from_table(cardhu_clk_init_table); cardhu_pinmux_init(); cardhu_i2c_init(); diff --git a/arch/arm/mach-tegra/board-enterprise-sensors.c b/arch/arm/mach-tegra/board-enterprise-sensors.c index 9bfed40325df..aab409b89ea9 100644 --- a/arch/arm/mach-tegra/board-enterprise-sensors.c +++ b/arch/arm/mach-tegra/board-enterprise-sensors.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-enterprise-sensors.c * - * Copyright (c) 2011, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -101,6 +101,7 @@ static void nct1008_probe_callback(struct nct1008_data *data) thermal_device->name = "nct1008"; thermal_device->data = data; + thermal_device->id = THERMAL_DEVICE_ID_NCT_EXT; thermal_device->offset = TDIODE_OFFSET; thermal_device->get_temp = nct_get_temp; thermal_device->get_temp_low = nct_get_temp_low; @@ -108,7 +109,7 @@ static void nct1008_probe_callback(struct nct1008_data *data) thermal_device->set_alert = nct_set_alert; thermal_device->set_shutdown_temp = nct_set_shutdown_temp; - tegra_thermal_set_device(thermal_device); + tegra_thermal_device_register(thermal_device); } static struct nct1008_platform_data enterprise_nct1008_pdata = { diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c index f73ce452e922..c44eda00e59e 100644 --- a/arch/arm/mach-tegra/board-enterprise.c +++ b/arch/arm/mach-tegra/board-enterprise.c @@ -64,10 +64,46 @@ #include "fuse.h" #include "pm.h" +static struct balanced_throttle throttle_list[] = { + { + .id = BALANCED_THROTTLE_ID_TJ, + .throt_tab_size = 10, + .throt_tab = { + { 0, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 760000, 1000 }, + { 760000, 1050 }, + {1000000, 1050 }, + {1000000, 1100 }, + }, + }, +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + { + .id = BALANCED_THROTTLE_ID_SKIN, + .throt_tab_size = 6, + .throt_tab = { + { 640000, 1200 }, + { 640000, 1200 }, + { 760000, 1200 }, + { 760000, 1200 }, + {1000000, 1200 }, + {1000000, 1200 }, + }, + }, +#endif +}; + /* All units are in millicelsius */ static struct tegra_thermal_data thermal_data = { + .shutdown_device_id = THERMAL_DEVICE_ID_NCT_EXT, .temp_shutdown = 90000, - .temp_offset = TDIODE_OFFSET, /* temps based on tdiode */ +#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE) + .throttle_edp_device_id = THERMAL_DEVICE_ID_NCT_EXT, +#endif #ifdef CONFIG_TEGRA_EDP_LIMITS .edp_offset = TDIODE_OFFSET, /* edp based on tdiode */ .hysteresis_edp = 3000, @@ -78,6 +114,10 @@ static struct tegra_thermal_data thermal_data = { .tc2 = 1, .passive_delay = 2000, #endif +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + .skin_device_id = THERMAL_DEVICE_ID_SKIN, + .temp_throttle_skin = 43000, +#endif }; static struct rfkill_gpio_platform_data enterprise_bt_rfkill_pdata[] = { @@ -915,7 +955,9 @@ static void enterprise_nfc_init(void) static void __init tegra_enterprise_init(void) { - tegra_thermal_init(&thermal_data); + tegra_thermal_init(&thermal_data, + throttle_list, + ARRAY_SIZE(throttle_list)); tegra_clk_init_from_table(enterprise_clk_init_table); enterprise_pinmux_init(); enterprise_i2c_init(); diff --git a/arch/arm/mach-tegra/board-kai-sensors.c b/arch/arm/mach-tegra/board-kai-sensors.c index c545b2d0d786..29d1bea2e8a7 100644 --- a/arch/arm/mach-tegra/board-kai-sensors.c +++ b/arch/arm/mach-tegra/board-kai-sensors.c @@ -87,6 +87,7 @@ static void nct1008_probe_callback(struct nct1008_data *data) thermal_device->name = "nct72"; thermal_device->data = data; + thermal_device->id = THERMAL_DEVICE_ID_NCT_EXT; thermal_device->offset = TDIODE_OFFSET; thermal_device->get_temp = nct_get_temp; thermal_device->get_temp_low = nct_get_temp_low; @@ -94,7 +95,7 @@ static void nct1008_probe_callback(struct nct1008_data *data) thermal_device->set_alert = nct_set_alert; thermal_device->set_shutdown_temp = nct_set_shutdown_temp; - tegra_thermal_set_device(thermal_device); + tegra_thermal_device_register(thermal_device); } #endif diff --git a/arch/arm/mach-tegra/board-kai.c b/arch/arm/mach-tegra/board-kai.c index 5dbb57b7cbb0..a2e64d8f44f6 100644 --- a/arch/arm/mach-tegra/board-kai.c +++ b/arch/arm/mach-tegra/board-kai.c @@ -67,10 +67,46 @@ #include "pm.h" #include "wdt-recovery.h" +static struct balanced_throttle throttle_list[] = { + { + .id = BALANCED_THROTTLE_ID_TJ, + .throt_tab_size = 10, + .throt_tab = { + { 0, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 640000, 1000 }, + { 760000, 1000 }, + { 760000, 1050 }, + {1000000, 1050 }, + {1000000, 1100 }, + }, + }, +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + { + .id = BALANCED_THROTTLE_ID_SKIN, + .throt_tab_size = 6, + .throt_tab = { + { 640000, 1200 }, + { 640000, 1200 }, + { 760000, 1200 }, + { 760000, 1200 }, + {1000000, 1200 }, + {1000000, 1200 }, + }, + }, +#endif +}; + /* All units are in millicelsius */ static struct tegra_thermal_data thermal_data = { + .shutdown_device_id = THERMAL_DEVICE_ID_NCT_EXT, .temp_shutdown = 90000, - .temp_offset = TDIODE_OFFSET, /* temps based on tdiode */ +#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE) + .throttle_edp_device_id = THERMAL_DEVICE_ID_NCT_EXT, +#endif #ifdef CONFIG_TEGRA_EDP_LIMITS .edp_offset = TDIODE_OFFSET, /* edp based on tdiode */ .hysteresis_edp = 3000, @@ -81,6 +117,10 @@ static struct tegra_thermal_data thermal_data = { .tc2 = 1, .passive_delay = 2000, #endif +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + .skin_device_id = THERMAL_DEVICE_ID_SKIN, + .temp_throttle_skin = 43000, +#endif }; @@ -806,7 +846,9 @@ static void kai_audio_init(void) static void __init tegra_kai_init(void) { - tegra_thermal_init(&thermal_data); + tegra_thermal_init(&thermal_data, + throttle_list, + ARRAY_SIZE(throttle_list)); tegra_clk_init_from_table(kai_clk_init_table); kai_pinmux_init(); kai_i2c_init(); diff --git a/arch/arm/mach-tegra/include/mach/thermal.h b/arch/arm/mach-tegra/include/mach/thermal.h index 78599971cd9f..ed71d0340a96 100644 --- a/arch/arm/mach-tegra/include/mach/thermal.h +++ b/arch/arm/mach-tegra/include/mach/thermal.h @@ -17,10 +17,35 @@ #ifndef __MACH_THERMAL_H #define __MACH_THERMAL_H +#include + +enum thermal_device_id { + THERMAL_DEVICE_ID_NULL = 0x0, + THERMAL_DEVICE_ID_NCT_EXT = 0x1, + THERMAL_DEVICE_ID_NCT_INT = 0x2, + THERMAL_DEVICE_ID_TSENSOR = 0x4, + THERMAL_DEVICE_ID_SKIN = 0x8, +}; + +#define THERMAL_DEVICE_MAX (4) + +enum balanced_throttle_id { + BALANCED_THROTTLE_ID_TJ, + BALANCED_THROTTLE_ID_SKIN, +}; + +struct skin_therm_est_subdevice { + enum thermal_device_id id; + long coeffs[HIST_LEN]; +}; + /* All units in millicelsius */ struct tegra_thermal_data { + enum thermal_device_id shutdown_device_id; long temp_shutdown; - long temp_offset; +#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE) + enum thermal_device_id throttle_edp_device_id; +#endif #ifdef CONFIG_TEGRA_EDP_LIMITS long edp_offset; long hysteresis_edp; @@ -31,10 +56,23 @@ struct tegra_thermal_data { int tc2; long passive_delay; #endif +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + enum thermal_device_id skin_device_id; + long temp_throttle_skin; + int tc1_skin; + int tc2_skin; + int passive_delay_skin; + + long skin_temp_offset; + long skin_period; + int skin_devs_size; + struct skin_therm_est_subdevice skin_devs[]; +#endif }; struct tegra_thermal_device { char *name; + enum thermal_device_id id; void *data; long offset; int (*get_temp) (void *, long *); @@ -45,40 +83,48 @@ struct tegra_thermal_device { #ifdef CONFIG_TEGRA_THERMAL_THROTTLE struct thermal_zone_device *thz; #endif + struct list_head node; }; -#ifdef CONFIG_TEGRA_THERMAL_THROTTLE struct throttle_table { unsigned int cpu_freq; int core_cap_level; }; +#define MAX_THROT_TABLE_SIZE (32) + struct balanced_throttle { - int id; - struct throttle_table *throt_tab; - int throt_tab_size; + enum balanced_throttle_id id; int is_throttling; int throttle_index; struct thermal_cooling_device *cdev; struct list_head node; + + int throt_tab_size; + struct throttle_table throt_tab[MAX_THROT_TABLE_SIZE]; }; -struct balanced_throttle *balanced_throttle_register( - int id, - struct throttle_table *table, - int tab_size); +#ifdef CONFIG_TEGRA_THERMAL_THROTTLE +int balanced_throttle_register(struct balanced_throttle *bthrot); +#else +static inline int balanced_throttle_register(struct balanced_throttle *bthrot) +{ return 0; } #endif #ifndef CONFIG_ARCH_TEGRA_2x_SOC -int tegra_thermal_init(struct tegra_thermal_data *data); -int tegra_thermal_set_device(struct tegra_thermal_device *device); +int tegra_thermal_init(struct tegra_thermal_data *data, + struct balanced_throttle *throttle_list, + int throttle_list_size); +int tegra_thermal_device_register(struct tegra_thermal_device *device); int tegra_thermal_exit(void); #else -static inline int tegra_thermal_init(struct tegra_thermal_data *data) +static inline int tegra_thermal_init(struct tegra_thermal_data *data, + struct balanced_throttle throttle_list, + int throttle_list_size); { return 0; } -static inline int tegra_thermal_set_device(struct tegra_thermal_device *dev) +static int tegra_thermal_device_register(struct tegra_thermal_device *device) { return 0; } static inline int tegra_thermal_exit(void) { return 0; } diff --git a/arch/arm/mach-tegra/tegra3_thermal.c b/arch/arm/mach-tegra/tegra3_thermal.c index d94158aff7d2..dcd07dd41c21 100644 --- a/arch/arm/mach-tegra/tegra3_thermal.c +++ b/arch/arm/mach-tegra/tegra3_thermal.c @@ -33,62 +33,25 @@ #include "cpu-tegra.h" #include "dvfs.h" -#define MAX_ZONES (16) +static struct tegra_thermal_data *therm; +static LIST_HEAD(tegra_therm_list); +static DEFINE_MUTEX(tegra_therm_mutex); -struct tegra_thermal { - struct tegra_thermal_device *device; - long temp_shutdown_tj; -#ifdef CONFIG_TEGRA_THERMAL_THROTTLE - long temp_throttle_tj; - int tc1; - int tc2; - long passive_delay; -#endif -#ifdef CONFIG_TEGRA_EDP_LIMITS - int edp_thermal_zone_val; - long edp_offset; - long hysteresis_edp; -#endif - struct mutex mutex; -}; +static struct balanced_throttle *throttle_list; +static int throttle_list_size; -static struct tegra_thermal thermal_state = { - .device = NULL, #ifdef CONFIG_TEGRA_EDP_LIMITS - .edp_thermal_zone_val = -1, +static long edp_thermal_zone_val; #endif -}; -#ifdef CONFIG_TEGRA_THERMAL_THROTTLE -static struct throttle_table tj_bthrot_table[] = { - { 0, 1000 }, - { 640000, 1000 }, - { 640000, 1000 }, - { 640000, 1000 }, - { 640000, 1000 }, - { 640000, 1000 }, - { 760000, 1000 }, - { 760000, 1050 }, - {1000000, 1050 }, - {1000000, 1100 }, -}; - -static struct balanced_throttle *tj_bthrot; -#define TJ_BALANCED_THROTTLE_ID (0) +#ifdef CONFIG_TEGRA_SKIN_THROTTLE +static int skin_devs_bitmap; +static struct therm_est_subdevice *skin_devs[THERMAL_DEVICE_MAX]; +static int skin_devs_count; #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; -} +#ifdef CONFIG_DEBUG_FS +static struct dentry *thermal_debugfs_root; #endif static inline long dev2tj(struct tegra_thermal_device *dev, @@ -103,19 +66,26 @@ static inline long tj2dev(struct tegra_thermal_device *dev, return tj_temp - dev->offset; } -static int tegra_thermal_get_tj_temp(long *tj_temp) +static int tegra_thermal_get_temp_unlocked(long *tj_temp, bool offsetted) { - long temp_dev; - struct tegra_thermal *thermal = &thermal_state; + struct tegra_thermal_device *dev = NULL; + int ret = 0; - if (!thermal->device) - return -1; +#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE) + list_for_each_entry(dev, &tegra_therm_list, node) + if (dev->id == therm->throttle_edp_device_id) + break; +#endif - thermal->device->get_temp(thermal->device->data, - &temp_dev); - *tj_temp = dev2tj(thermal->device, temp_dev); + if (dev) { + dev->get_temp(dev->data, tj_temp); + if (offsetted) + *tj_temp = dev2tj(dev, *tj_temp); + } else { + ret = -1; + } - return 0; + return ret; } #ifdef CONFIG_TEGRA_THERMAL_THROTTLE @@ -126,10 +96,16 @@ static int tegra_thermal_zone_bind(struct thermal_zone_device *thz, struct balanced_throttle *bthrot = cdevice->devdata; struct tegra_thermal_device *device = thz->devdata; - if ((bthrot->id == TJ_BALANCED_THROTTLE_ID) && - (device == thermal_state.device)) + if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) && + (device->id == therm->throttle_edp_device_id)) return thermal_zone_bind_cooling_device(thz, 0, cdevice); +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) && + (device->id == therm->throttle_edp_device_id)) + return thermal_zone_bind_cooling_device(thz, 0, cdevice); +#endif + return 0; } @@ -138,9 +114,15 @@ static int tegra_thermal_zone_unbind(struct thermal_zone_device *thz, struct balanced_throttle *bthrot = cdevice->devdata; struct tegra_thermal_device *device = thz->devdata; - if ((bthrot->id == TJ_BALANCED_THROTTLE_ID) && - (device == thermal_state.device)) + if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) && + (device->id == therm->throttle_edp_device_id)) + return thermal_zone_unbind_cooling_device(thz, 0, cdevice); + +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) && + (device->id == therm->skin_device_id)) return thermal_zone_unbind_cooling_device(thz, 0, cdevice); +#endif return 0; } @@ -175,7 +157,14 @@ static int tegra_thermal_zone_get_trip_temp(struct thermal_zone_device *thz, if (trip != 0) return -EINVAL; - *temp = tj2dev(device, thermal_state.temp_throttle_tj); + if (device->id == therm->throttle_edp_device_id) + *temp = therm->temp_throttle; +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + else if (device->id == therm->skin_device_id) + *temp = therm->temp_throttle_skin; +#endif + else + return -EINVAL; return 0; } @@ -189,10 +178,9 @@ static struct thermal_zone_device_ops tegra_thermal_zone_ops = { }; #endif -/* Make sure this function remains stateless */ -void tegra_thermal_alert(void *data) +static void tegra_thermal_alert_unlocked(void *data) { - struct tegra_thermal *thermal = data; + struct tegra_thermal_device *device = data; long temp_tj; long lo_limit_throttle_tj, hi_limit_throttle_tj; long lo_limit_edp_tj = 0, hi_limit_edp_tj = 0; @@ -204,34 +192,29 @@ void tegra_thermal_alert(void *data) int i; #endif - if (thermal != &thermal_state) - BUG(); - - mutex_lock(&thermal_state.mutex); - #ifdef CONFIG_TEGRA_THERMAL_THROTTLE - if (thermal->device->thz) { - if (!thermal->device->thz->passive) - thermal_zone_device_update(thermal->device->thz); + if (device->thz) { + if (!device->thz->passive) + thermal_zone_device_update(device->thz); } #endif /* Convert all temps to tj and then do all work/logic in terms of tj in order to avoid confusion */ - if (tegra_thermal_get_tj_temp(&temp_tj)) - goto done; - thermal->device->get_temp_low(thermal->device, &temp_low_dev); - temp_low_tj = dev2tj(thermal->device, temp_low_dev); + if (tegra_thermal_get_temp_unlocked(&temp_tj, true)) + return; + device->get_temp_low(device, &temp_low_dev); + temp_low_tj = dev2tj(device, temp_low_dev); lo_limit_throttle_tj = temp_low_tj; - hi_limit_throttle_tj = thermal->temp_shutdown_tj; + hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown); #ifdef CONFIG_TEGRA_THERMAL_THROTTLE - hi_limit_throttle_tj = thermal->temp_throttle_tj; + hi_limit_throttle_tj = dev2tj(device, therm->temp_throttle); - if (temp_tj > thermal->temp_throttle_tj) { - lo_limit_throttle_tj = thermal->temp_throttle_tj; - hi_limit_throttle_tj = thermal->temp_shutdown_tj; + if (temp_tj > dev2tj(device, therm->temp_throttle)) { + lo_limit_throttle_tj = dev2tj(device, therm->temp_throttle); + hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown); } #endif @@ -239,21 +222,21 @@ void tegra_thermal_alert(void *data) tegra_get_cpu_edp_limits(&z, &zones_sz); /* edp table based off of tdiode measurements */ -#define EDP_TEMP_TJ(_index) edp2tj(thermal, z[_index].temperature * 1000) +#define EDP_TEMP_TJ(_index) (z[_index].temperature * 1000 + therm->edp_offset) if (temp_tj < EDP_TEMP_TJ(0)) { lo_limit_edp_tj = temp_low_tj; 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; + therm->hysteresis_edp; + hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown); } else { for (i = 0; (i + 1) < zones_sz; i++) { 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; + therm->hysteresis_edp; hi_limit_edp_tj = EDP_TEMP_TJ(i+1); break; } @@ -262,168 +245,231 @@ void tegra_thermal_alert(void *data) #undef EDP_TEMP_TJ #else lo_limit_edp_tj = temp_low_tj; - hi_limit_edp_tj = thermal->temp_shutdown_tj; + hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown); #endif /* Get smallest window size */ 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, - tj2dev(thermal->device, lo_limit_tj), - tj2dev(thermal->device, hi_limit_tj)); + device->set_limits(device->data, + tj2dev(device, lo_limit_tj), + tj2dev(device, hi_limit_tj)); #ifdef CONFIG_TEGRA_EDP_LIMITS /* inform edp governor */ - if (thermal->edp_thermal_zone_val != temp_tj) - tegra_edp_update_thermal_zone(tj2edp(thermal, temp_tj)/1000); - - thermal->edp_thermal_zone_val = temp_tj; + if (edp_thermal_zone_val != temp_tj) { + long temp_edp = (dev2tj(device, temp_tj) - therm->edp_offset) / 1000; + tegra_edp_update_thermal_zone(temp_edp); + edp_thermal_zone_val = temp_edp; + } #endif +} -done: - mutex_unlock(&thermal_state.mutex); +/* Make sure this function remains stateless */ +void tegra_thermal_alert(void *data) +{ + mutex_lock(&tegra_therm_mutex); + tegra_thermal_alert_unlocked(data); + mutex_unlock(&tegra_therm_mutex); } +#ifdef CONFIG_TEGRA_SKIN_THROTTLE +static int tegra_skin_device_register(struct tegra_thermal_device *device) +{ + int i; + struct therm_est_subdevice *skin_dev = + kzalloc(sizeof(struct therm_est_subdevice), GFP_KERNEL); + + for (i = 0; i < therm->skin_devs_size; i++) { + if (therm->skin_devs[i].id == device->id) { + memcpy(skin_dev->coeffs, + therm->skin_devs[i].coeffs, + sizeof(skin_devs[i]->coeffs)); + break; + } + } + + skin_dev->dev_data = device->data; + skin_dev->get_temp = device->get_temp; + + skin_devs[skin_devs_count++] = skin_dev; + + /* Create skin thermal device */ + if (skin_devs_count == therm->skin_devs_size) { + struct tegra_thermal_device *thermal_skin_device; + struct therm_estimator *skin_estimator; + + skin_estimator = therm_est_register( + skin_devs, + skin_devs_count, + therm->skin_temp_offset, + therm->skin_period); + thermal_skin_device = kzalloc(sizeof(struct tegra_thermal_device), + GFP_KERNEL); + thermal_skin_device->name = "skin_pred"; + thermal_skin_device->id = THERMAL_DEVICE_ID_SKIN; + thermal_skin_device->data = skin_estimator; + thermal_skin_device->get_temp = + (int (*)(void *, long *)) therm_est_get_temp; + thermal_skin_device->set_limits = + (int (*)(void *, long, long)) therm_est_set_limits; + thermal_skin_device->set_alert = + (int (*)(void *, void (*)(void *), void *)) + therm_est_set_alert; + + tegra_thermal_device_register(thermal_skin_device); + } + return 0; +} +#endif -int tegra_thermal_set_device(struct tegra_thermal_device *device) +int tegra_thermal_device_register(struct tegra_thermal_device *device) { + struct tegra_thermal_device *dev; #ifdef CONFIG_TEGRA_THERMAL_THROTTLE struct thermal_zone_device *thz; + int t1 = 0, t2 = 0, pdelay = 0; + bool create_thz = false; #endif - /* only support one device */ - if (thermal_state.device) - return -EINVAL; - - thermal_state.device = device; + mutex_lock(&tegra_therm_mutex); + list_for_each_entry(dev, &tegra_therm_list, node) { + if (dev->id == device->id) { + mutex_unlock(&tegra_therm_mutex); + return -EINVAL; + } + } #ifdef CONFIG_TEGRA_THERMAL_THROTTLE - thz = thermal_zone_device_register(device->name, - 1, /* trips */ - device, - &tegra_thermal_zone_ops, - thermal_state.tc1, /* dT/dt */ - thermal_state.tc2, /* throttle */ - thermal_state.passive_delay, - 0); /* polling delay */ - if (IS_ERR_OR_NULL(thz)) - return -ENODEV; - - device->thz = thz; - - tj_bthrot = balanced_throttle_register( - TJ_BALANCED_THROTTLE_ID, - tj_bthrot_table, - ARRAY_SIZE(tj_bthrot_table)); - if (IS_ERR_OR_NULL(tj_bthrot)) - return -ENODEV; - + if (device->id == therm->throttle_edp_device_id) { + t1 = therm->tc1; + t2 = therm->tc2; + pdelay = therm->passive_delay; + create_thz = true; + } +#endif +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + if (device->id == therm->skin_device_id) { + t1 = 0; + t2 = 1; + pdelay = 5000; + create_thz = true; + } #endif - device->set_alert(device->data, - tegra_thermal_alert, - &thermal_state); - device->set_shutdown_temp(device->data, - tj2dev(device, thermal_state.temp_shutdown_tj)); +#ifdef CONFIG_TEGRA_THERMAL_THROTTLE + if (create_thz) { + thz = thermal_zone_device_register( + device->name, + 1, /* trips */ + device, + &tegra_thermal_zone_ops, + t1, /* dT/dt */ + t2, /* throttle */ + pdelay, + 0); /* polling delay */ + if (IS_ERR_OR_NULL(thz)) + return -ENODEV; + + device->thz = thz; + } +#endif + list_add(&device->node, &tegra_therm_list); + mutex_unlock(&tegra_therm_mutex); - /* initialize limits */ - tegra_thermal_alert(&thermal_state); + if (device->id == therm->shutdown_device_id) { + device->set_shutdown_temp(device->data, therm->temp_shutdown); + } - return 0; -} +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + if (device->id == therm->skin_device_id) { + if (create_thz) + device->set_alert(device->data, + (void (*)(void *))thermal_zone_device_update, + thz); + device->set_limits(device->data, 0, therm->temp_throttle_skin); + } +#endif -int __init tegra_thermal_init(struct tegra_thermal_data *data) -{ #ifdef CONFIG_TEGRA_THERMAL_THROTTLE - thermal_state.tc1 = data->tc1; - thermal_state.tc2 = data->tc2; - thermal_state.passive_delay = data->passive_delay; - thermal_state.temp_throttle_tj = data->temp_throttle + - data->temp_offset; -#endif - mutex_init(&thermal_state.mutex); -#ifdef CONFIG_TEGRA_EDP_LIMITS - thermal_state.edp_offset = data->edp_offset; - thermal_state.hysteresis_edp = data->hysteresis_edp; -#endif - thermal_state.temp_shutdown_tj = data->temp_shutdown + - data->temp_offset; + if (device->id == therm->throttle_edp_device_id) { + device->set_alert(device->data, tegra_thermal_alert, device); - return 0; -} + /* initialize limits */ + tegra_thermal_alert(device); + } +#endif -int tegra_thermal_exit(void) -{ -#ifdef CONFIG_TEGRA_THERMAL_THROTTLE - if (thermal_state.device->thz) - thermal_zone_device_unregister(thermal_state.device->thz); +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + if ((therm->skin_device_id == THERMAL_DEVICE_ID_SKIN) && + device->id && skin_devs_bitmap) + tegra_skin_device_register(device); #endif return 0; } -#ifdef CONFIG_DEBUG_FS - -#ifdef CONFIG_TEGRA_THERMAL_THROTTLE -static int tegra_thermal_throttle_temp_tj_set(void *data, u64 val) +/* This needs to be inialized later hand */ +static int __init throttle_list_init(void) { - mutex_lock(&thermal_state.mutex); - thermal_state.temp_throttle_tj = val; - mutex_unlock(&thermal_state.mutex); - - tegra_thermal_alert(&thermal_state); + int i; + for (i = 0; i < throttle_list_size; i++) + if (balanced_throttle_register(&throttle_list[i])) + return -ENODEV; return 0; } +late_initcall(throttle_list_init); -static int tegra_thermal_throttle_temp_tj_get(void *data, u64 *val) +int __init tegra_thermal_init(struct tegra_thermal_data *data, + struct balanced_throttle *tlist, + int tlist_size) { - *val = (u64)thermal_state.temp_throttle_tj; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(throttle_temp_tj_fops, - tegra_thermal_throttle_temp_tj_get, - tegra_thermal_throttle_temp_tj_set, - "%llu\n"); + therm = data; +#ifdef CONFIG_DEBUG_FS + thermal_debugfs_root = debugfs_create_dir("tegra_thermal", 0); #endif -static int tegra_thermal_shutdown_temp_tj_set(void *data, u64 val) -{ - thermal_state.temp_shutdown_tj = val; - - if (thermal_state.device) - thermal_state.device->set_shutdown_temp( - thermal_state.device->data, - tj2dev(thermal_state.device, - thermal_state.temp_shutdown_tj)); +#ifdef CONFIG_TEGRA_SKIN_THROTTLE + { + int i; + for (i = 0; i < therm->skin_devs_size; i++) + skin_devs_bitmap |= therm->skin_devs[i].id; + } +#endif - tegra_thermal_alert(&thermal_state); + throttle_list = tlist; + throttle_list_size = tlist_size; return 0; } -static int tegra_thermal_shutdown_temp_tj_get(void *data, u64 *val) +int tegra_thermal_exit(void) { - *val = (u64)thermal_state.temp_shutdown_tj; +#ifdef CONFIG_TEGRA_THERMAL_THROTTLE + struct tegra_thermal_device *dev; + mutex_lock(&tegra_therm_mutex); + list_for_each_entry(dev, &tegra_therm_list, node) { + thermal_zone_device_unregister(dev->thz); + } + mutex_unlock(&tegra_therm_mutex); +#endif + return 0; } -DEFINE_SIMPLE_ATTRIBUTE(shutdown_temp_tj_fops, - tegra_thermal_shutdown_temp_tj_get, - tegra_thermal_shutdown_temp_tj_set, - "%llu\n"); - - +#ifdef CONFIG_DEBUG_FS static int tegra_thermal_temp_tj_get(void *data, u64 *val) { long temp_tj; - if (tegra_thermal_get_tj_temp(&temp_tj)) + mutex_lock(&tegra_therm_mutex); + if (tegra_thermal_get_temp_unlocked(&temp_tj, false)) temp_tj = -1; + mutex_unlock(&tegra_therm_mutex); *val = (u64)temp_tj; @@ -435,98 +481,101 @@ DEFINE_SIMPLE_ATTRIBUTE(temp_tj_fops, NULL, "%llu\n"); -#ifdef CONFIG_TEGRA_THERMAL_THROTTLE -static int tegra_thermal_tc1_set(void *data, u64 val) -{ - thermal_state.device->thz->tc1 = val; - return 0; -} - -static int tegra_thermal_tc1_get(void *data, u64 *val) -{ - *val = (u64)thermal_state.device->thz->tc1; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(tc1_fops, - tegra_thermal_tc1_get, - tegra_thermal_tc1_set, - "%llu\n"); - -static int tegra_thermal_tc2_set(void *data, u64 val) -{ - thermal_state.device->thz->tc2 = val; - return 0; -} - -static int tegra_thermal_tc2_get(void *data, u64 *val) -{ - *val = (u64)thermal_state.device->thz->tc2; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(tc2_fops, - tegra_thermal_tc2_get, - tegra_thermal_tc2_set, - "%llu\n"); - -static int tegra_thermal_passive_delay_set(void *data, u64 val) +static int __init temp_tj_debug_init(void) { - thermal_state.device->thz->passive_delay = val; + debugfs_create_file("temp_tj", 0644, thermal_debugfs_root, + NULL, &temp_tj_fops); return 0; } - -static int tegra_thermal_passive_delay_get(void *data, u64 *val) -{ - *val = (u64)thermal_state.device->thz->passive_delay; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(passive_delay_fops, - tegra_thermal_passive_delay_get, - tegra_thermal_passive_delay_set, - "%llu\n"); +late_initcall(temp_tj_debug_init); + + +#define TEGRA_THERM_DEBUGFS(_name, _device_id, throttle, shutdown) \ + static int tegra_thermal_##_name##_set(void *data, u64 val) \ + { \ + struct tegra_thermal_device *dev; \ + mutex_lock(&tegra_therm_mutex); \ + therm->_name = val; \ + list_for_each_entry(dev, &tegra_therm_list, node) \ + if (dev->id == therm->_device_id) \ + break; \ + if (dev) { \ + if (throttle) \ + tegra_thermal_alert_unlocked(dev); \ + if (shutdown) \ + dev->set_shutdown_temp(dev->data, \ + therm->temp_shutdown); \ + } \ + mutex_unlock(&tegra_therm_mutex); \ + return 0; \ + } \ + static int tegra_thermal_##_name##_get(void *data, u64 *val) \ + { \ + *val = (u64)therm->_name; \ + return 0; \ + } \ + DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, \ + tegra_thermal_##_name##_get, \ + tegra_thermal_##_name##_set, \ + "%llu\n"); \ + static int __init _name##_debug_init(void) \ + { \ + debugfs_create_file(#_name, 0644, thermal_debugfs_root, \ + NULL, &_name##_fops); \ + return 0; \ + } \ + late_initcall(_name##_debug_init); + + +TEGRA_THERM_DEBUGFS(temp_shutdown, shutdown_device_id, false, true); +#ifdef CONFIG_TEGRA_THERMAL_THROTTLE +TEGRA_THERM_DEBUGFS(temp_throttle, throttle_edp_device_id, true, false); +#endif +#ifdef CONFIG_TEGRA_SKIN_THROTTLE +TEGRA_THERM_DEBUGFS(temp_throttle_skin, skin_device_id, false, false); #endif - - -static struct dentry *thermal_debugfs_root; - -static int __init tegra_thermal_debug_init(void) -{ - thermal_debugfs_root = debugfs_create_dir("tegra_thermal", 0); - - if (!debugfs_create_file("shutdown_temp_tj", 0644, thermal_debugfs_root, - NULL, &shutdown_temp_tj_fops)) - goto err_out; - - if (!debugfs_create_file("temp_tj", 0644, thermal_debugfs_root, - NULL, &temp_tj_fops)) - goto err_out; #ifdef CONFIG_TEGRA_THERMAL_THROTTLE - if (!debugfs_create_file("throttle_temp_tj", 0644, thermal_debugfs_root, - NULL, &throttle_temp_tj_fops)) - goto err_out; - - if (!debugfs_create_file("tc1", 0644, thermal_debugfs_root, - NULL, &tc1_fops)) - goto err_out; - - if (!debugfs_create_file("tc2", 0644, thermal_debugfs_root, - NULL, &tc2_fops)) - goto err_out; - - if (!debugfs_create_file("passive_delay", 0644, thermal_debugfs_root, - NULL, &passive_delay_fops)) - goto err_out; +#define THERM_DEBUGFS(_name) \ + static int tegra_thermal_##_name##_set(void *data, u64 val) \ + { \ + struct tegra_thermal_device *dev; \ + mutex_lock(&tegra_therm_mutex); \ + list_for_each_entry(dev, &tegra_therm_list, node) \ + if (dev->id == therm->throttle_edp_device_id) \ + break; \ + if (dev) \ + dev->thz->_name = val; \ + mutex_unlock(&tegra_therm_mutex); \ + return 0; \ + } \ + static int tegra_thermal_##_name##_get(void *data, u64 *val) \ + { \ + struct tegra_thermal_device *dev; \ + mutex_lock(&tegra_therm_mutex); \ + list_for_each_entry(dev, &tegra_therm_list, node) \ + if (dev->id == therm->throttle_edp_device_id) \ + break; \ + if (dev) \ + *val = (u64)dev->thz->_name; \ + mutex_unlock(&tegra_therm_mutex); \ + return 0; \ + } \ + DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, \ + tegra_thermal_##_name##_get, \ + tegra_thermal_##_name##_set, \ + "%llu\n"); \ + static int __init _name##_debug_init(void) \ + { \ + debugfs_create_file(#_name, 0644, thermal_debugfs_root, \ + NULL, &_name##_fops); \ + return 0; \ + } \ + late_initcall(_name##_debug_init); + + +THERM_DEBUGFS(tc1); +THERM_DEBUGFS(tc2); +THERM_DEBUGFS(passive_delay); #endif - - return 0; - -err_out: - debugfs_remove_recursive(thermal_debugfs_root); - return -ENOMEM; -} - -late_initcall(tegra_thermal_debug_init); #endif diff --git a/arch/arm/mach-tegra/tegra3_throttle.c b/arch/arm/mach-tegra/tegra3_throttle.c index 61dc5cdb6a7d..d980144ed052 100644 --- a/arch/arm/mach-tegra/tegra3_throttle.c +++ b/arch/arm/mach-tegra/tegra3_throttle.c @@ -33,7 +33,6 @@ #include "cpu-tegra.h" #include "dvfs.h" - static struct mutex *cpu_throttle_lock; static DEFINE_MUTEX(bthrot_list_lock); static LIST_HEAD(bthrot_list); @@ -63,13 +62,32 @@ unsigned int tegra_throttle_governor_speed(unsigned int requested_speed) struct balanced_throttle *bthrot; unsigned int throttle_speed = requested_speed; int index; + unsigned int bthrot_speed; + unsigned int lowest_speed; + struct cpufreq_frequency_table *cpu_freq_table; + struct tegra_cpufreq_table_data *table_data = + tegra_cpufreq_table_get(); + + if (!table_data) + return requested_speed; + + + cpu_freq_table = table_data->freq_table; + lowest_speed = cpu_freq_table[table_data->throttle_lowest_index].frequency; mutex_lock(&bthrot_list_lock); + list_for_each_entry(bthrot, &bthrot_list, node) { if (bthrot->is_throttling) { index = bthrot->throttle_index; - throttle_speed = min(throttle_speed, - bthrot->throt_tab[index].cpu_freq); + bthrot_speed = bthrot->throt_tab[index].cpu_freq; + + if (bthrot_speed == 0) + bthrot_speed = lowest_speed; + else + bthrot_speed = clip_to_table(bthrot_speed); + + throttle_speed = min(throttle_speed, bthrot_speed); } } mutex_unlock(&bthrot_list_lock); @@ -227,44 +245,25 @@ static struct dentry *throttle_debugfs_root; #endif /* CONFIG_DEBUG_FS */ -struct balanced_throttle *balanced_throttle_register( - int id, - struct throttle_table *table, - int tab_size) +int balanced_throttle_register(struct balanced_throttle *bthrot) { - struct balanced_throttle *bthrot; +#ifdef CONFIG_DEBUG_FS char name[32]; - int i, index; - struct cpufreq_frequency_table *cpu_freq_table; - struct tegra_cpufreq_table_data *table_data = - tegra_cpufreq_table_get(); - if (IS_ERR_OR_NULL(table_data)) - return ERR_PTR(-EINVAL); - - cpu_freq_table = table_data->freq_table; - - bthrot = kzalloc(sizeof(struct balanced_throttle), GFP_KERNEL); - - if (!bthrot) - return ERR_PTR(-ENOMEM); - - bthrot->id = id; - bthrot->throt_tab = table; - bthrot->throt_tab_size = tab_size; - +#endif + struct balanced_throttle *dev; - for (i = 0; i < bthrot->throt_tab_size; i++) { - unsigned int cpu_freq = bthrot->throt_tab[i].cpu_freq; - if (cpu_freq == 0) { - index = table_data->throttle_lowest_index; - cpu_freq = cpu_freq_table[index].frequency; - } else { - cpu_freq = clip_to_table(cpu_freq); + mutex_lock(&bthrot_list_lock); + list_for_each_entry(dev, &bthrot_list, node) { + if (dev->id == bthrot->id) { + mutex_unlock(&bthrot_list_lock); + return -EINVAL; } - - bthrot->throt_tab[i].cpu_freq = cpu_freq; } + + list_add(&bthrot->node, &bthrot_list); + mutex_unlock(&bthrot_list_lock); + bthrot->cdev = thermal_cooling_device_register( "balanced", bthrot, @@ -272,21 +271,16 @@ struct balanced_throttle *balanced_throttle_register( if (IS_ERR(bthrot->cdev)) { bthrot->cdev = NULL; - kfree(bthrot); - return ERR_PTR(-ENODEV); + return -ENODEV; } - mutex_lock(&bthrot_list_lock); - list_add(&bthrot->node, &bthrot_list); - mutex_unlock(&bthrot_list_lock); - #ifdef CONFIG_DEBUG_FS - sprintf(name, "throttle_table%d", id); + sprintf(name, "throttle_table%d", bthrot->id); debugfs_create_file(name,0644, throttle_debugfs_root, bthrot, &table_fops); #endif - return bthrot; + return 0; } int __init tegra_throttle_init(struct mutex *cpu_lock) diff --git a/arch/arm/mach-tegra/tegra3_tsensor.c b/arch/arm/mach-tegra/tegra3_tsensor.c index 01d3cd7ec627..7a1c122099bc 100644 --- a/arch/arm/mach-tegra/tegra3_tsensor.c +++ b/arch/arm/mach-tegra/tegra3_tsensor.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_tsensor.c * - * Copyright (C) 2011 NVIDIA Corporation. + * Copyright (C) 2011-2012 NVIDIA Corporation. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -107,6 +107,7 @@ static void tegra3_tsensor_probe_callback(struct tegra_tsensor_data *data) thermal_device->name = "tsensor"; thermal_device->data = data; + thermal_device->id = THERMAL_DEVICE_ID_TSENSOR; thermal_device->offset = TSENSOR_OFFSET; thermal_device->get_temp = tsensor_get_temp; thermal_device->get_temp_low = tsensor_get_temp_low; @@ -114,7 +115,8 @@ static void tegra3_tsensor_probe_callback(struct tegra_tsensor_data *data) thermal_device->set_alert = tsensor_set_alert; thermal_device->set_shutdown_temp = tsensor_set_shutdown_temp; - if (tegra_thermal_set_device(thermal_device)) /* This should not fail */ + /* This should not fail */ + if (tegra_thermal_device_register(thermal_device)) BUG(); } -- cgit v1.2.3