summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/clock.c5
-rw-r--r--arch/arm/mach-tegra/clock.h3
-rw-r--r--arch/arm/mach-tegra/tegra12_clocks.c18
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);
}