LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Colin Cross <ccross@android.com>
To: linux-tegra@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org, konkers@android.com,
	olof@lixom.net, Colin Cross <ccross@android.com>,
	Russell King <linux@arm.linux.org.uk>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 15/21] ARM: tegra: clock: Round rate before setting rate
Date: Sun, 13 Feb 2011 01:40:27 -0800	[thread overview]
Message-ID: <1297590033-15035-16-git-send-email-ccross@android.com> (raw)
In-Reply-To: <1297590033-15035-1-git-send-email-ccross@android.com>

Call the clock's round_rate op, if it exists, before calling
the set_rate op.  This will help later when dvfs is added,
dvfs needs to know what the final rate will be before the
frequency changes.

Also requires fixes to the round rate functions to ensure
calling round rate and then set rate will not cause the
frequency to be rounded down twice.  When picking clock
divider values, the clock framework picks the closest
frequency that is lower than the requested frequency.  If
the new frequency calculated from the divider value is
rounded down, and then passed to set_rate, it will get
rounded down again, possibly resulting in a frequency two
steps lower than the original requested frequency.

Fix the problem by rounding up when calculating the frequency
coming out of a clock divider, so if that frequency is
requested again, the same divider value will be picked.

Signed-off-by: Colin Cross <ccross@android.com>
---
 arch/arm/mach-tegra/clock.c         |   13 +++++++++++++
 arch/arm/mach-tegra/tegra2_clocks.c |    8 ++++----
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 2d9ddfd..4865bb4 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -85,6 +85,7 @@ static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p)
 
 	if (c->mul != 0 && c->div != 0) {
 		rate *= c->mul;
+		rate += c->div / 2; /* round up */
 		do_div(rate, c->div);
 	}
 
@@ -242,6 +243,7 @@ int clk_set_rate(struct clk *c, unsigned long rate)
 	int ret = 0;
 	unsigned long flags;
 	unsigned long old_rate;
+	long new_rate;
 
 	spin_lock_irqsave(&c->spinlock, flags);
 
@@ -255,6 +257,17 @@ int clk_set_rate(struct clk *c, unsigned long rate)
 	if (rate > c->max_rate)
 		rate = c->max_rate;
 
+	if (c->ops && c->ops->round_rate) {
+		new_rate = c->ops->round_rate(c, rate);
+
+		if (new_rate < 0) {
+			ret = new_rate;
+			goto out;
+		}
+
+		rate = new_rate;
+	}
+
 	ret = c->ops->set_rate(c, rate);
 	if (ret)
 		goto out;
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 2f79128..96b2490 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -866,9 +866,9 @@ static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
 		divider = clk_div71_get_divider(parent_rate, rate);
 		if (divider < 0)
 			return divider;
-		return parent_rate * 2 / (divider + 2);
+		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
 	} else if (c->flags & DIV_2) {
-		return parent_rate / 2;
+		return DIV_ROUND_UP(parent_rate, 2);
 	}
 	return -EINVAL;
 }
@@ -1058,12 +1058,12 @@ static long tegra2_periph_clk_round_rate(struct clk *c,
 		if (divider < 0)
 			return divider;
 
-		return parent_rate * 2 / (divider + 2);
+		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
 	} else if (c->flags & DIV_U16) {
 		divider = clk_div16_get_divider(parent_rate, rate);
 		if (divider < 0)
 			return divider;
-		return parent_rate / (divider + 1);
+		return DIV_ROUND_UP(parent_rate, divider + 1);
 	}
 	return -EINVAL;
 }
-- 
1.7.3.1


  parent reply	other threads:[~2011-02-13  9:43 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1297590033-15035-1-git-send-email-ccross@android.com>
2011-02-13  9:40 ` [PATCH 01/21] ARM: tegra: clock: enable clk reset for non-peripheral clocks Colin Cross
2011-02-13  9:40 ` [PATCH 02/21] ARM: tegra: clock: Don't BUG on changing an enabled PLL Colin Cross
2011-02-13  9:40 ` [PATCH 03/21] ARM: tegra: clock: Drop debugging Colin Cross
2011-02-13  9:40 ` [PATCH 04/21] ARM: tegra: clock: Don't use PLL lock bits Colin Cross
2011-02-13  9:40 ` [PATCH 05/21] ARM: tegra: clock: Disable clocks left on by bootloader Colin Cross
2011-02-13  9:40 ` [PATCH 06/21] ARM: tegra: clock: Initialize clocks that have no enable Colin Cross
2011-02-13  9:40 ` [PATCH 07/21] ARM: tegra: clock: Drop CPU dvfs Colin Cross
2011-02-13  9:40 ` [PATCH 08/21] ARM: tegra: clock: Rearrange static clock tables Colin Cross
2011-02-13  9:40 ` [PATCH 09/21] ARM: tegra: clock: Move unshared clk struct members into union Colin Cross
2011-02-13  9:40 ` [PATCH 10/21] ARM: tegra: clock: Convert global lock to a lock per clock Colin Cross
2011-02-13  9:40 ` [PATCH 11/21] ARM: tegra: cpufreq: Take an extra reference to pllx Colin Cross
2011-02-13  9:40 ` [PATCH 12/21] ARM: tegra: clock: Add shared bus clock type Colin Cross
2011-02-16 20:34   ` Stephen Boyd
2011-02-16 21:01     ` Colin Cross
2011-02-16 21:51       ` Stephen Boyd
2011-02-16 22:03         ` Colin Cross
2011-02-13  9:40 ` [PATCH 13/21] ARM: tegra: clock: Remove unnecessary uses of #ifdef CONFIG_DEBUG_FS Colin Cross
2011-02-13  9:40 ` [PATCH 14/21] ARM: tegra: clock: Refcount periph clock enables Colin Cross
2011-02-13  9:40 ` Colin Cross [this message]
2011-02-13  9:40 ` [PATCH 16/21] ARM: tegra: Add external memory controller driver Colin Cross
2011-02-13  9:40 ` [PATCH 17/21] ARM: tegra: clocks: Add emc scaling Colin Cross
2011-02-13  9:40 ` [PATCH 18/21] ARM: tegra: cpufreq: Adjust memory frequency with cpu frequency Colin Cross
2011-02-13  9:40 ` [PATCH 19/21] ARM: tegra: clock: Add function to set SDMMC tap delay Colin Cross
2011-02-13  9:40 ` [PATCH 20/21] ARM: tegra: clock: Fix clock issues in suspend Colin Cross
2011-02-13  9:40 ` [PATCH 21/21] ARM: tegra: clock: Miscellaneous clock updates Colin Cross

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1297590033-15035-16-git-send-email-ccross@android.com \
    --to=ccross@android.com \
    --cc=konkers@android.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tegra@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    --cc=olof@lixom.net \
    --subject='Re: [PATCH 15/21] ARM: tegra: clock: Round rate before setting rate' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).