aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authordmitry pervushin <dimka@nomadgs.com>2007-05-14 19:42:22 -0400
committerPaul Mundt <lethal@linux-sh.org>2007-05-21 01:34:45 -0400
commitdfbbbe92956b849a6704dbd5352348d6ba1165da (patch)
tree206daa54ab3567503c4cd7db9ecb85af31608bda /arch/sh/kernel
parente113276624104d9c3b25f333d8dd999b804d980a (diff)
sh: Fix clock multiplier on SH7722.
This fixes up the master clock multiplier and initial rate propagation for the SH7722 clocks. Signed-off-by: dmitry pervushin <dimka@nomadgs.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/cpu/clock.c7
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7722.c34
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
281void __init __attribute__ ((weak))
282arch_clk_init(void)
283{
284}
285
281static int show_clocks(char *buf, char **start, off_t off, 286static 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*/
142static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 }; 141static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 };
143 142
143static 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
144static void master_clk_init(struct clk *clk) 150static 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
149static void master_clk_recalc(struct clk *clk) 158
159static 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
156static int master_clk_setrate(struct clk *clk, unsigned long rate, int id) 166static 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
195static struct clk_ops sh7722_module_clk_ops = {
196 .recalc = module_clk_recalc,
197};
198
188struct frqcr_context { 199struct 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 */
572struct clk_ops *onchip_ops[] = { 583struct 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
586int __init sh7722_clock_init(void) 597int __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}
600arch_initcall(sh7722_clock_init);