diff options
-rw-r--r-- | arch/arm/mach-s3c2443/clock.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index d34f3d32eba5..17f064fabdaf 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c | |||
@@ -678,6 +678,29 @@ static struct clk clk_display = { | |||
678 | .round_rate = s3c2443_roundrate_clksrc256, | 678 | .round_rate = s3c2443_roundrate_clksrc256, |
679 | }; | 679 | }; |
680 | 680 | ||
681 | /* prediv | ||
682 | * | ||
683 | * this divides the msysclk down to pass to h/p/etc. | ||
684 | */ | ||
685 | |||
686 | static unsigned long s3c2443_prediv_getrate(struct clk *clk) | ||
687 | { | ||
688 | unsigned long rate = clk_get_rate(clk->parent); | ||
689 | unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); | ||
690 | |||
691 | clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK; | ||
692 | clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT; | ||
693 | |||
694 | return rate / (clkdiv0 + 1); | ||
695 | } | ||
696 | |||
697 | static struct clk clk_prediv = { | ||
698 | .name = "prediv", | ||
699 | .id = -1, | ||
700 | .parent = &clk_msysclk, | ||
701 | .get_rate = s3c2443_prediv_getrate, | ||
702 | }; | ||
703 | |||
681 | /* standard clock definitions */ | 704 | /* standard clock definitions */ |
682 | 705 | ||
683 | static struct clk init_clocks_disable[] = { | 706 | static struct clk init_clocks_disable[] = { |
@@ -957,10 +980,9 @@ static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0) | |||
957 | return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]; | 980 | return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]; |
958 | } | 981 | } |
959 | 982 | ||
960 | static inline unsigned long s3c2443_get_prediv(unsigned long clkcon0) | 983 | static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0) |
961 | { | 984 | { |
962 | clkcon0 &= S3C2443_CLKDIV0_PREDIV_MASK; | 985 | clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK; |
963 | clkcon0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT; | ||
964 | 986 | ||
965 | return clkcon0 + 1; | 987 | return clkcon0 + 1; |
966 | } | 988 | } |
@@ -986,6 +1008,7 @@ static struct clk *clks[] __initdata = { | |||
986 | &clk_hsmmc, | 1008 | &clk_hsmmc, |
987 | &clk_armdiv, | 1009 | &clk_armdiv, |
988 | &clk_arm, | 1010 | &clk_arm, |
1011 | &clk_prediv, | ||
989 | }; | 1012 | }; |
990 | 1013 | ||
991 | void __init s3c2443_init_clocks(int xtal) | 1014 | void __init s3c2443_init_clocks(int xtal) |
@@ -1001,15 +1024,19 @@ void __init s3c2443_init_clocks(int xtal) | |||
1001 | int ret; | 1024 | int ret; |
1002 | int ptr; | 1025 | int ptr; |
1003 | 1026 | ||
1027 | /* s3c2443 parents h and p clocks from prediv */ | ||
1028 | clk_h.parent = &clk_prediv; | ||
1029 | clk_p.parent = &clk_prediv; | ||
1030 | |||
1004 | pll = s3c2443_get_mpll(mpllcon, xtal); | 1031 | pll = s3c2443_get_mpll(mpllcon, xtal); |
1032 | clk_msysclk.rate = pll; | ||
1005 | 1033 | ||
1006 | fclk = pll / s3c2443_fclk_div(clkdiv0); | 1034 | fclk = pll / s3c2443_fclk_div(clkdiv0); |
1007 | hclk = fclk / s3c2443_get_prediv(clkdiv0); | 1035 | hclk = s3c2443_prediv_getrate(&clk_prediv); |
1036 | hclk = hclk / s3c2443_get_hdiv(clkdiv0); | ||
1008 | hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1); | 1037 | hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1); |
1009 | pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); | 1038 | pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); |
1010 | 1039 | ||
1011 | clk_armdiv.rate = fclk; | ||
1012 | |||
1013 | s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); | 1040 | s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); |
1014 | 1041 | ||
1015 | printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", | 1042 | printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", |