diff options
author | Alex Frid <afrid@nvidia.com> | 2011-06-27 14:36:58 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2012-03-22 23:28:10 -0700 |
commit | f5f8d6f713c16adc3732f86eef80ef50e0721178 (patch) | |
tree | d306dbf21aee036668e869433f07824ccca994de | |
parent | 793014b993f75016c4947db03b5528e5cda2b16e (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).
Original-Change-Id: Ia0e6886265aff1f624802e0415fe8cecb887b507
Reviewed-on: http://git-master/r/39918
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>
Rebase-Id: R0e0ee997ce9347470e207910f7b4f6c42143717f
-rw-r--r-- | arch/arm/mach-tegra/clock.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_clocks.c | 15 |
4 files changed, 28 insertions, 5 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 287121f5c1ab..fdbd5eec62a4 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -644,6 +644,16 @@ int tegra_is_clk_enabled(struct clk *c) } EXPORT_SYMBOL(tegra_is_clk_enabled); +int tegra_clk_shared_bus_update(struct clk *c) +{ + int ret = 0; + + if (c->ops && c->ops->shared_bus_update) + ret = c->ops->shared_bus_update(c); + + return ret; +} + /* dvfs initialization may lower default maximum rate */ void __init tegra_init_max_rate(struct clk *c, unsigned long max_rate) { diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index 822f0e9a9465..434451e1aed7 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h @@ -91,6 +91,7 @@ struct clk_ops { long (*round_rate)(struct clk *, unsigned long); int (*clk_cfg_ex)(struct clk *, enum tegra_clk_ex_param, u32); void (*reset)(struct clk *, bool); + int (*shared_bus_update)(struct clk *); }; struct clk_stats { @@ -228,6 +229,7 @@ unsigned long clk_get_max_rate(struct clk *c); unsigned long clk_get_min_rate(struct clk *c); unsigned long clk_get_rate_locked(struct clk *c); int clk_set_rate_locked(struct clk *c, unsigned long rate); +int tegra_clk_shared_bus_update(struct clk *c); int tegra_emc_set_rate(unsigned long rate); long tegra_emc_round_rate(unsigned long rate); struct clk *tegra_emc_predict_parent(unsigned long rate, u32 *div_value); diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index f7866bd91b3e..86fdb270bff9 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -159,6 +159,8 @@ static void __iomem *misc_gp_hidrev_base = IO_ADDRESS(TEGRA_APB_MISC_BASE); #define MISC_GP_HIDREV 0x804 +static int tegra2_clk_shared_bus_update(struct clk *bus); + /* * Some clocks share a register with other clocks. Any clock op that * non-atomically modifies a register used by another clock must lock @@ -525,6 +527,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 @@ -1285,6 +1288,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 */ @@ -1457,7 +1461,7 @@ static struct clk_ops tegra_cdev_clk_ops = { * enabled shared_bus_user clock, with a minimum value set by the * shared bus. */ -static int tegra_clk_shared_bus_update(struct clk *bus) +static int tegra2_clk_shared_bus_update(struct clk *bus) { struct clk *c; unsigned long rate = bus->min_rate; diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c index d5320b5acc18..f71b989fa2ba 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -295,6 +295,8 @@ /* FIXME: recommended safety delay after lock is detected */ #define PLL_POST_LOCK_DELAY 100 +static int tegra3_clk_shared_bus_update(struct clk *bus); + static bool detach_shared_bus; module_param(detach_shared_bus, bool, 0644); @@ -1162,6 +1164,7 @@ static struct clk_ops tegra_sbus_cmplx_ops = { .init = tegra3_sbus_cmplx_init, .set_rate = tegra3_sbus_cmplx_set_rate, .round_rate = tegra3_sbus_cmplx_round_rate, + .shared_bus_update = tegra3_clk_shared_bus_update, }; /* Blink output functions */ @@ -2359,6 +2362,7 @@ static struct clk_ops tegra_emc_clk_ops = { .set_rate = &tegra3_emc_clk_set_rate, .round_rate = &tegra3_emc_clk_round_rate, .reset = &tegra3_periph_clk_reset, + .shared_bus_update = &tegra3_clk_shared_bus_update, }; /* Clock doubler ops */ @@ -2641,6 +2645,7 @@ static struct clk_ops tegra_clk_cbus_ops = { .enable = tegra3_clk_cbus_enable, .set_rate = tegra3_clk_cbus_set_rate, .round_rate = tegra3_clk_cbus_round_rate, + .shared_bus_update = tegra3_clk_shared_bus_update, }; /* shared bus ops */ @@ -2651,7 +2656,7 @@ static struct clk_ops tegra_clk_cbus_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 int tegra3_clk_shared_bus_update(struct clk *bus) { struct clk *c; unsigned long rate = bus->min_rate; @@ -2659,7 +2664,7 @@ static void tegra_clk_shared_bus_update(struct clk *bus) unsigned long ceiling = bus->max_rate; if (detach_shared_bus) - return; + return 0; list_for_each_entry(c, &bus->shared_bus_list, u.shared_bus_user.node) { @@ -2683,8 +2688,10 @@ static void tegra_clk_shared_bus_update(struct clk *bus) } rate = min(max(rate, bw), ceiling); - if (rate != clk_get_rate(bus)) - clk_set_rate(bus, rate); + if (rate == clk_get_rate_locked(bus)) + return 0; + + return clk_set_rate_locked(bus, rate); }; static void tegra_clk_shared_bus_init(struct clk *c) |