diff options
author | Krishna Sitaraman <ksitaraman@nvidia.com> | 2014-05-23 15:52:59 -0700 |
---|---|---|
committer | Tony Ly <tly@nvidia.com> | 2014-06-05 17:06:29 -0700 |
commit | 8ebcb268c550e84885dc12774085bee06f75a3f1 (patch) | |
tree | 1256d97323b98f1d1d391514602957bebac0641b /arch/arm/mach-tegra/tegra12_clocks.c | |
parent | 32ae698081d85c4f780fae43cdff7a6b3edf7ac9 (diff) |
ARM: T132: DVFS: Cleanup cpufreq table generation
Also update table framework to easily change frequency granularity
below a given frequency.
Change-Id: I068f9e04b037e4b12bff422df5364560187ff777
Signed-off-by: Krishna Sitaraman <ksitaraman@nvidia.com>
Reviewed-on: http://git-master/r/414669
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Sai Gurrappadi <sgurrappadi@nvidia.com>
Reviewed-by: Chao Xu <cxu@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra12_clocks.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra12_clocks.c | 82 |
1 files changed, 70 insertions, 12 deletions
diff --git a/arch/arm/mach-tegra/tegra12_clocks.c b/arch/arm/mach-tegra/tegra12_clocks.c index 6be4d754a5b6..b21ee9e4a29c 100644 --- a/arch/arm/mach-tegra/tegra12_clocks.c +++ b/arch/arm/mach-tegra/tegra12_clocks.c @@ -9145,15 +9145,14 @@ void __init tegra12x_clk_init_la(void) static struct cpufreq_frequency_table freq_table[CPU_FREQ_TABLE_MAX_SIZE]; static struct tegra_cpufreq_table_data freq_table_data; +#ifndef CONFIG_ARCH_TEGRA_13x_SOC struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void) { int i, j; bool g_vmin_done = false; unsigned int freq, lp_backup_freq, g_vmin_freq, g_start_freq, max_freq; struct clk *cpu_clk_g = tegra_get_clock_by_name("cpu_g"); -#ifndef CONFIG_ARCH_TEGRA_13x_SOC struct clk *cpu_clk_lp = tegra_get_clock_by_name("cpu_lp"); -#endif /* Initialize once */ if (freq_table_data.freq_table) @@ -9165,36 +9164,28 @@ struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void) freq_table[i].frequency = CPUFREQ_TABLE_END; } -#ifndef CONFIG_ARCH_TEGRA_13x_SOC lp_backup_freq = cpu_clk_lp->u.cpu.backup_rate / 1000; -#else - lp_backup_freq = cpu_clk_g->u.cpu.backup_rate / 1000; -#endif if (!lp_backup_freq) { WARN(1, "%s: cannot make cpufreq table: no LP CPU backup rate\n", __func__); return NULL; } -#ifndef CONFIG_ARCH_TEGRA_13x_SOC if (!cpu_clk_lp->dvfs) { WARN(1, "%s: cannot make cpufreq table: no LP CPU dvfs\n", __func__); return NULL; } -#endif if (!cpu_clk_g->dvfs) { WARN(1, "%s: cannot make cpufreq table: no G CPU dvfs\n", __func__); return NULL; } g_vmin_freq = cpu_clk_g->dvfs->freqs[0] / 1000; -#ifndef CONFIG_ARCH_TEGRA_13x_SOC if (g_vmin_freq < lp_backup_freq) { WARN(1, "%s: cannot make cpufreq table: LP CPU backup rate" " exceeds G CPU rate at Vmin\n", __func__); return NULL; } -#endif /* Avoid duplicate frequency if g_vim_freq is already part of table */ if (g_vmin_freq == lp_backup_freq) g_vmin_done = true; @@ -9214,7 +9205,6 @@ struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void) * dvfs rate at minimum voltage is not missed (if it happens to be below * LP maximum rate) */ -#ifndef CONFIG_ARCH_TEGRA_13x_SOC max_freq = cpu_clk_lp->max_rate / 1000; for (j = 0; j < cpu_clk_lp->dvfs->num_freqs; j++) { freq = cpu_clk_lp->dvfs->freqs[j] / 1000; @@ -9231,7 +9221,6 @@ struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void) if (freq == max_freq) break; } -#endif /* Set G CPU min rate at least one table step below LP maximum */ cpu_clk_g->min_rate = min(freq_table[i-2].frequency, g_vmin_freq)*1000; @@ -9267,6 +9256,75 @@ struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void) return &freq_table_data; } +#else + +#define GRANULARITY_KHZ 25500 +#define GRANULARITY_END 204000 +#define CPU_THROTTLE_FREQ 408000 +#define CPU_SUSPEND_FREQ 408000 + +struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void) +{ + int i, j; + unsigned int freq, max_freq, cpu_min_freq; + struct clk *cpu_clk_g = tegra_get_clock_by_name("cpu_g"); + + /* Initialize once */ + if (freq_table_data.freq_table) + return &freq_table_data; + + /* Clean table */ + for (i = 0; i < CPU_FREQ_TABLE_MAX_SIZE; i++) { + freq_table[i].index = i; + freq_table[i].frequency = CPUFREQ_TABLE_END; + } + + if (!cpu_clk_g->dvfs) { + WARN(1, "%s: cannot make cpufreq table: no CPU dvfs\n", + __func__); + return NULL; + } + + cpu_min_freq = 204000; + + cpu_clk_g->min_rate = cpu_min_freq*1000; + + i = 0; + freq_table[i++].frequency = cpu_min_freq; + for (j=1; j <= (GRANULARITY_END - cpu_min_freq)/GRANULARITY_KHZ; j++) + freq_table[i++].frequency = cpu_min_freq + j*GRANULARITY_KHZ; + + /* Now, step along the rest of G CPU dvfs ladder */ + max_freq = cpu_clk_g->max_rate / 1000; + for (j = 0; j < cpu_clk_g->dvfs->num_freqs; j++) { + freq = cpu_clk_g->dvfs->freqs[j] / 1000; + if (freq > GRANULARITY_END) + freq_table[i++].frequency = freq; + if (freq == max_freq) + break; + } + + freq_table_data.throttle_lowest_index = 0; + freq_table_data.suspend_index = 0; + + for (j = 1; j < i; j++) { + if ((freq_table[j].frequency > CPU_THROTTLE_FREQ) && + (freq_table[j-1].frequency <= CPU_THROTTLE_FREQ)) + freq_table_data.throttle_lowest_index = j - 1; + if ((freq_table[j].frequency > CPU_SUSPEND_FREQ) && + (freq_table[j-1].frequency <= CPU_SUSPEND_FREQ)) + freq_table_data.suspend_index = j - 1; + } + + /* Throttle high index one step below maximum */ + BUG_ON(i >= CPU_FREQ_TABLE_MAX_SIZE); + freq_table_data.throttle_highest_index = i - 2; + freq_table_data.freq_table = freq_table; + return &freq_table_data; +} + +#endif + /* EMC/CPU frequency ratio for power/performance optimization */ unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate) { |