diff options
Diffstat (limited to 'arch/arm/mach-lpc32xx/clock.c')
-rw-r--r-- | arch/arm/mach-lpc32xx/clock.c | 62 |
1 files changed, 21 insertions, 41 deletions
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 473015ac07bd..f55c772d1816 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c | |||
@@ -82,6 +82,7 @@ | |||
82 | * will also impact the individual peripheral rates. | 82 | * will also impact the individual peripheral rates. |
83 | */ | 83 | */ |
84 | 84 | ||
85 | #include <linux/export.h> | ||
85 | #include <linux/kernel.h> | 86 | #include <linux/kernel.h> |
86 | #include <linux/list.h> | 87 | #include <linux/list.h> |
87 | #include <linux/errno.h> | 88 | #include <linux/errno.h> |
@@ -97,9 +98,10 @@ | |||
97 | #include "clock.h" | 98 | #include "clock.h" |
98 | #include "common.h" | 99 | #include "common.h" |
99 | 100 | ||
101 | static DEFINE_SPINLOCK(global_clkregs_lock); | ||
102 | |||
100 | static struct clk clk_armpll; | 103 | static struct clk clk_armpll; |
101 | static struct clk clk_usbpll; | 104 | static struct clk clk_usbpll; |
102 | static DEFINE_MUTEX(clkm_lock); | ||
103 | 105 | ||
104 | /* | 106 | /* |
105 | * Post divider values for PLLs based on selected register value | 107 | * Post divider values for PLLs based on selected register value |
@@ -127,7 +129,7 @@ static struct clk osc_32KHz = { | |||
127 | static int local_pll397_enable(struct clk *clk, int enable) | 129 | static int local_pll397_enable(struct clk *clk, int enable) |
128 | { | 130 | { |
129 | u32 reg; | 131 | u32 reg; |
130 | unsigned long timeout = 1 + msecs_to_jiffies(10); | 132 | unsigned long timeout = jiffies + msecs_to_jiffies(10); |
131 | 133 | ||
132 | reg = __raw_readl(LPC32XX_CLKPWR_PLL397_CTRL); | 134 | reg = __raw_readl(LPC32XX_CLKPWR_PLL397_CTRL); |
133 | 135 | ||
@@ -142,7 +144,7 @@ static int local_pll397_enable(struct clk *clk, int enable) | |||
142 | /* Wait for PLL397 lock */ | 144 | /* Wait for PLL397 lock */ |
143 | while (((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) & | 145 | while (((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) & |
144 | LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0) && | 146 | LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0) && |
145 | (timeout > jiffies)) | 147 | time_before(jiffies, timeout)) |
146 | cpu_relax(); | 148 | cpu_relax(); |
147 | 149 | ||
148 | if ((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) & | 150 | if ((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) & |
@@ -156,7 +158,7 @@ static int local_pll397_enable(struct clk *clk, int enable) | |||
156 | static int local_oscmain_enable(struct clk *clk, int enable) | 158 | static int local_oscmain_enable(struct clk *clk, int enable) |
157 | { | 159 | { |
158 | u32 reg; | 160 | u32 reg; |
159 | unsigned long timeout = 1 + msecs_to_jiffies(10); | 161 | unsigned long timeout = jiffies + msecs_to_jiffies(10); |
160 | 162 | ||
161 | reg = __raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL); | 163 | reg = __raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL); |
162 | 164 | ||
@@ -171,7 +173,7 @@ static int local_oscmain_enable(struct clk *clk, int enable) | |||
171 | /* Wait for main oscillator to start */ | 173 | /* Wait for main oscillator to start */ |
172 | while (((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) & | 174 | while (((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) & |
173 | LPC32XX_CLKPWR_MOSC_DISABLE) != 0) && | 175 | LPC32XX_CLKPWR_MOSC_DISABLE) != 0) && |
174 | (timeout > jiffies)) | 176 | time_before(jiffies, timeout)) |
175 | cpu_relax(); | 177 | cpu_relax(); |
176 | 178 | ||
177 | if ((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) & | 179 | if ((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) & |
@@ -383,7 +385,7 @@ static int local_usbpll_enable(struct clk *clk, int enable) | |||
383 | { | 385 | { |
384 | u32 reg; | 386 | u32 reg; |
385 | int ret = -ENODEV; | 387 | int ret = -ENODEV; |
386 | unsigned long timeout = 1 + msecs_to_jiffies(10); | 388 | unsigned long timeout = jiffies + msecs_to_jiffies(10); |
387 | 389 | ||
388 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | 390 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); |
389 | 391 | ||
@@ -396,7 +398,7 @@ static int local_usbpll_enable(struct clk *clk, int enable) | |||
396 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | 398 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); |
397 | 399 | ||
398 | /* Wait for PLL lock */ | 400 | /* Wait for PLL lock */ |
399 | while ((timeout > jiffies) & (ret == -ENODEV)) { | 401 | while (time_before(jiffies, timeout) && (ret == -ENODEV)) { |
400 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | 402 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); |
401 | if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS) | 403 | if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS) |
402 | ret = 0; | 404 | ret = 0; |
@@ -926,20 +928,8 @@ static struct clk clk_lcd = { | |||
926 | .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN, | 928 | .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN, |
927 | }; | 929 | }; |
928 | 930 | ||
929 | static inline void clk_lock(void) | ||
930 | { | ||
931 | mutex_lock(&clkm_lock); | ||
932 | } | ||
933 | |||
934 | static inline void clk_unlock(void) | ||
935 | { | ||
936 | mutex_unlock(&clkm_lock); | ||
937 | } | ||
938 | |||
939 | static void local_clk_disable(struct clk *clk) | 931 | static void local_clk_disable(struct clk *clk) |
940 | { | 932 | { |
941 | WARN_ON(clk->usecount == 0); | ||
942 | |||
943 | /* Don't attempt to disable clock if it has no users */ | 933 | /* Don't attempt to disable clock if it has no users */ |
944 | if (clk->usecount > 0) { | 934 | if (clk->usecount > 0) { |
945 | clk->usecount--; | 935 | clk->usecount--; |
@@ -982,10 +972,11 @@ static int local_clk_enable(struct clk *clk) | |||
982 | int clk_enable(struct clk *clk) | 972 | int clk_enable(struct clk *clk) |
983 | { | 973 | { |
984 | int ret; | 974 | int ret; |
975 | unsigned long flags; | ||
985 | 976 | ||
986 | clk_lock(); | 977 | spin_lock_irqsave(&global_clkregs_lock, flags); |
987 | ret = local_clk_enable(clk); | 978 | ret = local_clk_enable(clk); |
988 | clk_unlock(); | 979 | spin_unlock_irqrestore(&global_clkregs_lock, flags); |
989 | 980 | ||
990 | return ret; | 981 | return ret; |
991 | } | 982 | } |
@@ -996,9 +987,11 @@ EXPORT_SYMBOL(clk_enable); | |||
996 | */ | 987 | */ |
997 | void clk_disable(struct clk *clk) | 988 | void clk_disable(struct clk *clk) |
998 | { | 989 | { |
999 | clk_lock(); | 990 | unsigned long flags; |
991 | |||
992 | spin_lock_irqsave(&global_clkregs_lock, flags); | ||
1000 | local_clk_disable(clk); | 993 | local_clk_disable(clk); |
1001 | clk_unlock(); | 994 | spin_unlock_irqrestore(&global_clkregs_lock, flags); |
1002 | } | 995 | } |
1003 | EXPORT_SYMBOL(clk_disable); | 996 | EXPORT_SYMBOL(clk_disable); |
1004 | 997 | ||
@@ -1007,13 +1000,7 @@ EXPORT_SYMBOL(clk_disable); | |||
1007 | */ | 1000 | */ |
1008 | unsigned long clk_get_rate(struct clk *clk) | 1001 | unsigned long clk_get_rate(struct clk *clk) |
1009 | { | 1002 | { |
1010 | unsigned long rate; | 1003 | return clk->get_rate(clk); |
1011 | |||
1012 | clk_lock(); | ||
1013 | rate = clk->get_rate(clk); | ||
1014 | clk_unlock(); | ||
1015 | |||
1016 | return rate; | ||
1017 | } | 1004 | } |
1018 | EXPORT_SYMBOL(clk_get_rate); | 1005 | EXPORT_SYMBOL(clk_get_rate); |
1019 | 1006 | ||
@@ -1029,11 +1016,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
1029 | * the actual rate set as part of the peripheral dividers | 1016 | * the actual rate set as part of the peripheral dividers |
1030 | * instead of high level clock control | 1017 | * instead of high level clock control |
1031 | */ | 1018 | */ |
1032 | if (clk->set_rate) { | 1019 | if (clk->set_rate) |
1033 | clk_lock(); | ||
1034 | ret = clk->set_rate(clk, rate); | 1020 | ret = clk->set_rate(clk, rate); |
1035 | clk_unlock(); | ||
1036 | } | ||
1037 | 1021 | ||
1038 | return ret; | 1022 | return ret; |
1039 | } | 1023 | } |
@@ -1044,15 +1028,11 @@ EXPORT_SYMBOL(clk_set_rate); | |||
1044 | */ | 1028 | */ |
1045 | long clk_round_rate(struct clk *clk, unsigned long rate) | 1029 | long clk_round_rate(struct clk *clk, unsigned long rate) |
1046 | { | 1030 | { |
1047 | clk_lock(); | ||
1048 | |||
1049 | if (clk->round_rate) | 1031 | if (clk->round_rate) |
1050 | rate = clk->round_rate(clk, rate); | 1032 | rate = clk->round_rate(clk, rate); |
1051 | else | 1033 | else |
1052 | rate = clk->get_rate(clk); | 1034 | rate = clk->get_rate(clk); |
1053 | 1035 | ||
1054 | clk_unlock(); | ||
1055 | |||
1056 | return rate; | 1036 | return rate; |
1057 | } | 1037 | } |
1058 | EXPORT_SYMBOL(clk_round_rate); | 1038 | EXPORT_SYMBOL(clk_round_rate); |
@@ -1111,10 +1091,10 @@ static struct clk_lookup lookups[] = { | |||
1111 | _REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan) | 1091 | _REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan) |
1112 | _REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand) | 1092 | _REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand) |
1113 | _REGISTER_CLOCK("lpc32xx-adc", NULL, clk_adc) | 1093 | _REGISTER_CLOCK("lpc32xx-adc", NULL, clk_adc) |
1114 | _REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0) | 1094 | _REGISTER_CLOCK(NULL, "i2s0_ck", clk_i2s0) |
1115 | _REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1) | 1095 | _REGISTER_CLOCK(NULL, "i2s1_ck", clk_i2s1) |
1116 | _REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc) | 1096 | _REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc) |
1117 | _REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc) | 1097 | _REGISTER_CLOCK("dev:mmc0", NULL, clk_mmc) |
1118 | _REGISTER_CLOCK("lpc-net.0", NULL, clk_net) | 1098 | _REGISTER_CLOCK("lpc-net.0", NULL, clk_net) |
1119 | _REGISTER_CLOCK("dev:clcd", NULL, clk_lcd) | 1099 | _REGISTER_CLOCK("dev:clcd", NULL, clk_lcd) |
1120 | _REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd) | 1100 | _REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd) |