diff options
| -rw-r--r-- | arch/sh/kernel/cpu/clock.c | 7 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 34 |
2 files changed, 29 insertions, 12 deletions
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 014f318f5a05..63251549e9a8 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c | |||
| @@ -278,6 +278,11 @@ arch_init_clk_ops(struct clk_ops **ops, int type) | |||
| 278 | { | 278 | { |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | void __init __attribute__ ((weak)) | ||
| 282 | arch_clk_init(void) | ||
| 283 | { | ||
| 284 | } | ||
| 285 | |||
| 281 | static int show_clocks(char *buf, char **start, off_t off, | 286 | static int show_clocks(char *buf, char **start, off_t off, |
| 282 | int len, int *eof, void *data) | 287 | int len, int *eof, void *data) |
| 283 | { | 288 | { |
| @@ -314,6 +319,8 @@ int __init clk_init(void) | |||
| 314 | ret |= clk_register(clk); | 319 | ret |= clk_register(clk); |
| 315 | } | 320 | } |
| 316 | 321 | ||
| 322 | arch_clk_init(); | ||
| 323 | |||
| 317 | /* Kick the child clocks.. */ | 324 | /* Kick the child clocks.. */ |
| 318 | propagate_rate(&master_clk); | 325 | propagate_rate(&master_clk); |
| 319 | propagate_rate(&bus_clk); | 326 | propagate_rate(&bus_clk); |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 29090035bc5b..51b386d454de 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <asm/clock.h> | 17 | #include <asm/clock.h> |
| 18 | #include <asm/freq.h> | 18 | #include <asm/freq.h> |
| 19 | 19 | ||
| 20 | #define SH7722_PLL_FREQ (32000000/8) | ||
| 21 | #define N (-1) | 20 | #define N (-1) |
| 22 | #define NM (-2) | 21 | #define NM (-2) |
| 23 | #define ROUND_NEAREST 0 | 22 | #define ROUND_NEAREST 0 |
| @@ -141,28 +140,36 @@ static void adjust_clocks(int originate, int *l, unsigned long v[], | |||
| 141 | */ | 140 | */ |
| 142 | static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 }; | 141 | static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 }; |
| 143 | 142 | ||
| 143 | static void master_clk_recalc(struct clk *clk) | ||
| 144 | { | ||
| 145 | unsigned frqcr = ctrl_inl(FRQCR); | ||
| 146 | |||
| 147 | clk->rate = CONFIG_SH_PCLK_FREQ * (((frqcr >> 24) & 0x1f) + 1); | ||
| 148 | } | ||
| 149 | |||
| 144 | static void master_clk_init(struct clk *clk) | 150 | static void master_clk_init(struct clk *clk) |
| 145 | { | 151 | { |
| 146 | clk_set_rate(clk, clk_get_rate(clk)); | 152 | clk->parent = NULL; |
| 153 | clk->flags |= CLK_RATE_PROPAGATES; | ||
| 154 | clk->rate = CONFIG_SH_PCLK_FREQ; | ||
| 155 | master_clk_recalc(clk); | ||
| 147 | } | 156 | } |
| 148 | 157 | ||
| 149 | static void master_clk_recalc(struct clk *clk) | 158 | |
| 159 | static void module_clk_recalc(struct clk *clk) | ||
| 150 | { | 160 | { |
| 151 | unsigned long frqcr = ctrl_inl(FRQCR); | 161 | unsigned long frqcr = ctrl_inl(FRQCR); |
| 152 | 162 | ||
| 153 | clk->rate = CONFIG_SH_PCLK_FREQ * (1 + (frqcr >> 24 & 0xF)); | 163 | clk->rate = clk->parent->rate / (((frqcr >> 24) & 0x1f) + 1); |
| 154 | } | 164 | } |
| 155 | 165 | ||
| 156 | static int master_clk_setrate(struct clk *clk, unsigned long rate, int id) | 166 | static int master_clk_setrate(struct clk *clk, unsigned long rate, int id) |
| 157 | { | 167 | { |
| 158 | int div = rate / SH7722_PLL_FREQ; | 168 | int div = rate / clk->rate; |
| 159 | int master_divs[] = { 2, 3, 4, 6, 8, 16 }; | 169 | int master_divs[] = { 2, 3, 4, 6, 8, 16 }; |
| 160 | int index; | 170 | int index; |
| 161 | unsigned long frqcr; | 171 | unsigned long frqcr; |
| 162 | 172 | ||
| 163 | if (rate < SH7722_PLL_FREQ * 2) | ||
| 164 | return -EINVAL; | ||
| 165 | |||
| 166 | for (index = 1; index < ARRAY_SIZE(master_divs); index++) | 173 | for (index = 1; index < ARRAY_SIZE(master_divs); index++) |
| 167 | if (div >= master_divs[index - 1] && div < master_divs[index]) | 174 | if (div >= master_divs[index - 1] && div < master_divs[index]) |
| 168 | break; | 175 | break; |
| @@ -185,6 +192,10 @@ static struct clk_ops sh7722_master_clk_ops = { | |||
| 185 | .set_rate = master_clk_setrate, | 192 | .set_rate = master_clk_setrate, |
| 186 | }; | 193 | }; |
| 187 | 194 | ||
| 195 | static struct clk_ops sh7722_module_clk_ops = { | ||
| 196 | .recalc = module_clk_recalc, | ||
| 197 | }; | ||
| 198 | |||
| 188 | struct frqcr_context { | 199 | struct frqcr_context { |
| 189 | unsigned mask; | 200 | unsigned mask; |
| 190 | unsigned shift; | 201 | unsigned shift; |
| @@ -489,7 +500,7 @@ static void sh7722_siu_recalc(struct clk *clk) | |||
| 489 | 500 | ||
| 490 | if (siu < 0) | 501 | if (siu < 0) |
| 491 | return /* siu */ ; | 502 | return /* siu */ ; |
| 492 | BUG_ON(siu > 1); | 503 | BUG_ON(siu > 2); |
| 493 | r = ctrl_inl(sh7722_siu_regs[siu]); | 504 | r = ctrl_inl(sh7722_siu_regs[siu]); |
| 494 | clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF]; | 505 | clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF]; |
| 495 | } | 506 | } |
| @@ -571,7 +582,7 @@ static struct clk *sh7722_clocks[] = { | |||
| 571 | */ | 582 | */ |
| 572 | struct clk_ops *onchip_ops[] = { | 583 | struct clk_ops *onchip_ops[] = { |
| 573 | &sh7722_master_clk_ops, | 584 | &sh7722_master_clk_ops, |
| 574 | &sh7722_frqcr_clk_ops, | 585 | &sh7722_module_clk_ops, |
| 575 | &sh7722_frqcr_clk_ops, | 586 | &sh7722_frqcr_clk_ops, |
| 576 | &sh7722_frqcr_clk_ops, | 587 | &sh7722_frqcr_clk_ops, |
| 577 | }; | 588 | }; |
| @@ -583,7 +594,7 @@ arch_init_clk_ops(struct clk_ops **ops, int type) | |||
| 583 | *ops = onchip_ops[type]; | 594 | *ops = onchip_ops[type]; |
| 584 | } | 595 | } |
| 585 | 596 | ||
| 586 | int __init sh7722_clock_init(void) | 597 | int __init arch_clk_init(void) |
| 587 | { | 598 | { |
| 588 | struct clk *master; | 599 | struct clk *master; |
| 589 | int i; | 600 | int i; |
| @@ -597,4 +608,3 @@ int __init sh7722_clock_init(void) | |||
| 597 | clk_put(master); | 608 | clk_put(master); |
| 598 | return 0; | 609 | return 0; |
| 599 | } | 610 | } |
| 600 | arch_initcall(sh7722_clock_init); | ||
