summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2012-12-03 15:01:27 -0800
committerSimone Willett <swillett@nvidia.com>2012-12-05 17:43:27 -0800
commit9563d7290f7e06f1d64ed801c2cef7c802715d64 (patch)
treebe14dcba4b7d1d5848db59e5ae70dc9f78bbb4c9 /arch
parent51524645b8a162309f302b8fb51be6709cd2ffb1 (diff)
ARM: tegra11: clock: Support cbus scaling below Fmax@Vmin
So far, frequencies of graphics engines on cbus are scaled along the respective DVFS operating points only, which effectively set minimum scaling frequency to Fmax@Vmin level. This commit extended cbus scaling range down to the minimum rate supported by the bus parent pll with the regular frequency steps of 48MHz. Change-Id: I8289f0317d85529c5d765d8f800319eb19de6423 Signed-off-by: Alex Frid <afrid@nvidia.com> Reviewed-on: http://git-master/r/168189 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/clock.h1
-rw-r--r--arch/arm/mach-tegra/tegra11_clocks.c29
2 files changed, 21 insertions, 9 deletions
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index c0c8a3d7fb38..cbc3e23bd1ab 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -221,6 +221,7 @@ struct clk {
struct {
struct clk *top_user;
struct clk *slow_user;
+ unsigned long fmax_at_vmin;
} cbus;
struct {
struct list_head node;
diff --git a/arch/arm/mach-tegra/tegra11_clocks.c b/arch/arm/mach-tegra/tegra11_clocks.c
index 26636f65d088..aa03a67eaf24 100644
--- a/arch/arm/mach-tegra/tegra11_clocks.c
+++ b/arch/arm/mach-tegra/tegra11_clocks.c
@@ -4364,6 +4364,7 @@ static void tegra11_clk_cbus_init(struct clk *c)
{
c->state = OFF;
c->set = true;
+ c->min_rate = c->parent->min_rate;
}
static int tegra11_clk_cbus_enable(struct clk *c)
@@ -4371,30 +4372,40 @@ static int tegra11_clk_cbus_enable(struct clk *c)
return 0;
}
+#define CBUS_LOW_RATE_STEP 48000000 /* 48MHz */
+
static long tegra11_clk_cbus_round_rate(struct clk *c, unsigned long rate)
{
int i;
+ unsigned long next_rate;
- if (!c->dvfs) {
- if (!c->min_rate)
- c->min_rate = c->parent->min_rate;
- rate = max(rate, c->min_rate);
+ if (rate <= c->min_rate)
+ return c->min_rate;
+
+ if (!c->dvfs)
return rate;
- }
/* update min now, since no dvfs table was available during init
(skip placeholder entries set to 1 kHz) */
- if (!c->min_rate) {
+ if (!c->u.cbus.fmax_at_vmin) {
for (i = 0; i < (c->dvfs->num_freqs - 1); i++) {
if (c->dvfs->freqs[i] > 1 * c->dvfs->freqs_mult) {
- c->min_rate = c->dvfs->freqs[i];
+ c->u.cbus.fmax_at_vmin = c->dvfs->freqs[i];
break;
}
}
- BUG_ON(!c->min_rate);
+ BUG_ON(!c->u.cbus.fmax_at_vmin);
+ }
+
+ /* round up rates below Fmax@Vmin to the ladder with regular steps */
+ next_rate = c->u.cbus.fmax_at_vmin;
+ if (rate < next_rate) {
+ while ((rate + CBUS_LOW_RATE_STEP) < next_rate)
+ next_rate -= CBUS_LOW_RATE_STEP;
+ return next_rate;
}
- rate = max(rate, c->min_rate);
+ /* round up rates above Fmax@Vmin to DVFS ladder */
for (i = 0; i < (c->dvfs->num_freqs - 1); i++) {
unsigned long f = c->dvfs->freqs[i];
int mv = c->dvfs->millivolts[i];