diff options
author | Heiko St?bner <heiko@sntech.de> | 2011-10-14 02:08:56 -0400 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2011-10-14 02:15:49 -0400 |
commit | aab08eebdf87d3e6eda5c81f119423af63f5aee1 (patch) | |
tree | dc8b3182c00b3e4b4989d6c9a559153068804094 /arch/arm/plat-s3c24xx | |
parent | d9a3bfbd7e80ecf24d2322659d5c0542f9d95e78 (diff) |
ARM: S3C2443: Move clk_arm and clk_armdiv to common code
The system-layout of the armdiv and armclk is common to
S3C2443/S3C2416/S3C2450 and only differs in the array of
possible dividers. Therefore it is possible to reuse the
clock definitions for all of these SoCs.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/plat-s3c24xx')
-rw-r--r-- | arch/arm/plat-s3c24xx/s3c2443-clock.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/arch/arm/plat-s3c24xx/s3c2443-clock.c b/arch/arm/plat-s3c24xx/s3c2443-clock.c index 3f2117b8c0d4..f9c5b0343cf3 100644 --- a/arch/arm/plat-s3c24xx/s3c2443-clock.c +++ b/arch/arm/plat-s3c24xx/s3c2443-clock.c | |||
@@ -160,10 +160,95 @@ static struct clk clk_prediv = { | |||
160 | }, | 160 | }, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | /* armdiv | ||
164 | * | ||
165 | * this clock is sourced from msysclk and can have a number of | ||
166 | * divider values applied to it to then be fed into armclk. | ||
167 | */ | ||
168 | |||
163 | static unsigned int *armdiv; | 169 | static unsigned int *armdiv; |
164 | static int nr_armdiv; | 170 | static int nr_armdiv; |
165 | static int armdivmask; | 171 | static int armdivmask; |
166 | 172 | ||
173 | static unsigned long s3c2443_armclk_roundrate(struct clk *clk, | ||
174 | unsigned long rate) | ||
175 | { | ||
176 | unsigned long parent = clk_get_rate(clk->parent); | ||
177 | unsigned long calc; | ||
178 | unsigned best = 256; /* bigger than any value */ | ||
179 | unsigned div; | ||
180 | int ptr; | ||
181 | |||
182 | for (ptr = 0; ptr < nr_armdiv; ptr++) { | ||
183 | div = armdiv[ptr]; | ||
184 | calc = parent / div; | ||
185 | if (calc <= rate && div < best) | ||
186 | best = div; | ||
187 | } | ||
188 | |||
189 | return parent / best; | ||
190 | } | ||
191 | |||
192 | static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate) | ||
193 | { | ||
194 | unsigned long parent = clk_get_rate(clk->parent); | ||
195 | unsigned long calc; | ||
196 | unsigned div; | ||
197 | unsigned best = 256; /* bigger than any value */ | ||
198 | int ptr; | ||
199 | int val = -1; | ||
200 | |||
201 | for (ptr = 0; ptr < nr_armdiv; ptr++) { | ||
202 | div = armdiv[ptr]; | ||
203 | calc = parent / div; | ||
204 | if (calc <= rate && div < best) { | ||
205 | best = div; | ||
206 | val = ptr; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | if (val >= 0) { | ||
211 | unsigned long clkcon0; | ||
212 | |||
213 | clkcon0 = __raw_readl(S3C2443_CLKDIV0); | ||
214 | clkcon0 &= ~armdivmask; | ||
215 | clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT; | ||
216 | __raw_writel(clkcon0, S3C2443_CLKDIV0); | ||
217 | } | ||
218 | |||
219 | return (val == -1) ? -EINVAL : 0; | ||
220 | } | ||
221 | |||
222 | static struct clk clk_armdiv = { | ||
223 | .name = "armdiv", | ||
224 | .parent = &clk_msysclk.clk, | ||
225 | .ops = &(struct clk_ops) { | ||
226 | .round_rate = s3c2443_armclk_roundrate, | ||
227 | .set_rate = s3c2443_armclk_setrate, | ||
228 | }, | ||
229 | }; | ||
230 | |||
231 | /* armclk | ||
232 | * | ||
233 | * this is the clock fed into the ARM core itself, from armdiv or from hclk. | ||
234 | */ | ||
235 | |||
236 | static struct clk *clk_arm_sources[] = { | ||
237 | [0] = &clk_armdiv, | ||
238 | [1] = &clk_h, | ||
239 | }; | ||
240 | |||
241 | static struct clksrc_clk clk_arm = { | ||
242 | .clk = { | ||
243 | .name = "armclk", | ||
244 | }, | ||
245 | .sources = &(struct clksrc_sources) { | ||
246 | .sources = clk_arm_sources, | ||
247 | .nr_sources = ARRAY_SIZE(clk_arm_sources), | ||
248 | }, | ||
249 | .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 }, | ||
250 | }; | ||
251 | |||
167 | /* usbhost | 252 | /* usbhost |
168 | * | 253 | * |
169 | * usb host bus-clock, usually 48MHz to provide USB bus clock timing | 254 | * usb host bus-clock, usually 48MHz to provide USB bus clock timing |
@@ -462,6 +547,7 @@ static struct clk *clks[] __initdata = { | |||
462 | &clk_ext, | 547 | &clk_ext, |
463 | &clk_epll, | 548 | &clk_epll, |
464 | &clk_usb_bus, | 549 | &clk_usb_bus, |
550 | &clk_armdiv, | ||
465 | }; | 551 | }; |
466 | 552 | ||
467 | static struct clksrc_clk *clksrcs[] __initdata = { | 553 | static struct clksrc_clk *clksrcs[] __initdata = { |
@@ -471,6 +557,7 @@ static struct clksrc_clk *clksrcs[] __initdata = { | |||
471 | &clk_epllref, | 557 | &clk_epllref, |
472 | &clk_esysclk, | 558 | &clk_esysclk, |
473 | &clk_msysclk, | 559 | &clk_msysclk, |
560 | &clk_arm, | ||
474 | }; | 561 | }; |
475 | 562 | ||
476 | void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, | 563 | void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, |