diff options
author | Alex Frid <afrid@nvidia.com> | 2012-12-03 15:01:27 -0800 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-12-05 17:43:27 -0800 |
commit | 9563d7290f7e06f1d64ed801c2cef7c802715d64 (patch) | |
tree | be14dcba4b7d1d5848db59e5ae70dc9f78bbb4c9 /arch | |
parent | 51524645b8a162309f302b8fb51be6709cd2ffb1 (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.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra11_clocks.c | 29 |
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]; |