summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-12-14 15:28:44 -0800
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-01-19 10:29:49 -0800
commit4f5892b1c1aa1ffb085333bb2412464a66910a99 (patch)
treec89dc27e341342176a60a8531385526c133de2b1
parent732dd0ebfa107da83c18bedc42f1d606271bb89c (diff)
ARM: tegra: dvfs: Add cold zone Tegra3 CPU dvfs limits
Added alternative frequency limits for Tegra3 CPU. These limits are applied only in the lowest CPU EDP temperature zone, and the offset from regular Tegra3 dvfs frequencies is set at -50MHz at all scaling voltage steps. Offset values as well as temperature threshold are to be updated per characterization. Bug 913884 Change-Id: Ia420f54b4c9fdc966e44d0269d45d9164d751b5f Signed-off-by: Alex Frid <afrid@nvidia.com> Reviewed-on: http://git-master/r/70189 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com> Tested-by: Diwakar Tundlam <dtundlam@nvidia.com> Reviewed-by: Krishna Reddy <vdumpa@nvidia.com> Reviewed-on: http://git-master/r/75615 Reviewed-by: Varun Wadekar <vwadekar@nvidia.com> Tested-by: Varun Wadekar <vwadekar@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c6
-rw-r--r--arch/arm/mach-tegra/dvfs.h4
-rw-r--r--arch/arm/mach-tegra/tegra3_dvfs.c42
3 files changed, 50 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index 5599c298ac5b..24ed5d229a5d 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -41,6 +41,7 @@
#include "clock.h"
#include "cpu-tegra.h"
+#include "dvfs.h"
/* tegra throttling and edp governors require frequencies in the table
to be in ascending order */
@@ -226,11 +227,14 @@ int tegra_edp_update_thermal_zone(int temperature)
mutex_lock(&tegra_cpu_lock);
edp_thermal_index = index;
- /* Update cpu rate if cpufreq (at least on cpu0) is already started */
+ /* Update cpu rate if cpufreq (at least on cpu0) is already started;
+ alter cpu dvfs table for this thermal zone if necessary */
+ tegra_cpu_dvfs_alter(edp_thermal_index, true);
if (target_cpu_speed[0]) {
edp_update_limit();
tegra_cpu_set_speed_cap(NULL);
}
+ tegra_cpu_dvfs_alter(edp_thermal_index, false);
mutex_unlock(&tegra_cpu_lock);
return ret;
diff --git a/arch/arm/mach-tegra/dvfs.h b/arch/arm/mach-tegra/dvfs.h
index f7e863f14f39..eaecf425fe87 100644
--- a/arch/arm/mach-tegra/dvfs.h
+++ b/arch/arm/mach-tegra/dvfs.h
@@ -125,6 +125,7 @@ int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate);
void tegra_dvfs_core_cap_enable(bool enable);
void tegra_dvfs_core_cap_level_set(int level);
int tegra_dvfs_alt_freqs_set(struct dvfs *d, bool enable);
+void tegra_cpu_dvfs_alter(int edp_thermal_index, bool before_clk_update);
#else
static inline void tegra_soc_init_dvfs(void)
{}
@@ -161,6 +162,9 @@ static inline void tegra_dvfs_core_cap_level_set(int level)
{}
static inline int tegra_dvfs_alt_freqs_set(struct dvfs *d, bool enable)
{ return 0; }
+static inline void tegra_cpu_dvfs_alter(int edp_thermal_index,
+ bool before_clk_update)
+{}
#endif
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
diff --git a/arch/arm/mach-tegra/tegra3_dvfs.c b/arch/arm/mach-tegra/tegra3_dvfs.c
index 8bd8bf7b775f..8f560ca6f7b9 100644
--- a/arch/arm/mach-tegra/tegra3_dvfs.c
+++ b/arch/arm/mach-tegra/tegra3_dvfs.c
@@ -30,10 +30,14 @@
static bool tegra_dvfs_cpu_disabled;
static bool tegra_dvfs_core_disabled;
+static struct dvfs *cpu_dvfs;
static const int cpu_millivolts[MAX_DVFS_FREQS] = {
800, 825, 850, 875, 900, 912, 975, 1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1212, 1237};
+static const unsigned int cpu_cold_offs_mhz[MAX_DVFS_FREQS] = {
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50};
+
static const int core_millivolts[MAX_DVFS_FREQS] =
{1000, 1050, 1100, 1150, 1200, 1250, 1300};
@@ -422,6 +426,31 @@ static void __init init_dvfs_one(struct dvfs *d, int nominal_mv_index)
}
}
+static void __init init_dvfs_cold(struct dvfs *d, int nominal_mv_index)
+{
+ int i;
+ unsigned long offs;
+
+ BUG_ON((nominal_mv_index == 0) || (nominal_mv_index > d->num_freqs));
+
+ for (i = 0; i < d->num_freqs; i++) {
+ offs = cpu_cold_offs_mhz[i] * MHZ;
+ if (i > nominal_mv_index)
+ d->alt_freqs[i] = d->alt_freqs[i - 1];
+ else if (d->freqs[i] > offs)
+ d->alt_freqs[i] = d->freqs[i] - offs;
+ else {
+ d->alt_freqs[i] = d->freqs[i];
+ pr_warn("tegra3_dvfs: cold offset %lu is too high for"
+ " regular dvfs limit %lu\n", offs, d->freqs[i]);
+ }
+
+ if (i)
+ BUG_ON(d->alt_freqs[i] < d->alt_freqs[i - 1]);
+ }
+ d->alt_freqs_state = ALT_FREQS_DISABLED;
+}
+
static bool __init match_dvfs_one(struct dvfs *d, int speedo_id, int process_id)
{
if ((d->process_id != -1 && d->process_id != process_id) ||
@@ -535,7 +564,6 @@ void __init tegra_soc_init_dvfs(void)
int i;
int core_nominal_mv_index;
int cpu_nominal_mv_index;
- struct dvfs *cpu_dvfs = NULL;
#ifndef CONFIG_TEGRA_CORE_DVFS
tegra_dvfs_core_disabled = true;
@@ -581,6 +609,7 @@ void __init tegra_soc_init_dvfs(void)
/* Initialize matching cpu dvfs entry already found when nominal
voltage was determined */
init_dvfs_one(cpu_dvfs, cpu_nominal_mv_index);
+ init_dvfs_cold(cpu_dvfs, cpu_nominal_mv_index);
/* Finally disable dvfs on rails if necessary */
if (tegra_dvfs_core_disabled)
@@ -596,6 +625,17 @@ void __init tegra_soc_init_dvfs(void)
tegra_dvfs_core_disabled ? "disabled" : "enabled");
}
+void tegra_cpu_dvfs_alter(int edp_thermal_index, bool before_clk_update)
+{
+ bool enable = !edp_thermal_index;
+
+ if (enable != before_clk_update) {
+ int ret = tegra_dvfs_alt_freqs_set(cpu_dvfs, enable);
+ WARN_ONCE(ret, "tegra dvfs: failed to set CPU alternative"
+ " frequency limits for cold temeperature\n");
+ }
+}
+
int tegra_dvfs_rail_disable_prepare(struct dvfs_rail *rail)
{
int ret = 0;