summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra12_clocks.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2014-03-03 21:51:56 -0800
committerYu-Huan Hsu <yhsu@nvidia.com>2014-03-07 19:14:18 -0800
commitdce48a11bb2aae7e7d7c31042e6f49491146f4f8 (patch)
tree7cb5fd41a12f755f7af62d8a87cce37977b12666 /arch/arm/mach-tegra/tegra12_clocks.c
parentfd1a6febe4ef3a1acc8847b00501777ccb2c833e (diff)
ARM: tegra: power: Restore EMC clock client for CPU
This partially reverts commit bd65c015c97c87454e9dc0988485cd4191fe4d0c. It restores EMC clock client created for setting EMC frequency floor due to CPU-to-EMC direct coupling. The application of the restored client is limited to operational requirements - SoC may fail if they are not satisfied. EMC and CPU frequency scaling relations for power and performance optimization still handled via MCCPU actmon device. Tegra13 is the only tegra platform with restored direct CPU-to-EMC scaling dependency. Bug 1473244 Change-Id: Ie1771655cc6b8d304b7050dab141d356971525f8 Signed-off-by: Alex Frid <afrid@nvidia.com> Reviewed-on: http://git-master/r/377456 Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra12_clocks.c')
-rw-r--r--arch/arm/mach-tegra/tegra12_clocks.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/tegra12_clocks.c b/arch/arm/mach-tegra/tegra12_clocks.c
index 4c24e622e511..55832f68c21c 100644
--- a/arch/arm/mach-tegra/tegra12_clocks.c
+++ b/arch/arm/mach-tegra/tegra12_clocks.c
@@ -8431,8 +8431,10 @@ struct clk tegra_list_clks[] = {
SHARED_SCLK("sbc6.sclk", "tegra12-spi.5", "sclk", &tegra_clk_apb, NULL, 0, 0),
SHARED_EMC_CLK("avp.emc", "tegra-avp", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
- SHARED_EMC_CLK("mon_cpu.emc", "tegra_mon", "cpu_emc",
- &tegra_clk_emc, NULL, 0, 0, 0),
+ SHARED_EMC_CLK("mon_cpu.emc", "tegra_mon", "cpu_emc", &tegra_clk_emc, NULL, 0, 0, 0),
+#ifdef CONFIG_ARCH_TEGRA_13x_SOC
+ SHARED_EMC_CLK("cpu.emc", "tegra-cpu", "cpu_emc", &tegra_clk_emc, NULL, 0, 0, 0),
+#endif
SHARED_EMC_CLK("disp1.emc", "tegradc.0", "emc", &tegra_clk_emc, NULL, 0, SHARED_ISO_BW, BIT(EMC_USER_DC1)),
SHARED_EMC_CLK("disp2.emc", "tegradc.1", "emc", &tegra_clk_emc, NULL, 0, SHARED_ISO_BW, BIT(EMC_USER_DC2)),
SHARED_EMC_CLK("hdmi.emc", "hdmi", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
@@ -9276,6 +9278,7 @@ struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void)
return &freq_table_data;
}
+/* EMC/CPU frequency ratio for power/performance optimization */
unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate)
{
static unsigned long emc_max_rate;
@@ -9300,6 +9303,29 @@ unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate)
return 0; /* emc min */
}
+#ifdef CONFIG_ARCH_TEGRA_13x_SOC
+/* EMC/CPU frequency operational requirement limit */
+unsigned long tegra_emc_cpu_limit(unsigned long cpu_rate)
+{
+ static unsigned long last_emc_rate;
+ unsigned long emc_rate;
+
+ /* Vote on memory bus frequency based on cpu frequency;
+ cpu rate is in kHz, emc rate is in Hz */
+ if (cpu_rate > 1122000)
+ emc_rate = 600000000; /* cpu > 1.1GHz, emc 600MHz */
+ else
+ emc_rate = 300000000; /* 300MHz floor always */
+
+ /* When going down, allow some time for CPU DFLL to settle */
+ if (emc_rate < last_emc_rate)
+ udelay(200); /* FIXME: to be characterized */
+
+ last_emc_rate = emc_rate;
+ return emc_rate;
+}
+#endif
+
int tegra_update_mselect_rate(unsigned long cpu_rate)
{
static struct clk *mselect; /* statics init to 0 */