summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorPrashant Gaikwad <pgaikwad@nvidia.com>2011-07-22 15:03:04 +0530
committerManish Tuteja <mtuteja@nvidia.com>2011-07-25 02:44:05 -0700
commitcaa12c3b3d1aac557599313be83fbd8715cc7694 (patch)
tree69055135b3d2201ff4718a27942c1caf9ba46aab /arch
parent047c82473b70803b21566f43bbabe9b7bf7423be (diff)
ARM: tegra: clock: Use bus lock to protect shared bus update
Protected shared bus update with bus lock - common for all shared bus users (update procedure was already covered by individual shared users locks, but it did not prevent concurrent access to shared rates list). Reviewed-on: http://git-master/r/39918 (cherry picked from commit 09ca93ccf0c8400a876a23eef3cd771f2f4ac9d2) Change-Id: Ie660fcb8c962712ceaa230a9dead684fcaf37d24 Reviewed-on: http://git-master/r/42589 Reviewed-by: Manish Tuteja <mtuteja@nvidia.com> Tested-by: Manish Tuteja <mtuteja@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/clock.c25
-rw-r--r--arch/arm/mach-tegra/clock.h3
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c10
3 files changed, 31 insertions, 7 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 0a61e08dcb2e..2de6093fe2e0 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -347,15 +347,12 @@ struct clk *clk_get_parent(struct clk *c)
}
EXPORT_SYMBOL(clk_get_parent);
-int clk_set_rate(struct clk *c, unsigned long rate)
+int clk_set_rate_locked(struct clk *c, unsigned long rate)
{
int ret = 0;
- unsigned long flags;
unsigned long old_rate;
long new_rate;
- clk_lock_save(c, flags);
-
if (!c->ops || !c->ops->set_rate) {
ret = -ENOSYS;
goto out;
@@ -391,6 +388,16 @@ int clk_set_rate(struct clk *c, unsigned long rate)
ret = tegra_dvfs_set_rate(c, rate);
out:
+ return ret;
+}
+
+int clk_set_rate(struct clk *c, unsigned long rate)
+{
+ int ret;
+ unsigned long flags;
+
+ clk_lock_save(c, flags);
+ ret = clk_set_rate_locked(c, rate);
clk_unlock_restore(c, flags);
return ret;
}
@@ -516,6 +523,16 @@ void tegra_periph_reset_assert(struct clk *c)
}
EXPORT_SYMBOL(tegra_periph_reset_assert);
+void tegra_clk_shared_bus_update(struct clk *c)
+{
+ unsigned long flags;
+
+ clk_lock_save(c, flags);
+ if (c->ops && c->ops->shared_bus_update)
+ c->ops->shared_bus_update(c);
+ clk_unlock_restore(c, flags);
+}
+
void __init tegra_init_clock(void)
{
tegra2_init_clocks();
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 6a1c5ba96a8a..acbabaa94b60 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -68,6 +68,7 @@ struct clk_ops {
int (*set_rate)(struct clk *, unsigned long);
long (*round_rate)(struct clk *, unsigned long);
void (*reset)(struct clk *, bool);
+ void (*shared_bus_update)(struct clk *);
};
enum clk_state {
@@ -177,6 +178,8 @@ int clk_reparent(struct clk *c, struct clk *parent);
void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
void clk_set_cansleep(struct clk *c);
unsigned long clk_get_rate_locked(struct clk *c);
+int clk_set_rate_locked(struct clk *c, unsigned long rate);
+void tegra_clk_shared_bus_update(struct clk *c);
void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
#ifdef CONFIG_CPU_FREQ
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 2331b675b510..95b7a9cbc7a1 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -154,6 +154,8 @@
static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+static void tegra2_clk_shared_bus_update(struct clk *bus);
+
/*
* Some peripheral clocks share an enable bit, so refcount the enable bits
* in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
@@ -494,6 +496,7 @@ static struct clk_ops tegra_virtual_sclk_ops = {
.init = tegra2_virtual_sclk_init,
.set_rate = tegra2_virtual_sclk_set_rate,
.round_rate = tegra2_virtual_sclk_round_rate,
+ .shared_bus_update = tegra2_clk_shared_bus_update,
};
/* virtual cop clock functions. Used to acquire the fake 'cop' clock to
@@ -1138,6 +1141,7 @@ static struct clk_ops tegra_emc_clk_ops = {
.set_rate = &tegra2_emc_clk_set_rate,
.round_rate = &tegra2_emc_clk_round_rate,
.reset = &tegra2_periph_clk_reset,
+ .shared_bus_update = &tegra2_clk_shared_bus_update,
};
/* Clock doubler ops */
@@ -1299,7 +1303,7 @@ static struct clk_ops tegra_cdev_clk_ops = {
* enabled shared_bus_user clock, with a minimum value set by the
* shared bus.
*/
-static void tegra_clk_shared_bus_update(struct clk *bus)
+static void tegra2_clk_shared_bus_update(struct clk *bus)
{
struct clk *c;
unsigned long rate = bus->min_rate;
@@ -1310,8 +1314,8 @@ static void tegra_clk_shared_bus_update(struct clk *bus)
rate = max(c->u.shared_bus_user.rate, rate);
}
- if (rate != clk_get_rate(bus))
- clk_set_rate(bus, rate);
+ if (rate != clk_get_rate_locked(bus))
+ clk_set_rate_locked(bus, rate);
};
static void tegra_clk_shared_bus_init(struct clk *c)