Skip to content

Commit

Permalink
sh: Fix clock multiplier on SH7722.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dmitry pervushin authored and Paul Mundt committed May 21, 2007
1 parent e113276 commit dfbbbe9
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
7 changes: 7 additions & 0 deletions arch/sh/kernel/cpu/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,11 @@ arch_init_clk_ops(struct clk_ops **ops, int type)
{
}

void __init __attribute__ ((weak))
arch_clk_init(void)
{
}

static int show_clocks(char *buf, char **start, off_t off,
int len, int *eof, void *data)
{
Expand Down Expand Up @@ -314,6 +319,8 @@ int __init clk_init(void)
ret |= clk_register(clk);
}

arch_clk_init();

/* Kick the child clocks.. */
propagate_rate(&master_clk);
propagate_rate(&bus_clk);
Expand Down
34 changes: 22 additions & 12 deletions arch/sh/kernel/cpu/sh4a/clock-sh7722.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <asm/clock.h>
#include <asm/freq.h>

#define SH7722_PLL_FREQ (32000000/8)
#define N (-1)
#define NM (-2)
#define ROUND_NEAREST 0
Expand Down Expand Up @@ -141,28 +140,36 @@ static void adjust_clocks(int originate, int *l, unsigned long v[],
*/
static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 };

static void master_clk_recalc(struct clk *clk)
{
unsigned frqcr = ctrl_inl(FRQCR);

clk->rate = CONFIG_SH_PCLK_FREQ * (((frqcr >> 24) & 0x1f) + 1);
}

static void master_clk_init(struct clk *clk)
{
clk_set_rate(clk, clk_get_rate(clk));
clk->parent = NULL;
clk->flags |= CLK_RATE_PROPAGATES;
clk->rate = CONFIG_SH_PCLK_FREQ;
master_clk_recalc(clk);
}

static void master_clk_recalc(struct clk *clk)

static void module_clk_recalc(struct clk *clk)
{
unsigned long frqcr = ctrl_inl(FRQCR);

clk->rate = CONFIG_SH_PCLK_FREQ * (1 + (frqcr >> 24 & 0xF));
clk->rate = clk->parent->rate / (((frqcr >> 24) & 0x1f) + 1);
}

static int master_clk_setrate(struct clk *clk, unsigned long rate, int id)
{
int div = rate / SH7722_PLL_FREQ;
int div = rate / clk->rate;
int master_divs[] = { 2, 3, 4, 6, 8, 16 };
int index;
unsigned long frqcr;

if (rate < SH7722_PLL_FREQ * 2)
return -EINVAL;

for (index = 1; index < ARRAY_SIZE(master_divs); index++)
if (div >= master_divs[index - 1] && div < master_divs[index])
break;
Expand All @@ -185,6 +192,10 @@ static struct clk_ops sh7722_master_clk_ops = {
.set_rate = master_clk_setrate,
};

static struct clk_ops sh7722_module_clk_ops = {
.recalc = module_clk_recalc,
};

struct frqcr_context {
unsigned mask;
unsigned shift;
Expand Down Expand Up @@ -489,7 +500,7 @@ static void sh7722_siu_recalc(struct clk *clk)

if (siu < 0)
return /* siu */ ;
BUG_ON(siu > 1);
BUG_ON(siu > 2);
r = ctrl_inl(sh7722_siu_regs[siu]);
clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF];
}
Expand Down Expand Up @@ -571,7 +582,7 @@ static struct clk *sh7722_clocks[] = {
*/
struct clk_ops *onchip_ops[] = {
&sh7722_master_clk_ops,
&sh7722_frqcr_clk_ops,
&sh7722_module_clk_ops,
&sh7722_frqcr_clk_ops,
&sh7722_frqcr_clk_ops,
};
Expand All @@ -583,7 +594,7 @@ arch_init_clk_ops(struct clk_ops **ops, int type)
*ops = onchip_ops[type];
}

int __init sh7722_clock_init(void)
int __init arch_clk_init(void)
{
struct clk *master;
int i;
Expand All @@ -597,4 +608,3 @@ int __init sh7722_clock_init(void)
clk_put(master);
return 0;
}
arch_initcall(sh7722_clock_init);

0 comments on commit dfbbbe9

Please sign in to comment.