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 1e027514096d..0e01bf44479c 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; |
@@ -891,20 +893,8 @@ static struct clk clk_lcd = { | |||
891 | .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN, | 893 | .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN, |
892 | }; | 894 | }; |
893 | 895 | ||
894 | static inline void clk_lock(void) | ||
895 | { | ||
896 | mutex_lock(&clkm_lock); | ||
897 | } | ||
898 | |||
899 | static inline void clk_unlock(void) | ||
900 | { | ||
901 | mutex_unlock(&clkm_lock); | ||
902 | } | ||
903 | |||
904 | static void local_clk_disable(struct clk *clk) | 896 | static void local_clk_disable(struct clk *clk) |
905 | { | 897 | { |
906 | WARN_ON(clk->usecount == 0); | ||
907 | |||
908 | /* Don't attempt to disable clock if it has no users */ | 898 | /* Don't attempt to disable clock if it has no users */ |
909 | if (clk->usecount > 0) { | 899 | if (clk->usecount > 0) { |
910 | clk->usecount--; | 900 | clk->usecount--; |
@@ -947,10 +937,11 @@ static int local_clk_enable(struct clk *clk) | |||
947 | int clk_enable(struct clk *clk) | 937 | int clk_enable(struct clk *clk) |
948 | { | 938 | { |
949 | int ret; | 939 | int ret; |
940 | unsigned long flags; | ||
950 | 941 | ||
951 | clk_lock(); | 942 | spin_lock_irqsave(&global_clkregs_lock, flags); |
952 | ret = local_clk_enable(clk); | 943 | ret = local_clk_enable(clk); |
953 | clk_unlock(); | 944 | spin_unlock_irqrestore(&global_clkregs_lock, flags); |
954 | 945 | ||
955 | return ret; | 946 | return ret; |
956 | } | 947 | } |
@@ -961,9 +952,11 @@ EXPORT_SYMBOL(clk_enable); | |||
961 | */ | 952 | */ |
962 | void clk_disable(struct clk *clk) | 953 | void clk_disable(struct clk *clk) |
963 | { | 954 | { |
964 | clk_lock(); | 955 | unsigned long flags; |
956 | |||
957 | spin_lock_irqsave(&global_clkregs_lock, flags); | ||
965 | local_clk_disable(clk); | 958 | local_clk_disable(clk); |
966 | clk_unlock(); | 959 | spin_unlock_irqrestore(&global_clkregs_lock, flags); |
967 | } | 960 | } |
968 | EXPORT_SYMBOL(clk_disable); | 961 | EXPORT_SYMBOL(clk_disable); |
969 | 962 | ||
@@ -972,13 +965,7 @@ EXPORT_SYMBOL(clk_disable); | |||
972 | */ | 965 | */ |
973 | unsigned long clk_get_rate(struct clk *clk) | 966 | unsigned long clk_get_rate(struct clk *clk) |
974 | { | 967 | { |
975 | unsigned long rate; | 968 | return clk->get_rate(clk); |
976 | |||
977 | clk_lock(); | ||
978 | rate = clk->get_rate(clk); | ||
979 | clk_unlock(); | ||
980 | |||
981 | return rate; | ||
982 | } | 969 | } |
983 | EXPORT_SYMBOL(clk_get_rate); | 970 | EXPORT_SYMBOL(clk_get_rate); |
984 | 971 | ||
@@ -994,11 +981,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
994 | * the actual rate set as part of the peripheral dividers | 981 | * the actual rate set as part of the peripheral dividers |
995 | * instead of high level clock control | 982 | * instead of high level clock control |
996 | */ | 983 | */ |
997 | if (clk->set_rate) { | 984 | if (clk->set_rate) |
998 | clk_lock(); | ||
999 | ret = clk->set_rate(clk, rate); | 985 | ret = clk->set_rate(clk, rate); |
1000 | clk_unlock(); | ||
1001 | } | ||
1002 | 986 | ||
1003 | return ret; | 987 | return ret; |
1004 | } | 988 | } |
@@ -1009,15 +993,11 @@ EXPORT_SYMBOL(clk_set_rate); | |||
1009 | */ | 993 | */ |
1010 | long clk_round_rate(struct clk *clk, unsigned long rate) | 994 | long clk_round_rate(struct clk *clk, unsigned long rate) |
1011 | { | 995 | { |
1012 | clk_lock(); | ||
1013 | |||
1014 | if (clk->round_rate) | 996 | if (clk->round_rate) |
1015 | rate = clk->round_rate(clk, rate); | 997 | rate = clk->round_rate(clk, rate); |
1016 | else | 998 | else |
1017 | rate = clk->get_rate(clk); | 999 | rate = clk->get_rate(clk); |
1018 | 1000 | ||
1019 | clk_unlock(); | ||
1020 | |||
1021 | return rate; | 1001 | return rate; |
1022 | } | 1002 | } |
1023 | EXPORT_SYMBOL(clk_round_rate); | 1003 | EXPORT_SYMBOL(clk_round_rate); |
@@ -1075,10 +1055,10 @@ static struct clk_lookup lookups[] = { | |||
1075 | _REGISTER_CLOCK("dev:ssp1", NULL, clk_ssp1) | 1055 | _REGISTER_CLOCK("dev:ssp1", NULL, clk_ssp1) |
1076 | _REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan) | 1056 | _REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan) |
1077 | _REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand) | 1057 | _REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand) |
1078 | _REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0) | 1058 | _REGISTER_CLOCK(NULL, "i2s0_ck", clk_i2s0) |
1079 | _REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1) | 1059 | _REGISTER_CLOCK(NULL, "i2s1_ck", clk_i2s1) |
1080 | _REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc) | 1060 | _REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc) |
1081 | _REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc) | 1061 | _REGISTER_CLOCK("dev:mmc0", NULL, clk_mmc) |
1082 | _REGISTER_CLOCK("lpc-net.0", NULL, clk_net) | 1062 | _REGISTER_CLOCK("lpc-net.0", NULL, clk_net) |
1083 | _REGISTER_CLOCK("dev:clcd", NULL, clk_lcd) | 1063 | _REGISTER_CLOCK("dev:clcd", NULL, clk_lcd) |
1084 | _REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd) | 1064 | _REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd) |