diff options
author | Alex Frid <afrid@nvidia.com> | 2013-09-19 15:08:33 -0700 |
---|---|---|
committer | Ajay Nandakumar <anandakumarm@nvidia.com> | 2013-10-03 19:17:28 +0530 |
commit | 0b2cb04e9f86865f507d92e677b9443849d845aa (patch) | |
tree | f990a9459b0d2b411502b7eb1dffbd1ab1bf3725 /arch/arm | |
parent | 1023b7ebd6009895dee1f92f96aaa05ffb9bdbb8 (diff) |
ARM: tegra12: clock: Support shared bus rate retention
Added Tegra12 shared bus rate retention mechanism: do not scale bus
clock to minimum rate if there is no rate request from shared users;
instead keep current bus rate.
This mechanism allows to reduce voltage scaling and pll re-locking
steps during shared bus on/off transitions provided underlying physical
clock is disabled when all floor and bandwidth users are disabled. It
should not be used with always-on buses like emc or system clock. For
now, retention is not enabled on any Tegra12 shared buses.
Change-Id: I9bc611311d0a801f11c094154a09d3456322395e
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/278178
Tested-by: Prashant Malani <pmalani@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
(cherry picked from commit 2e9524c6c42fc92bec83f032d6fe3571748e2059)
Signed-off-by: Ajay Nandakumar <anandakumarm@nvidia.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-tegra/clock.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra12_clocks.c | 18 |
3 files changed, 22 insertions, 4 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 23be76bde7b5..a3857d54ce5a 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -1684,6 +1684,11 @@ static int clk_debugfs_register_one(struct clk *c) if (!d) goto err_out; + d = debugfs_create_x32("shared_bus_flags", S_IRUGO, c->dent, + (u32 *)&c->shared_bus_flags); + if (!d) + goto err_out; + d = debugfs_create_file( "max", parent_rate_mode, c->dent, c, &max_fops); if (!d) diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index e79ba018402e..f2b4bfa74bab 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h @@ -85,6 +85,8 @@ struct clk; #define PERIPH_ON_APB (1 << 29) #define PERIPH_ON_CBUS (1 << 30) +#define SHARED_BUS_RETENTION (1 << 0) + #ifdef CONFIG_COMMON_CLK struct clk_tegra; #define to_clk_tegra(_hw) container_of(_hw, struct clk_tegra, hw) @@ -191,6 +193,7 @@ struct clk { struct clk_backup shared_bus_backup; struct clk *child_bus; unsigned long override_rate; + u32 shared_bus_flags; union { struct { diff --git a/arch/arm/mach-tegra/tegra12_clocks.c b/arch/arm/mach-tegra/tegra12_clocks.c index 93bca0a439b3..e12a179e8075 100644 --- a/arch/arm/mach-tegra/tegra12_clocks.c +++ b/arch/arm/mach-tegra/tegra12_clocks.c @@ -5619,9 +5619,12 @@ static unsigned long tegra12_clk_shared_bus_update(struct clk *bus, unsigned long ceiling = bus->max_rate; unsigned long ceiling_but_iso = bus->max_rate; u32 usage_flags = 0; + bool rate_set = false; list_for_each_entry(c, &bus->shared_bus_list, u.shared_bus_user.node) { + bool cap_user = (c->u.shared_bus_user.mode == SHARED_CEILING) || + (c->u.shared_bus_user.mode == SHARED_CEILING_BUT_ISO); /* * Ignore requests from disabled floor and bw users, and from * auto-users riding the bus. Always honor ceiling users, even @@ -5629,14 +5632,15 @@ static unsigned long tegra12_clk_shared_bus_update(struct clk *bus, * bus just because ceiling is set. Ignore SCLK/AHB/APB dividers * to propagate flat max request. */ - if (c->u.shared_bus_user.enabled || - (c->u.shared_bus_user.mode == SHARED_CEILING) || - (c->u.shared_bus_user.mode == SHARED_CEILING_BUT_ISO)) { + if (c->u.shared_bus_user.enabled || cap_user) { unsigned long request_rate = c->u.shared_bus_user.rate; if (!(c->flags & DIV_BUS)) request_rate *= c->div ? : 1; usage_flags |= c->u.shared_bus_user.usage_flag; + if (!cap_user) + rate_set = true; + switch (c->u.shared_bus_user.mode) { case SHARED_ISO_BW: iso_bw += request_rate; @@ -5702,7 +5706,13 @@ static unsigned long tegra12_clk_shared_bus_update(struct clk *bus, *bus_slow = slow; *rate_cap = ceiling; } else { - /* If satic bus dvfs table, complete rounding and aggregation */ + /* + * If satic bus dvfs table, complete rounding and aggregation. + * In case when no user requested bus rate, and bus retention + * is enabled, don't scale down - keep current rate. + */ + if (!rate_set && (bus->shared_bus_flags & SHARED_BUS_RETENTION)) + rate = clk_get_rate_locked(bus); rate = tegra12_clk_cap_shared_bus(bus, rate, ceiling); } |