[ARM] S3C24XX: Change clock locking to use spinlocks.
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>
This commit is contained in:
parent
3055547680
commit
c3391e36d6
|
@ -37,7 +37,7 @@
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
@ -55,7 +55,11 @@
|
||||||
|
|
||||||
static LIST_HEAD(clocks);
|
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 */
|
/* enable and disable calls for use with the clk struct */
|
||||||
|
|
||||||
|
@ -77,7 +81,7 @@ struct clk *clk_get(struct device *dev, const char *id)
|
||||||
else
|
else
|
||||||
idno = to_platform_device(dev)->id;
|
idno = to_platform_device(dev)->id;
|
||||||
|
|
||||||
mutex_lock(&clocks_mutex);
|
spin_lock(&clocks_lock);
|
||||||
|
|
||||||
list_for_each_entry(p, &clocks, list) {
|
list_for_each_entry(p, &clocks, list) {
|
||||||
if (p->id == idno &&
|
if (p->id == idno &&
|
||||||
|
@ -101,7 +105,7 @@ struct clk *clk_get(struct device *dev, const char *id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&clocks_mutex);
|
spin_unlock(&clocks_lock);
|
||||||
return clk;
|
return clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,12 +121,12 @@ int clk_enable(struct clk *clk)
|
||||||
|
|
||||||
clk_enable(clk->parent);
|
clk_enable(clk->parent);
|
||||||
|
|
||||||
mutex_lock(&clocks_mutex);
|
spin_lock(&clocks_lock);
|
||||||
|
|
||||||
if ((clk->usage++) == 0)
|
if ((clk->usage++) == 0)
|
||||||
(clk->enable)(clk, 1);
|
(clk->enable)(clk, 1);
|
||||||
|
|
||||||
mutex_unlock(&clocks_mutex);
|
spin_unlock(&clocks_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,12 +135,12 @@ void clk_disable(struct clk *clk)
|
||||||
if (IS_ERR(clk) || clk == NULL)
|
if (IS_ERR(clk) || clk == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&clocks_mutex);
|
spin_lock(&clocks_lock);
|
||||||
|
|
||||||
if ((--clk->usage) == 0)
|
if ((--clk->usage) == 0)
|
||||||
(clk->enable)(clk, 0);
|
(clk->enable)(clk, 0);
|
||||||
|
|
||||||
mutex_unlock(&clocks_mutex);
|
spin_unlock(&clocks_lock);
|
||||||
clk_disable(clk->parent);
|
clk_disable(clk->parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,9 +186,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||||
if (clk->set_rate == NULL)
|
if (clk->set_rate == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&clocks_mutex);
|
spin_lock(&clocks_lock);
|
||||||
ret = (clk->set_rate)(clk, rate);
|
ret = (clk->set_rate)(clk, rate);
|
||||||
mutex_unlock(&clocks_mutex);
|
spin_unlock(&clocks_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -201,12 +205,12 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||||
if (IS_ERR(clk))
|
if (IS_ERR(clk))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&clocks_mutex);
|
spin_lock(&clocks_lock);
|
||||||
|
|
||||||
if (clk->set_parent)
|
if (clk->set_parent)
|
||||||
ret = (clk->set_parent)(clk, parent);
|
ret = (clk->set_parent)(clk, parent);
|
||||||
|
|
||||||
mutex_unlock(&clocks_mutex);
|
spin_unlock(&clocks_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -302,9 +306,9 @@ int s3c24xx_register_clock(struct clk *clk)
|
||||||
|
|
||||||
/* add to the list of available clocks */
|
/* add to the list of available clocks */
|
||||||
|
|
||||||
mutex_lock(&clocks_mutex);
|
spin_lock(&clocks_lock);
|
||||||
list_add(&clk->list, &clocks);
|
list_add(&clk->list, &clocks);
|
||||||
mutex_unlock(&clocks_mutex);
|
spin_unlock(&clocks_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
|
||||||
struct clk {
|
struct clk {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
|
@ -51,7 +53,7 @@ extern struct clk clk_xtal;
|
||||||
* Please DO NOT use these outside of arch/arm/mach-s3c2410
|
* 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);
|
extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include <linux/sysdev.h>
|
#include <linux/sysdev.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
@ -102,13 +101,13 @@ static int s3c244x_clk_add(struct sys_device *sysdev)
|
||||||
if (clk_get_rate(clock_upll) > (94 * MHZ)) {
|
if (clk_get_rate(clock_upll) > (94 * MHZ)) {
|
||||||
clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
|
clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
|
||||||
|
|
||||||
mutex_lock(&clocks_mutex);
|
spin_lock(&clocks_lock);
|
||||||
|
|
||||||
clkdivn = __raw_readl(S3C2410_CLKDIVN);
|
clkdivn = __raw_readl(S3C2410_CLKDIVN);
|
||||||
clkdivn |= S3C2440_CLKDIVN_UCLK;
|
clkdivn |= S3C2440_CLKDIVN_UCLK;
|
||||||
__raw_writel(clkdivn, S3C2410_CLKDIVN);
|
__raw_writel(clkdivn, S3C2410_CLKDIVN);
|
||||||
|
|
||||||
mutex_unlock(&clocks_mutex);
|
spin_unlock(&clocks_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue