diff options
author | Alex Frid <afrid@nvidia.com> | 2011-10-21 21:47:36 -0700 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2011-10-26 15:57:50 -0700 |
commit | c6b3f6e0eb0b6e3485d02fc5306a1c09cbacf914 (patch) | |
tree | cdeeff06fdbee33ad58ee3cc5cbb2c1d34b03549 | |
parent | 677c01d3d9edaf7e91f09de5025e7864b6a288d8 (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).
Change-Id: I1338ead036bc69b3e803c76b5e2eaf51d21290cc
Reviewed-on: http://git-master/r/60117
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/tegra3_clocks.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_emc.c | 32 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_emc.h | 3 |
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 330bb7a5e1e5..405e85dc5460 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -2278,6 +2278,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 */ @@ -2289,7 +2290,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 98ad9326b375..49833f28f56a 100644 --- a/arch/arm/mach-tegra/tegra3_emc.c +++ b/arch/arm/mach-tegra/tegra3_emc.c @@ -821,14 +821,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; @@ -838,6 +834,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: @@ -883,22 +884,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); @@ -922,6 +917,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 daa313f0f516..1b525c537c57 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 |