summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-10-21 21:47:36 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:45 -0800
commit9738f60a41ff7910e58f3100f5dcb1fb5c2e0321 (patch)
tree893ab8c3859b3a395f6cc3360744b903ce86dab6 /arch
parent0d68bbc3997b6ef0540c08d7098b3e3d630b6d67 (diff)
ARM: tegra: clock: Update Tegra3 EMC clock configuration
- Moved initialization of Tegra3 dram configuration variables from EMC DVFS setup to EMC clock initialization, so that these variables can be used independently of DVFS. - Added graceful exit from EMC DVFS setup in case of empty DVFS table - Applied EMC minimum rate to direct EMC clock round rate operations (currently applied only to shared EMC bus update). (cherry picked from commit c6b3f6e0eb0b6e3485d02fc5306a1c09cbacf914) (cherry picked from commit cbf09d55bb9fa9c9ade7bb472859b4808f47b615) Change-Id: I84bbdc05ff7a0670ec9d088b98a9df25683db4df Reviewed-on: http://git-master/r/62029 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com> Rebase-Id: R0fb03ff9903aa51aa922b4a49eed96aad0e97a06
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/tegra3_clocks.c3
-rw-r--r--arch/arm/mach-tegra/tegra3_emc.c32
-rw-r--r--arch/arm/mach-tegra/tegra3_emc.h3
3 files changed, 25 insertions, 13 deletions
diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c
index 84b379ead5d5..3b92d7d7bec5 100644
--- a/arch/arm/mach-tegra/tegra3_clocks.c
+++ b/arch/arm/mach-tegra/tegra3_clocks.c
@@ -2329,6 +2329,7 @@ static struct clk_ops tegra_clk_out_ops = {
static void tegra3_emc_clk_init(struct clk *c)
{
tegra3_periph_clk_init(c);
+ tegra_emc_dram_type_init(c);
/* On A01 limit EMC maximum rate to boot frequency;
starting with A02 full PLLM range should be supported */
@@ -2340,7 +2341,7 @@ static void tegra3_emc_clk_init(struct clk *c)
static long tegra3_emc_clk_round_rate(struct clk *c, unsigned long rate)
{
- long new_rate = rate;
+ long new_rate = max(rate, c->min_rate);
new_rate = tegra_emc_round_rate(new_rate);
if (new_rate < 0)
diff --git a/arch/arm/mach-tegra/tegra3_emc.c b/arch/arm/mach-tegra/tegra3_emc.c
index 76fd8ff0a8c9..e8df8c8209ab 100644
--- a/arch/arm/mach-tegra/tegra3_emc.c
+++ b/arch/arm/mach-tegra/tegra3_emc.c
@@ -780,14 +780,10 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
unsigned long boot_rate, max_rate;
const struct clk_mux_sel *sel;
- emc_cfg_saved = emc_readl(EMC_CFG);
-
emc_stats.clkchange_count = 0;
spin_lock_init(&emc_stats.spinlock);
emc_stats.last_update = get_jiffies_64();
- emc = tegra_get_clock_by_name("emc");
- BUG_ON(!emc);
boot_rate = clk_get_rate(emc) / 1000;
max_rate = clk_get_max_rate(emc) / 1000;
@@ -797,6 +793,11 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
return;
}
+ if (!table || !table_size) {
+ pr_warn("tegra: EMC DFS table is empty\n");
+ return;
+ }
+
tegra_emc_table_size = min(table_size, TEGRA_EMC_TABLE_MAX_SIZE);
switch (table[0].rev) {
case 0x30:
@@ -842,22 +843,16 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
tegra_emc_clk_sel[i].value |= EMC_CLK_MC_SAME_FREQ;
}
- dram_type = (emc_readl(EMC_FBIO_CFG5) &
- EMC_CFG5_TYPE_MASK) >> EMC_CFG5_TYPE_SHIFT;
+ /* Configure clock change mode according to dram type */
if ((dram_type != DRAM_TYPE_DDR3) && (dram_type != DRAM_TYPE_LPDDR2)) {
- pr_err("Not supported DRAM type %u\n", dram_type);
+ pr_err("tegra: not supported DRAM type %u\n", dram_type);
return;
}
- if (dram_type == DRAM_TYPE_DDR3)
- emc->min_rate = EMC_MIN_RATE_DDR3;
-
reg = emc_readl(EMC_CFG_2) & (~EMC_CFG_2_MODE_MASK);
reg |= ((dram_type == DRAM_TYPE_LPDDR2) ? EMC_CFG_2_PD_MODE :
EMC_CFG_2_SREF_MODE) << EMC_CFG_2_MODE_SHIFT;
emc_writel(reg, EMC_CFG_2);
- dram_dev_num = (mc_readl(MC_EMEM_ADR_CFG) & 0x1) + 1; /* 2 dev max */
-
if (!max_entry) {
pr_err("tegra: invalid EMC DFS table: entry for max rate"
" %lu kHz is not found\n", max_rate);
@@ -878,6 +873,19 @@ void tegra_emc_timing_invalidate(void)
emc_timing_in_sync = false;
}
+void tegra_emc_dram_type_init(struct clk *c)
+{
+ emc = c;
+
+ dram_type = (emc_readl(EMC_FBIO_CFG5) &
+ EMC_CFG5_TYPE_MASK) >> EMC_CFG5_TYPE_SHIFT;
+ if (dram_type == DRAM_TYPE_DDR3)
+ emc->min_rate = EMC_MIN_RATE_DDR3;
+
+ dram_dev_num = (mc_readl(MC_EMEM_ADR_CFG) & 0x1) + 1; /* 2 dev max */
+ emc_cfg_saved = emc_readl(EMC_CFG);
+}
+
int tegra_emc_get_dram_type(void)
{
return dram_type;
diff --git a/arch/arm/mach-tegra/tegra3_emc.h b/arch/arm/mach-tegra/tegra3_emc.h
index 29c5c47994ae..24dd5655d22d 100644
--- a/arch/arm/mach-tegra/tegra3_emc.h
+++ b/arch/arm/mach-tegra/tegra3_emc.h
@@ -43,8 +43,11 @@ struct tegra_emc_table {
u32 emc_mode_2;
};
+struct clk;
+
void tegra_init_emc(const struct tegra_emc_table *table, int table_size);
+void tegra_emc_dram_type_init(struct clk *c);
int tegra_emc_get_dram_type(void);
#ifdef CONFIG_PM_SLEEP