Skip to content

Commit

Permalink
ARM: S3C2443: Add set_rate and round_rate calls for armdiv clock
Browse files Browse the repository at this point in the history
Add set_rate and round_rate calls to armdiv for future use with cpu
frequency scaling.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
  • Loading branch information
Ben Dooks committed Mar 7, 2010
1 parent 71ed587 commit 41f23a0
Showing 1 changed file with 73 additions and 20 deletions.
93 changes: 73 additions & 20 deletions arch/arm/mach-s3c2443/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,83 @@ static struct clksrc_clk clk_msysclk = {
* divider values applied to it to then be fed into armclk.
*/

/* armdiv divisor table */

static unsigned int armdiv[16] = {
[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1,
[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2,
[S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3,
[S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4,
[S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6,
[S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8,
[S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12,
[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16,
};

static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
{
clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;

return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
}

static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
unsigned long rate)
{
unsigned long parent = clk_get_rate(clk->parent);
unsigned long calc;
unsigned best = 256; /* bigger than any value */
unsigned div;
int ptr;

for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
div = armdiv[ptr];
calc = parent / div;
if (calc <= rate && div < best)
best = div;
}

return parent / best;
}

static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
{
unsigned long parent = clk_get_rate(clk->parent);
unsigned long calc;
unsigned div;
unsigned best = 256; /* bigger than any value */
int ptr;
int val = -1;

for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
div = armdiv[ptr];
calc = parent / div;
if (calc <= rate && div < best) {
best = div;
val = ptr;
}
}

if (val >= 0) {
unsigned long clkcon0;

clkcon0 = __raw_readl(S3C2443_CLKDIV0);
clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
__raw_writel(clkcon0, S3C2443_CLKDIV0);
}

return (val == -1) ? -EINVAL : 0;
}

static struct clk clk_armdiv = {
.name = "armdiv",
.id = -1,
.parent = &clk_msysclk.clk,
.ops = &(struct clk_ops) {
.round_rate = s3c2443_armclk_roundrate,
.set_rate = s3c2443_armclk_setrate,
},
};

/* armclk
Expand Down Expand Up @@ -619,26 +692,6 @@ static void __init s3c2443_clk_initparents(void)
s3c_set_clksrc(init_list[ptr], true);
}

/* armdiv divisor table */

static unsigned int armdiv[16] = {
[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1,
[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2,
[S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3,
[S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4,
[S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6,
[S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8,
[S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12,
[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16,
};

static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
{
clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;

return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
}

static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
{
clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK;
Expand Down

0 comments on commit 41f23a0

Please sign in to comment.