diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-01-28 07:01:18 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-01-28 08:20:50 -0500 |
commit | bdbea34ddd2e52dc73f03e7ef7197d4c0da400d6 (patch) | |
tree | 655dbe87607c90150d11923b18bd0401c0793c87 /arch/arm/mach-s3c2412 | |
parent | 57c1b0f8dbfffaa00a242b171429e56489caef15 (diff) |
[ARM] 4778/1: S3C2412: Add armclk and init from DVS state
Add armclk to the S3C2412 to indicate the current clock connected to
the ARM core.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-s3c2412')
-rw-r--r-- | arch/arm/mach-s3c2412/clock.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c index 458993601897..42ccb5eb6042 100644 --- a/arch/arm/mach-s3c2412/clock.c +++ b/arch/arm/mach-s3c2412/clock.c | |||
@@ -234,6 +234,45 @@ static struct clk clk_msysclk = { | |||
234 | .set_parent = s3c2412_setparent_msysclk, | 234 | .set_parent = s3c2412_setparent_msysclk, |
235 | }; | 235 | }; |
236 | 236 | ||
237 | static int s3c2412_setparent_armclk(struct clk *clk, struct clk *parent) | ||
238 | { | ||
239 | unsigned long flags; | ||
240 | unsigned long clkdiv; | ||
241 | unsigned long dvs; | ||
242 | |||
243 | /* Note, we current equate fclk andf msysclk for S3C2412 */ | ||
244 | |||
245 | if (parent == &clk_msysclk || parent == &clk_f) | ||
246 | dvs = 0; | ||
247 | else if (parent == &clk_h) | ||
248 | dvs = S3C2412_CLKDIVN_DVSEN; | ||
249 | else | ||
250 | return -EINVAL; | ||
251 | |||
252 | clk->parent = parent; | ||
253 | |||
254 | /* update this under irq lockdown, clkdivn is not protected | ||
255 | * by the clock system. */ | ||
256 | |||
257 | local_irq_save(flags); | ||
258 | |||
259 | clkdiv = __raw_readl(S3C2410_CLKDIVN); | ||
260 | clkdiv &= ~S3C2412_CLKDIVN_DVSEN; | ||
261 | clkdiv |= dvs; | ||
262 | __raw_writel(clkdiv, S3C2410_CLKDIVN); | ||
263 | |||
264 | local_irq_restore(flags); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static struct clk clk_armclk = { | ||
270 | .name = "armclk", | ||
271 | .id = -1, | ||
272 | .parent = &clk_msysclk, | ||
273 | .set_parent = s3c2412_setparent_armclk, | ||
274 | }; | ||
275 | |||
237 | /* these next clocks have an divider immediately after them, | 276 | /* these next clocks have an divider immediately after them, |
238 | * so we can register them with their divider and leave out the | 277 | * so we can register them with their divider and leave out the |
239 | * intermediate clock stage | 278 | * intermediate clock stage |
@@ -630,11 +669,13 @@ static struct clk *clks[] __initdata = { | |||
630 | &clk_erefclk, | 669 | &clk_erefclk, |
631 | &clk_urefclk, | 670 | &clk_urefclk, |
632 | &clk_mrefclk, | 671 | &clk_mrefclk, |
672 | &clk_armclk, | ||
633 | }; | 673 | }; |
634 | 674 | ||
635 | int __init s3c2412_baseclk_add(void) | 675 | int __init s3c2412_baseclk_add(void) |
636 | { | 676 | { |
637 | unsigned long clkcon = __raw_readl(S3C2410_CLKCON); | 677 | unsigned long clkcon = __raw_readl(S3C2410_CLKCON); |
678 | unsigned int dvs; | ||
638 | struct clk *clkp; | 679 | struct clk *clkp; |
639 | int ret; | 680 | int ret; |
640 | int ptr; | 681 | int ptr; |
@@ -655,6 +696,15 @@ int __init s3c2412_baseclk_add(void) | |||
655 | } | 696 | } |
656 | } | 697 | } |
657 | 698 | ||
699 | /* set the dvs state according to what we got at boot time */ | ||
700 | |||
701 | dvs = __raw_readl(S3C2410_CLKDIVN) & S3C2412_CLKDIVN_DVSEN; | ||
702 | |||
703 | if (dvs) | ||
704 | clk_armclk.parent = &clk_h; | ||
705 | |||
706 | printk(KERN_INFO "S3C2412: DVS is %s\n", dvs ? "on" : "off"); | ||
707 | |||
658 | /* ensure usb bus clock is within correct rate of 48MHz */ | 708 | /* ensure usb bus clock is within correct rate of 48MHz */ |
659 | 709 | ||
660 | if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) { | 710 | if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) { |