summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/edp_core.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2012-11-24 19:13:04 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 12:44:54 -0700
commita42d130a9b97ebe0ed33db6b9849584c5d9e22fe (patch)
tree17d955cda95eb74b9682556bba45532fd0dd7643 /arch/arm/mach-tegra/edp_core.c
parent81b704b8c6a518e1c0764b285703517096367aca (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.c78
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__);