aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-s3c24xx
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-05 21:21:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-05 21:21:21 -0400
commitc861cd3e92d92ae946e19099f198018fcb4fd887 (patch)
treefab678a30a85cf80038c560221d6ab01812a3891 /arch/arm/plat-s3c24xx
parent7abec10c623d9e0416dab6919a0ea22e6283516b (diff)
parentb8bc83971cc20cae3c3b65c26a804f350d74960c (diff)
Merge branch 'next/devel2' of git://git.linaro.org/people/arnd/arm-soc
* 'next/devel2' of git://git.linaro.org/people/arnd/arm-soc: (30 commits) ARM: mmp: register internal sram bank ARM: mmp: register audio sram bank ARM: mmp: add sram allocator gpio/samsung: Complain loudly if we don't know the SoC ARM: S3C64XX: Fix SoC identification for S3C64xx devices ARM: S3C2443: Remove redundant s3c_register_clocks call for init_clocks ARM: S3C24XX: Add devname for hsmmc1 pclk ARM: S3C24XX: use clk_get_rate to init fclk in common_setup_clocks ARM: S3C2443: Accommodate cpufreq frequency scheme in armdiv ARM: S3C2443: handle unset armdiv values gracefully ARM: S3C2443: Add get_rate operation for clk_armdiv ARM: S3C2416: Add comment describing the armdiv/armclk ARM: S3C2443: Move clk_arm and clk_armdiv to common code ARM: S3C24XX: Add infrastructure to transmit armdiv to common code ARM: S3C2416: Add armdiv_mask constant ARM: EXYNOS4: Add support for M-5MOLS camera on Nuri board ARM: EXYNOS4: Enable MFC on ORIGEN ARM: SAMSUNG: Add support s3c2416-adc for S3C2416/S3C2450 ARM: SAMSUNG: Add support s3c2443-adc for S3C2443 ARM: SAMSUNG: Allow overriding of adc device name for S3C24XX ...
Diffstat (limited to 'arch/arm/plat-s3c24xx')
-rw-r--r--arch/arm/plat-s3c24xx/s3c2443-clock.c135
1 files changed, 130 insertions, 5 deletions
diff --git a/arch/arm/plat-s3c24xx/s3c2443-clock.c b/arch/arm/plat-s3c24xx/s3c2443-clock.c
index 07a4c81587ac..5a21b15b2a97 100644
--- a/arch/arm/plat-s3c24xx/s3c2443-clock.c
+++ b/arch/arm/plat-s3c24xx/s3c2443-clock.c
@@ -160,6 +160,124 @@ 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
169static unsigned int *armdiv;
170static int nr_armdiv;
171static int armdivmask;
172
173static 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 if (!nr_armdiv)
183 return -EINVAL;
184
185 for (ptr = 0; ptr < nr_armdiv; ptr++) {
186 div = armdiv[ptr];
187 if (div) {
188 /* cpufreq provides 266mhz as 266666000 not 266666666 */
189 calc = (parent / div / 1000) * 1000;
190 if (calc <= rate && div < best)
191 best = div;
192 }
193 }
194
195 return parent / best;
196}
197
198static unsigned long s3c2443_armclk_getrate(struct clk *clk)
199{
200 unsigned long rate = clk_get_rate(clk->parent);
201 unsigned long clkcon0;
202 int val;
203
204 if (!nr_armdiv || !armdivmask)
205 return -EINVAL;
206
207 clkcon0 = __raw_readl(S3C2443_CLKDIV0);
208 clkcon0 &= armdivmask;
209 val = clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT;
210
211 return rate / armdiv[val];
212}
213
214static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
215{
216 unsigned long parent = clk_get_rate(clk->parent);
217 unsigned long calc;
218 unsigned div;
219 unsigned best = 256; /* bigger than any value */
220 int ptr;
221 int val = -1;
222
223 if (!nr_armdiv || !armdivmask)
224 return -EINVAL;
225
226 for (ptr = 0; ptr < nr_armdiv; ptr++) {
227 div = armdiv[ptr];
228 if (div) {
229 /* cpufreq provides 266mhz as 266666000 not 266666666 */
230 calc = (parent / div / 1000) * 1000;
231 if (calc <= rate && div < best) {
232 best = div;
233 val = ptr;
234 }
235 }
236 }
237
238 if (val >= 0) {
239 unsigned long clkcon0;
240
241 clkcon0 = __raw_readl(S3C2443_CLKDIV0);
242 clkcon0 &= ~armdivmask;
243 clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
244 __raw_writel(clkcon0, S3C2443_CLKDIV0);
245 }
246
247 return (val == -1) ? -EINVAL : 0;
248}
249
250static struct clk clk_armdiv = {
251 .name = "armdiv",
252 .parent = &clk_msysclk.clk,
253 .ops = &(struct clk_ops) {
254 .round_rate = s3c2443_armclk_roundrate,
255 .get_rate = s3c2443_armclk_getrate,
256 .set_rate = s3c2443_armclk_setrate,
257 },
258};
259
260/* armclk
261 *
262 * this is the clock fed into the ARM core itself, from armdiv or from hclk.
263 */
264
265static struct clk *clk_arm_sources[] = {
266 [0] = &clk_armdiv,
267 [1] = &clk_h,
268};
269
270static struct clksrc_clk clk_arm = {
271 .clk = {
272 .name = "armclk",
273 },
274 .sources = &(struct clksrc_sources) {
275 .sources = clk_arm_sources,
276 .nr_sources = ARRAY_SIZE(clk_arm_sources),
277 },
278 .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
279};
280
163/* usbhost 281/* usbhost
164 * 282 *
165 * usb host bus-clock, usually 48MHz to provide USB bus clock timing 283 * usb host bus-clock, usually 48MHz to provide USB bus clock timing
@@ -308,6 +426,7 @@ static struct clk init_clocks[] = {
308 .ctrlbit = S3C2443_HCLKCON_DMA5, 426 .ctrlbit = S3C2443_HCLKCON_DMA5,
309 }, { 427 }, {
310 .name = "hsmmc", 428 .name = "hsmmc",
429 .devname = "s3c-sdhci.1",
311 .parent = &clk_h, 430 .parent = &clk_h,
312 .enable = s3c2443_clkcon_enable_h, 431 .enable = s3c2443_clkcon_enable_h,
313 .ctrlbit = S3C2443_HCLKCON_HSMMC, 432 .ctrlbit = S3C2443_HCLKCON_HSMMC,
@@ -402,8 +521,7 @@ static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
402 521
403/* EPLLCON compatible enough to get on/off information */ 522/* EPLLCON compatible enough to get on/off information */
404 523
405void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll, 524void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll)
406 fdiv_fn get_fdiv)
407{ 525{
408 unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); 526 unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
409 unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON); 527 unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
@@ -423,7 +541,7 @@ void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll,
423 pll = get_mpll(mpllcon, xtal); 541 pll = get_mpll(mpllcon, xtal);
424 clk_msysclk.clk.rate = pll; 542 clk_msysclk.clk.rate = pll;
425 543
426 fclk = pll / get_fdiv(clkdiv0); 544 fclk = clk_get_rate(&clk_armdiv);
427 hclk = s3c2443_prediv_getrate(&clk_prediv); 545 hclk = s3c2443_prediv_getrate(&clk_prediv);
428 hclk /= s3c2443_get_hdiv(clkdiv0); 546 hclk /= s3c2443_get_hdiv(clkdiv0);
429 pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); 547 pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
@@ -458,6 +576,7 @@ static struct clk *clks[] __initdata = {
458 &clk_ext, 576 &clk_ext,
459 &clk_epll, 577 &clk_epll,
460 &clk_usb_bus, 578 &clk_usb_bus,
579 &clk_armdiv,
461}; 580};
462 581
463static struct clksrc_clk *clksrcs[] __initdata = { 582static struct clksrc_clk *clksrcs[] __initdata = {
@@ -467,13 +586,19 @@ static struct clksrc_clk *clksrcs[] __initdata = {
467 &clk_epllref, 586 &clk_epllref,
468 &clk_esysclk, 587 &clk_esysclk,
469 &clk_msysclk, 588 &clk_msysclk,
589 &clk_arm,
470}; 590};
471 591
472void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, 592void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
473 fdiv_fn get_fdiv) 593 unsigned int *divs, int nr_divs,
594 int divmask)
474{ 595{
475 int ptr; 596 int ptr;
476 597
598 armdiv = divs;
599 nr_armdiv = nr_divs;
600 armdivmask = divmask;
601
477 /* s3c2443 parents h and p clocks from prediv */ 602 /* s3c2443 parents h and p clocks from prediv */
478 clk_h.parent = &clk_prediv; 603 clk_h.parent = &clk_prediv;
479 clk_p.parent = &clk_prediv; 604 clk_p.parent = &clk_prediv;
@@ -494,5 +619,5 @@ void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
494 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 619 s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
495 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); 620 s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
496 621
497 s3c2443_common_setup_clocks(get_mpll, get_fdiv); 622 s3c2443_common_setup_clocks(get_mpll);
498} 623}