summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/clock.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-01-24 22:12:28 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:42:16 -0800
commitad6e170a82799cdfd7bdf5240f612b36dc151dc0 (patch)
treec34eec4e2937f1c3cb4b2aaf1a3fd41e81e18ff1 /arch/arm/mach-tegra/clock.c
parent6ea8f8522a40a988c4926fde70ed1fd159981d8f (diff)
ARM: tegra: clock: Prevent parent over-clocking
Pre-set clock rate when changing parent to avoid parent over-clocking during clock initialization from common/board specific tables. Drivers however, may still hit over-clocking error. Original-Change-Id: Ib101d85e90ab4c1194ac98680c930eebd8c56b76 Reviewed-on: http://git-master/r/16877 Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Scott Williams <scwilliams@nvidia.com> Original-Change-Id: I307e7eb507d885c381087812d262d56338aab861 Rebase-Id: R1c5fae8b3b048b31b2ed775a602ea33afb5c732e
Diffstat (limited to 'arch/arm/mach-tegra/clock.c')
-rw-r--r--arch/arm/mach-tegra/clock.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 326010e65325..dec8937821bf 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -440,6 +440,28 @@ out:
}
EXPORT_SYMBOL(clk_round_rate);
+static int tegra_clk_clip_rate_for_parent(struct clk *c, struct clk *p)
+{
+ unsigned long flags, max_rate, old_rate, new_rate;
+
+ clk_lock_save(c, flags);
+
+ max_rate = clk_get_max_rate(c);
+ new_rate = clk_predict_rate_from_parent(c, p);
+ old_rate = clk_get_rate_locked(c);
+
+ clk_unlock_restore(c, flags);
+
+ if (new_rate > max_rate) {
+ u64 rate = max_rate;
+ rate *= old_rate;
+ do_div(rate, new_rate);
+
+ return clk_set_rate(c, (unsigned long)rate);
+ }
+ return 0;
+}
+
static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
{
struct clk *c;
@@ -464,6 +486,14 @@ static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
}
if (c->parent != p) {
+ ret = tegra_clk_clip_rate_for_parent(c, p);
+ if (ret) {
+ pr_warning("Unable to clip rate for parent %s"
+ " of clock %s: %d\n",
+ table->parent, table->name, ret);
+ return -EINVAL;
+ }
+
ret = clk_set_parent(c, p);
if (ret) {
pr_warning("Unable to set parent %s of clock %s: %d\n",