[ARM] S3C64XX: Add ARM clock
Add ARM clock to provide 'arm' from the APLL to the ARM core. Signed-off-by: Ben Dooks <ben-linux@fluff.org>
This commit is contained in:
parent
8f1ecf1d96
commit
496a3f0927
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include <plat/cpu-freq.h>
|
#include <plat/cpu-freq.h>
|
||||||
#include <plat/regs-serial.h>
|
#include <plat/regs-serial.h>
|
||||||
|
#include <plat/regs-clock.h>
|
||||||
|
|
||||||
#include <plat/cpu.h>
|
#include <plat/cpu.h>
|
||||||
#include <plat/devs.h>
|
#include <plat/devs.h>
|
||||||
|
@ -54,7 +55,7 @@ void __init s3c6400_init_clocks(int xtal)
|
||||||
printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
|
printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
|
||||||
s3c24xx_register_baseclocks(xtal);
|
s3c24xx_register_baseclocks(xtal);
|
||||||
s3c64xx_register_clocks();
|
s3c64xx_register_clocks();
|
||||||
s3c6400_register_clocks();
|
s3c6400_register_clocks(S3C6400_CLKDIV0_ARM_MASK);
|
||||||
s3c6400_setup_clocks();
|
s3c6400_setup_clocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <plat/cpu-freq.h>
|
#include <plat/cpu-freq.h>
|
||||||
#include <plat/regs-serial.h>
|
#include <plat/regs-serial.h>
|
||||||
|
#include <plat/regs-clock.h>
|
||||||
|
|
||||||
#include <plat/cpu.h>
|
#include <plat/cpu.h>
|
||||||
#include <plat/devs.h>
|
#include <plat/devs.h>
|
||||||
|
@ -68,7 +69,7 @@ void __init s3c6410_init_clocks(int xtal)
|
||||||
printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
|
printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
|
||||||
s3c24xx_register_baseclocks(xtal);
|
s3c24xx_register_baseclocks(xtal);
|
||||||
s3c64xx_register_clocks();
|
s3c64xx_register_clocks();
|
||||||
s3c6400_register_clocks();
|
s3c6400_register_clocks(S3C6410_CLKDIV0_ARM_MASK);
|
||||||
s3c6400_setup_clocks();
|
s3c6400_setup_clocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
/* Common init code for S3C6400 related SoCs */
|
/* Common init code for S3C6400 related SoCs */
|
||||||
|
|
||||||
extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
|
extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
|
||||||
extern void s3c6400_register_clocks(void);
|
extern void s3c6400_register_clocks(unsigned armclk_divlimit);
|
||||||
extern void s3c6400_setup_clocks(void);
|
extern void s3c6400_setup_clocks(void);
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_S3C6400
|
#ifdef CONFIG_CPU_S3C6400
|
||||||
|
|
|
@ -133,6 +133,65 @@ static struct clksrc_clk clk_mout_mpll = {
|
||||||
.sources = &clk_src_mpll,
|
.sources = &clk_src_mpll,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unsigned int armclk_mask;
|
||||||
|
|
||||||
|
static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
|
||||||
|
{
|
||||||
|
unsigned long rate = clk_get_rate(clk->parent);
|
||||||
|
u32 clkdiv;
|
||||||
|
|
||||||
|
/* divisor mask starts at bit0, so no need to shift */
|
||||||
|
clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
|
||||||
|
|
||||||
|
return rate / (clkdiv + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
|
||||||
|
unsigned long rate)
|
||||||
|
{
|
||||||
|
unsigned long parent = clk_get_rate(clk->parent);
|
||||||
|
u32 div;
|
||||||
|
|
||||||
|
if (parent < rate)
|
||||||
|
return rate;
|
||||||
|
|
||||||
|
div = (parent / rate) - 1;
|
||||||
|
if (div > armclk_mask)
|
||||||
|
div = armclk_mask;
|
||||||
|
|
||||||
|
return parent / (div + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
|
||||||
|
{
|
||||||
|
unsigned long parent = clk_get_rate(clk->parent);
|
||||||
|
u32 div;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
if (rate < parent / (armclk_mask + 1))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
rate = clk_round_rate(clk, rate);
|
||||||
|
div = clk_get_rate(clk->parent) / rate;
|
||||||
|
|
||||||
|
val = __raw_readl(S3C_CLK_DIV0);
|
||||||
|
val &= armclk_mask;
|
||||||
|
val |= (div - 1);
|
||||||
|
__raw_writel(val, S3C_CLK_DIV0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct clk clk_arm = {
|
||||||
|
.name = "armclk",
|
||||||
|
.id = -1,
|
||||||
|
.parent = &clk_mout_apll.clk,
|
||||||
|
.get_rate = s3c64xx_clk_arm_get_rate,
|
||||||
|
.set_rate = s3c64xx_clk_arm_set_rate,
|
||||||
|
.round_rate = s3c64xx_clk_arm_round_rate,
|
||||||
|
};
|
||||||
|
|
||||||
static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
|
static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
|
||||||
{
|
{
|
||||||
unsigned long rate = clk_get_rate(clk->parent);
|
unsigned long rate = clk_get_rate(clk->parent);
|
||||||
|
@ -665,14 +724,29 @@ static struct clk *clks[] __initdata = {
|
||||||
&clk_audio1.clk,
|
&clk_audio1.clk,
|
||||||
&clk_irda.clk,
|
&clk_irda.clk,
|
||||||
&clk_camif.clk,
|
&clk_camif.clk,
|
||||||
|
&clk_arm,
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init s3c6400_register_clocks(void)
|
/**
|
||||||
|
* s3c6400_register_clocks - register clocks for s3c6400 and above
|
||||||
|
* @armclk_divlimit: Divisor mask for ARMCLK
|
||||||
|
*
|
||||||
|
* Register the clocks for the S3C6400 and above SoC range, such
|
||||||
|
* as ARMCLK and the clocks which have divider chains attached.
|
||||||
|
*
|
||||||
|
* This call does not setup the clocks, which is left to the
|
||||||
|
* s3c6400_setup_clocks() call which may be needed by the cpufreq
|
||||||
|
* or resume code to re-set the clocks if the bootloader has changed
|
||||||
|
* them.
|
||||||
|
*/
|
||||||
|
void __init s3c6400_register_clocks(unsigned armclk_divlimit)
|
||||||
{
|
{
|
||||||
struct clk *clkp;
|
struct clk *clkp;
|
||||||
int ret;
|
int ret;
|
||||||
int ptr;
|
int ptr;
|
||||||
|
|
||||||
|
armclk_mask = armclk_divlimit;
|
||||||
|
|
||||||
for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
|
for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
|
||||||
clkp = clks[ptr];
|
clkp = clks[ptr];
|
||||||
ret = s3c24xx_register_clock(clkp);
|
ret = s3c24xx_register_clock(clkp);
|
||||||
|
|
Loading…
Reference in New Issue