diff options
author | Alex Frid <afrid@nvidia.com> | 2012-11-24 19:13:04 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 12:44:54 -0700 |
commit | a42d130a9b97ebe0ed33db6b9849584c5d9e22fe (patch) | |
tree | 17d955cda95eb74b9682556bba45532fd0dd7643 /arch/arm/mach-tegra/edp_core.c | |
parent | 81b704b8c6a518e1c0764b285703517096367aca (diff) |
ARM: tegra: power: Update core EDP with temperature
Added core EDP thermal layer as active cooling device, and updated
core EDP limits when temperature threshold are tripped.
Bug 1165638
Change-Id: I37cd8ab0a94909d198f21ba02e9308ca4d23bcb6
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/168929
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/edp_core.c')
-rw-r--r-- | arch/arm/mach-tegra/edp_core.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/edp_core.c b/arch/arm/mach-tegra/edp_core.c index 378916d63871..1909dd67b45c 100644 --- a/arch/arm/mach-tegra/edp_core.c +++ b/arch/arm/mach-tegra/edp_core.c @@ -23,6 +23,7 @@ #include <linux/suspend.h> #include <mach/edp.h> +#include <mach/thermal.h> #include "clock.h" #include "fuse.h" @@ -321,6 +322,78 @@ const struct attribute *core_edp_attributes[] = { static struct kobject *core_edp_kobj; +/* core edp temperature update */ +static int core_edp_get_cdev_max_state(struct thermal_cooling_device *cdev, + unsigned long *max_state) +{ + *max_state = limits ? limits->temperature_ranges - 1 : 0; + return 0; +} + +static int core_edp_get_cdev_cur_state(struct thermal_cooling_device *cdev, + unsigned long *cur_state) +{ + *cur_state = core_edp_thermal_idx; + return 0; +} + +static int core_edp_set_cdev_state(struct thermal_cooling_device *cdev, + unsigned long cur_state) +{ + int ret = 0; + unsigned long *old_cap_rates; + unsigned long *new_cap_rates; + + if (!limits) { + core_edp_thermal_idx = cur_state; + return 0; + } + + mutex_lock(&core_edp_lock); + + if (core_edp_thermal_idx != cur_state) { + old_cap_rates = get_current_cap_rates(); + new_cap_rates = get_cap_rates( + core_edp_scpu_state, core_edp_profile, + core_edp_modules_state, cur_state); + ret = update_cap_rates(new_cap_rates, old_cap_rates); + /* + * Unlike updating other state variables, temperature change + * must be always "accepted" (it's already happened) - just + * re-try one more time in case of error + */ + if (ret) + update_cap_rates(new_cap_rates, old_cap_rates); + + core_edp_thermal_idx = cur_state; + } + mutex_unlock(&core_edp_lock); + + return 0; +} + +static struct thermal_cooling_device_ops core_edp_cooling_ops = { + .get_max_state = core_edp_get_cdev_max_state, + .get_cur_state = core_edp_get_cdev_cur_state, + .set_cur_state = core_edp_set_cdev_state, +}; + +static struct tegra_cooling_device core_edp_cdev; + +struct tegra_cooling_device *tegra_core_edp_get_cdev(void) +{ + if (!limits) + return NULL; + + if (!core_edp_cdev.cdev_type) { + core_edp_cdev.cdev_type = "core_edp"; + core_edp_cdev.trip_temperatures = limits->temperatures; + core_edp_cdev.trip_temperatures_num = + limits->temperature_ranges-1; + } + return &core_edp_cdev; +} + /* * Since EMC rate on suspend exit is set to boot configuration with no regards * to EDP constraints, force profile_favor_emc on suspend entry, and restore @@ -369,6 +442,11 @@ static int __init tegra_core_edp_late_init(void) if (!limits) return 0; + /* continue on error - initialized at max temperature, anyway */ + if (IS_ERR_OR_NULL(thermal_cooling_device_register( + core_edp_cdev.cdev_type, NULL, &core_edp_cooling_ops))) + pr_err("%s: failed to register edp cooling device\n", __func__); + /* exit on error - prevent changing profile_favor_emc */ if (register_pm_notifier(&core_edp_pm_notifier)) { pr_err("%s: failed to register edp pm notifier\n", __func__); |