Skip to content

Commit

Permalink
[ARM] S3C24XX: Change clock locking to use spinlocks.
Browse files Browse the repository at this point in the history
We cannot sleep if we have cpufreq pm enabled during some
of the clock operations, so change to use a spinlock to
protect the clock system.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
  • Loading branch information
Ben Dooks committed Dec 15, 2008
1 parent 3055547 commit c3391e3
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 18 deletions.
32 changes: 18 additions & 14 deletions arch/arm/plat-s3c24xx/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/io.h>

Expand All @@ -55,7 +55,11 @@

static LIST_HEAD(clocks);

DEFINE_MUTEX(clocks_mutex);
/* We originally used an mutex here, but some contexts (see resume)
* are calling functions such as clk_set_parent() with IRQs disabled
* causing an BUG to be triggered.
*/
DEFINE_SPINLOCK(clocks_lock);

/* enable and disable calls for use with the clk struct */

Expand All @@ -77,7 +81,7 @@ struct clk *clk_get(struct device *dev, const char *id)
else
idno = to_platform_device(dev)->id;

mutex_lock(&clocks_mutex);
spin_lock(&clocks_lock);

list_for_each_entry(p, &clocks, list) {
if (p->id == idno &&
Expand All @@ -101,7 +105,7 @@ struct clk *clk_get(struct device *dev, const char *id)
}
}

mutex_unlock(&clocks_mutex);
spin_unlock(&clocks_lock);
return clk;
}

Expand All @@ -117,12 +121,12 @@ int clk_enable(struct clk *clk)

clk_enable(clk->parent);

mutex_lock(&clocks_mutex);
spin_lock(&clocks_lock);

if ((clk->usage++) == 0)
(clk->enable)(clk, 1);

mutex_unlock(&clocks_mutex);
spin_unlock(&clocks_lock);
return 0;
}

Expand All @@ -131,12 +135,12 @@ void clk_disable(struct clk *clk)
if (IS_ERR(clk) || clk == NULL)
return;

mutex_lock(&clocks_mutex);
spin_lock(&clocks_lock);

if ((--clk->usage) == 0)
(clk->enable)(clk, 0);

mutex_unlock(&clocks_mutex);
spin_unlock(&clocks_lock);
clk_disable(clk->parent);
}

Expand Down Expand Up @@ -182,9 +186,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (clk->set_rate == NULL)
return -EINVAL;

mutex_lock(&clocks_mutex);
spin_lock(&clocks_lock);
ret = (clk->set_rate)(clk, rate);
mutex_unlock(&clocks_mutex);
spin_unlock(&clocks_lock);

return ret;
}
Expand All @@ -201,12 +205,12 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
if (IS_ERR(clk))
return -EINVAL;

mutex_lock(&clocks_mutex);
spin_lock(&clocks_lock);

if (clk->set_parent)
ret = (clk->set_parent)(clk, parent);

mutex_unlock(&clocks_mutex);
spin_unlock(&clocks_lock);

return ret;
}
Expand Down Expand Up @@ -302,9 +306,9 @@ int s3c24xx_register_clock(struct clk *clk)

/* add to the list of available clocks */

mutex_lock(&clocks_mutex);
spin_lock(&clocks_lock);
list_add(&clk->list, &clocks);
mutex_unlock(&clocks_mutex);
spin_unlock(&clocks_lock);

return 0;
}
Expand Down
4 changes: 3 additions & 1 deletion arch/arm/plat-s3c24xx/include/plat/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
* published by the Free Software Foundation.
*/

#include <linux/spinlock.h>

struct clk {
struct list_head list;
struct module *owner;
Expand Down Expand Up @@ -51,7 +53,7 @@ extern struct clk clk_xtal;
* Please DO NOT use these outside of arch/arm/mach-s3c2410
*/

extern struct mutex clocks_mutex;
extern spinlock_t clocks_lock;

extern int s3c2410_clkcon_enable(struct clk *clk, int enable);

Expand Down
5 changes: 2 additions & 3 deletions arch/arm/plat-s3c24xx/s3c244x-clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#include <linux/sysdev.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/io.h>

Expand Down Expand Up @@ -102,13 +101,13 @@ static int s3c244x_clk_add(struct sys_device *sysdev)
if (clk_get_rate(clock_upll) > (94 * MHZ)) {
clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;

mutex_lock(&clocks_mutex);
spin_lock(&clocks_lock);

clkdivn = __raw_readl(S3C2410_CLKDIVN);
clkdivn |= S3C2440_CLKDIVN_UCLK;
__raw_writel(clkdivn, S3C2410_CLKDIVN);

mutex_unlock(&clocks_mutex);
spin_unlock(&clocks_lock);
}

return 0;
Expand Down

0 comments on commit c3391e3

Please sign in to comment.