aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorRoland Stigge <stigge@antcom.de>2012-02-08 15:41:05 -0500
committerOlof Johansson <olof@lixom.net>2012-02-09 19:00:33 -0500
commit93d199a13a6fb8db05d851a1afa8bf938a307be4 (patch)
tree7d6a2351696d1ca2b5622bebda64d6bb84f2fe76 /arch/arm
parent9862048abfe5fbd134553a8de30cf8767291fb1f (diff)
ARM: LPC32xx: clock.c: Fix mutex lock issues
This patch fixes the mutex issue in clock.c, as done in Kevin Wells' original driver update: In some cases, the clock drivers could grab a mutex twice in an improper context. This patch changes the mutex mechanism to a simple irq lock/unlock mechanism and removes un-needed locks from some functions. (See also git.lpclinux.com) Signed-off-by: Roland Stigge <stigge@antcom.de> Tested-by: Wolfram Sang <w.sang@pengutronix.de> Acked-by: Kevin Wells <kevin.wells@nxp.com> Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-lpc32xx/clock.c41
1 files changed, 11 insertions, 30 deletions
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
index 39dcbd0e68b2..fef863062a5e 100644
--- a/arch/arm/mach-lpc32xx/clock.c
+++ b/arch/arm/mach-lpc32xx/clock.c
@@ -97,9 +97,10 @@
97#include "clock.h" 97#include "clock.h"
98#include "common.h" 98#include "common.h"
99 99
100static DEFINE_SPINLOCK(global_clkregs_lock);
101
100static struct clk clk_armpll; 102static struct clk clk_armpll;
101static struct clk clk_usbpll; 103static struct clk clk_usbpll;
102static DEFINE_MUTEX(clkm_lock);
103 104
104/* 105/*
105 * Post divider values for PLLs based on selected register value 106 * Post divider values for PLLs based on selected register value
@@ -891,16 +892,6 @@ static struct clk clk_lcd = {
891 .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN, 892 .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
892}; 893};
893 894
894static inline void clk_lock(void)
895{
896 mutex_lock(&clkm_lock);
897}
898
899static inline void clk_unlock(void)
900{
901 mutex_unlock(&clkm_lock);
902}
903
904static void local_clk_disable(struct clk *clk) 895static void local_clk_disable(struct clk *clk)
905{ 896{
906 /* Don't attempt to disable clock if it has no users */ 897 /* Don't attempt to disable clock if it has no users */
@@ -945,10 +936,11 @@ static int local_clk_enable(struct clk *clk)
945int clk_enable(struct clk *clk) 936int clk_enable(struct clk *clk)
946{ 937{
947 int ret; 938 int ret;
939 unsigned long flags;
948 940
949 clk_lock(); 941 spin_lock_irqsave(&global_clkregs_lock, flags);
950 ret = local_clk_enable(clk); 942 ret = local_clk_enable(clk);
951 clk_unlock(); 943 spin_unlock_irqrestore(&global_clkregs_lock, flags);
952 944
953 return ret; 945 return ret;
954} 946}
@@ -959,9 +951,11 @@ EXPORT_SYMBOL(clk_enable);
959 */ 951 */
960void clk_disable(struct clk *clk) 952void clk_disable(struct clk *clk)
961{ 953{
962 clk_lock(); 954 unsigned long flags;
955
956 spin_lock_irqsave(&global_clkregs_lock, flags);
963 local_clk_disable(clk); 957 local_clk_disable(clk);
964 clk_unlock(); 958 spin_unlock_irqrestore(&global_clkregs_lock, flags);
965} 959}
966EXPORT_SYMBOL(clk_disable); 960EXPORT_SYMBOL(clk_disable);
967 961
@@ -970,13 +964,7 @@ EXPORT_SYMBOL(clk_disable);
970 */ 964 */
971unsigned long clk_get_rate(struct clk *clk) 965unsigned long clk_get_rate(struct clk *clk)
972{ 966{
973 unsigned long rate; 967 return clk->get_rate(clk);
974
975 clk_lock();
976 rate = clk->get_rate(clk);
977 clk_unlock();
978
979 return rate;
980} 968}
981EXPORT_SYMBOL(clk_get_rate); 969EXPORT_SYMBOL(clk_get_rate);
982 970
@@ -992,11 +980,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
992 * the actual rate set as part of the peripheral dividers 980 * the actual rate set as part of the peripheral dividers
993 * instead of high level clock control 981 * instead of high level clock control
994 */ 982 */
995 if (clk->set_rate) { 983 if (clk->set_rate)
996 clk_lock();
997 ret = clk->set_rate(clk, rate); 984 ret = clk->set_rate(clk, rate);
998 clk_unlock();
999 }
1000 985
1001 return ret; 986 return ret;
1002} 987}
@@ -1007,15 +992,11 @@ EXPORT_SYMBOL(clk_set_rate);
1007 */ 992 */
1008long clk_round_rate(struct clk *clk, unsigned long rate) 993long clk_round_rate(struct clk *clk, unsigned long rate)
1009{ 994{
1010 clk_lock();
1011
1012 if (clk->round_rate) 995 if (clk->round_rate)
1013 rate = clk->round_rate(clk, rate); 996 rate = clk->round_rate(clk, rate);
1014 else 997 else
1015 rate = clk->get_rate(clk); 998 rate = clk->get_rate(clk);
1016 999
1017 clk_unlock();
1018
1019 return rate; 1000 return rate;
1020} 1001}
1021EXPORT_SYMBOL(clk_round_rate); 1002EXPORT_SYMBOL(clk_round_rate);