Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 496a3f09 authored by Ben Dooks's avatar Ben Dooks
Browse files

[ARM] S3C64XX: Add ARM clock



Add ARM clock to provide 'arm' from the APLL to the ARM core.

Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
parent 8f1ecf1d
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -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();
}
}


+2 −1
Original line number Original line Diff line number Diff line
@@ -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();
}
}


+1 −1
Original line number Original line Diff line number Diff line
@@ -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
+75 −1
Original line number Original line Diff line number Diff line
@@ -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);