diff options
| -rw-r--r-- | arch/arm/mach-s3c2443/clock.c | 93 |
1 files changed, 73 insertions, 20 deletions
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index 177719c7c267..62cd4eaee01b 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c | |||
| @@ -165,10 +165,83 @@ static struct clksrc_clk clk_msysclk = { | |||
| 165 | * divider values applied to it to then be fed into armclk. | 165 | * divider values applied to it to then be fed into armclk. |
| 166 | */ | 166 | */ |
| 167 | 167 | ||
| 168 | /* armdiv divisor table */ | ||
| 169 | |||
| 170 | static unsigned int armdiv[16] = { | ||
| 171 | [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1, | ||
| 172 | [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2, | ||
| 173 | [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3, | ||
| 174 | [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4, | ||
| 175 | [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6, | ||
| 176 | [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8, | ||
| 177 | [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12, | ||
| 178 | [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16, | ||
| 179 | }; | ||
| 180 | |||
| 181 | static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0) | ||
| 182 | { | ||
| 183 | clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK; | ||
| 184 | |||
| 185 | return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]; | ||
| 186 | } | ||
| 187 | |||
| 188 | static unsigned long s3c2443_armclk_roundrate(struct clk *clk, | ||
| 189 | unsigned long rate) | ||
| 190 | { | ||
| 191 | unsigned long parent = clk_get_rate(clk->parent); | ||
| 192 | unsigned long calc; | ||
| 193 | unsigned best = 256; /* bigger than any value */ | ||
| 194 | unsigned div; | ||
| 195 | int ptr; | ||
| 196 | |||
| 197 | for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) { | ||
| 198 | div = armdiv[ptr]; | ||
| 199 | calc = parent / div; | ||
| 200 | if (calc <= rate && div < best) | ||
| 201 | best = div; | ||
| 202 | } | ||
| 203 | |||
| 204 | return parent / best; | ||
| 205 | } | ||
| 206 | |||
| 207 | static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate) | ||
| 208 | { | ||
| 209 | unsigned long parent = clk_get_rate(clk->parent); | ||
| 210 | unsigned long calc; | ||
| 211 | unsigned div; | ||
| 212 | unsigned best = 256; /* bigger than any value */ | ||
| 213 | int ptr; | ||
| 214 | int val = -1; | ||
| 215 | |||
| 216 | for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) { | ||
| 217 | div = armdiv[ptr]; | ||
| 218 | calc = parent / div; | ||
| 219 | if (calc <= rate && div < best) { | ||
| 220 | best = div; | ||
| 221 | val = ptr; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | if (val >= 0) { | ||
| 226 | unsigned long clkcon0; | ||
| 227 | |||
| 228 | clkcon0 = __raw_readl(S3C2443_CLKDIV0); | ||
| 229 | clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK; | ||
| 230 | clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT; | ||
| 231 | __raw_writel(clkcon0, S3C2443_CLKDIV0); | ||
| 232 | } | ||
| 233 | |||
| 234 | return (val == -1) ? -EINVAL : 0; | ||
| 235 | } | ||
| 236 | |||
| 168 | static struct clk clk_armdiv = { | 237 | static struct clk clk_armdiv = { |
| 169 | .name = "armdiv", | 238 | .name = "armdiv", |
| 170 | .id = -1, | 239 | .id = -1, |
| 171 | .parent = &clk_msysclk.clk, | 240 | .parent = &clk_msysclk.clk, |
| 241 | .ops = &(struct clk_ops) { | ||
| 242 | .round_rate = s3c2443_armclk_roundrate, | ||
| 243 | .set_rate = s3c2443_armclk_setrate, | ||
| 244 | }, | ||
| 172 | }; | 245 | }; |
| 173 | 246 | ||
| 174 | /* armclk | 247 | /* armclk |
| @@ -619,26 +692,6 @@ static void __init s3c2443_clk_initparents(void) | |||
| 619 | s3c_set_clksrc(init_list[ptr], true); | 692 | s3c_set_clksrc(init_list[ptr], true); |
| 620 | } | 693 | } |
| 621 | 694 | ||
| 622 | /* armdiv divisor table */ | ||
| 623 | |||
| 624 | static unsigned int armdiv[16] = { | ||
| 625 | [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1, | ||
| 626 | [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2, | ||
| 627 | [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3, | ||
| 628 | [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4, | ||
| 629 | [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6, | ||
| 630 | [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8, | ||
| 631 | [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12, | ||
| 632 | [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16, | ||
| 633 | }; | ||
| 634 | |||
| 635 | static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0) | ||
| 636 | { | ||
| 637 | clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK; | ||
| 638 | |||
| 639 | return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]; | ||
| 640 | } | ||
| 641 | |||
| 642 | static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0) | 695 | static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0) |
| 643 | { | 696 | { |
| 644 | clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK; | 697 | clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK; |
