diff mbox

[RFC] ARM: EXYNOS5: Support Exynos5-bus devfreq driver

Message ID 1355141166-17205-1-git-send-email-a.kesavan@samsung.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Abhilash Kesavan Dec. 10, 2012, 12:06 p.m. UTC
- Setup the INT clock ops to control/vary INT frequency
- Add mappings initially for the PPMU device

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
Corresponding devfreq driver support for Exynos5 has been posted at:
https://patchwork.kernel.org/patch/1823931/

Tested after merging for-rafael branch of
git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq.git
with for-next branch of
git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git

 arch/arm/mach-exynos/clock-exynos5.c           |  151 ++++++++++++++++++++++++
 arch/arm/mach-exynos/common.c                  |   25 ++++
 arch/arm/mach-exynos/include/mach/map.h        |    6 +
 arch/arm/mach-exynos/include/mach/regs-clock.h |   48 ++++++++
 arch/arm/plat-samsung/include/plat/map-s5p.h   |    6 +
 5 files changed, 236 insertions(+), 0 deletions(-)

Comments

jhbird.choi@samsung.com Dec. 10, 2012, 11:59 p.m. UTC | #1
Hi Abhilash Kesavan.


> +	/* Change Divider - LEX */
> +	tmp = __raw_readl(EXYNOS5_CLKDIV_LEX);
> +
> +	tmp &= ~(EXYNOS5_CLKDIV_LEX_ATCLK_LEX_MASK |
> +		EXYNOS5_CLKDIV_LEX_PCLK_LEX_MASK);
> +
> +	tmp |= int_freq[div_index].clk_div_lex;
> +
> +	__raw_writel(tmp, EXYNOS5_CLKDIV_LEX);
> +

I knew that only ATCLK_LEX & PCLK_LEX divider value are in CLKDIV_LEX
register. (Others are reserved and value is 0)
So, I think 
"
tmp = int_freq[div_index].clk_div_lex;
__raw_writel(tmp, EXYNOS5_CLKDIV_LEX);
"
Is enough.

> +	tmp = __raw_readl(EXYNOS5_CLKDIV_LEX);
> +
> +	tmp &= ~(EXYNOS5_CLKDIV_LEX_ATCLK_LEX_MASK |
> +		EXYNOS5_CLKDIV_LEX_PCLK_LEX_MASK);
-> not need.



> +	while (__raw_readl(EXYNOS5_CLKDIV_STAT_LEX) & 0x110)
> +		cpu_relax();
> +
> +	/* Change Divider - R0X */
> +	tmp = __raw_readl(EXYNOS5_CLKDIV_R0X);
> +
> +	tmp &= ~EXYNOS5_CLKDIV_R0X_PCLK_R0X_MASK;
> +
> +	tmp |= int_freq[div_index].clk_div_r0x;
> +
> +	__raw_writel(tmp, EXYNOS5_CLKDIV_R0X);
> +

Same here


> +	while (__raw_readl(EXYNOS5_CLKDIV_STAT_R0X) & 0x10)
> +		cpu_relax();
> +
> +	/* Change Divider - R1X */
> +	tmp = __raw_readl(EXYNOS5_CLKDIV_R1X);
> +
> +	tmp &= ~EXYNOS5_CLKDIV_R1X_PCLK_R1X_MASK;
> +
> +	tmp |= int_freq[div_index].clk_div_r1x;
> +
> +	__raw_writel(tmp, EXYNOS5_CLKDIV_R1X);
> +

Same here

> +	while (__raw_readl(EXYNOS5_CLKDIV_STAT_R1X) & 0x10)
> +		cpu_relax();

How about your opinion?

thanks



> -----Original Message-----
> From: Abhilash Kesavan [mailto:a.kesavan@samsung.com]
> Sent: Monday, December 10, 2012 9:06 PM
> To: linux-kernel@vger.kernel.org; linux-pm@vger.kernel.org;
> kgene.kim@samsung.com
> Cc: myungjoo.ham@samsung.com; kyungmin.park@samsung.com; rjw@sisk.pl;
> jhbird.choi@samsung.com; Abhilash Kesavan
> Subject: [RFC PATCH] ARM: EXYNOS5: Support Exynos5-bus devfreq driver
> 
> - Setup the INT clock ops to control/vary INT frequency
> - Add mappings initially for the PPMU device
> 
> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> ---
> Corresponding devfreq driver support for Exynos5 has been posted at:
> https://patchwork.kernel.org/patch/1823931/
> 
> Tested after merging for-rafael branch of
> git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq.git
> with for-next branch of
> git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
> 
>  arch/arm/mach-exynos/clock-exynos5.c           |  151
> ++++++++++++++++++++++++
>  arch/arm/mach-exynos/common.c                  |   25 ++++
>  arch/arm/mach-exynos/include/mach/map.h        |    6 +
>  arch/arm/mach-exynos/include/mach/regs-clock.h |   48 ++++++++
>  arch/arm/plat-samsung/include/plat/map-s5p.h   |    6 +
>  5 files changed, 236 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-
> exynos/clock-exynos5.c
> index 5c63bc7..f00b259 100644
> --- a/arch/arm/mach-exynos/clock-exynos5.c
> +++ b/arch/arm/mach-exynos/clock-exynos5.c
> @@ -109,6 +109,11 @@ static struct clk exynos5_clk_sclk_usbphy = {
>  	.rate		= 48000000,
>  };
> 
> +/* Virtual Bus INT clock */
> +static struct clk exynos5_int_clk = {
> +	.name		= "int_clk",
> +};
> +
>  static int exynos5_clksrc_mask_top_ctrl(struct clk *clk, int enable)
>  {
>  	return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_TOP, clk, enable);
> @@ -1519,6 +1524,149 @@ static struct clk *exynos5_clks[] __initdata = {
>  	&clk_fout_cpll,
>  	&clk_fout_mpll_div2,
>  	&exynos5_clk_armclk,
> +	&exynos5_int_clk,
> +};
> +
> +#define INT_FREQ(f, a0, a1, a2, a3, a4, a5, b0, b1, b2, b3, \
> +			c0, c1, d0, e0) \
> +	{ \
> +		.freq = (f) * 1000000, \
> +		.clk_div_top0 = ((a0) << 0 | (a1) << 8 | (a2) << 12 | \
> +				(a3) << 16 | (a4) << 20 | (a5) << 28), \
> +		.clk_div_top1 = ((b0) << 12 | (b1) << 16 | (b2) << 20 | \
> +				(b3) << 24), \
> +		.clk_div_lex = ((c0) << 4 | (c1) << 8), \
> +		.clk_div_r0x = ((d0) << 4), \
> +		.clk_div_r1x = ((e0) << 4), \
> +	}
> +
> +static struct {
> +	unsigned long freq;
> +	u32 clk_div_top0;
> +	u32 clk_div_top1;
> +	u32 clk_div_lex;
> +	u32 clk_div_r0x;
> +	u32 clk_div_r1x;
> +} int_freq[] = {
> +	/*
> +	 * values:
> +	 * freq
> +	 * clock divider for ACLK66, ACLK166, ACLK200, ACLK266,
> +			ACLK333, ACLK300_DISP1
> +	 * clock divider for ACLK300_GSCL, ACLK400_IOP, ACLK400_ISP,
> ACLK66_PRE
> +	 * clock divider for PCLK_LEX, ATCLK_LEX
> +	 * clock divider for ACLK_PR0X
> +	 * clock divider for ACLK_PR1X
> +	 */
> +	INT_FREQ(266, 1, 1, 3, 2, 0, 0, 0, 1, 1, 5, 1, 0, 1, 1),
> +	INT_FREQ(200, 1, 2, 4, 3, 1, 0, 0, 3, 2, 5, 1, 0, 1, 1),
> +	INT_FREQ(160, 1, 3, 4, 4, 2, 0, 0, 3, 3, 5, 1, 0, 1, 1),
> +	INT_FREQ(133, 1, 3, 5, 5, 2, 1, 1, 4, 4, 5, 1, 0, 1, 1),
> +	INT_FREQ(100, 1, 7, 7, 7, 7, 3, 7, 7, 7, 5, 1, 0, 1, 1),
> +};
> +
> +static unsigned long exynos5_clk_int_get_rate(struct clk *clk)
> +{
> +	return clk->rate;
> +}
> +
> +static void exynos5_int_set_clkdiv(unsigned int div_index)
> +{
> +	unsigned int tmp;
> +
> +	/* Change Divider - TOP0 */
> +	tmp = __raw_readl(EXYNOS5_CLKDIV_TOP0);
> +
> +	tmp &= ~(EXYNOS5_CLKDIV_TOP0_ACLK266_MASK |
> +		EXYNOS5_CLKDIV_TOP0_ACLK200_MASK |
> +		EXYNOS5_CLKDIV_TOP0_ACLK66_MASK |
> +		EXYNOS5_CLKDIV_TOP0_ACLK333_MASK |
> +		EXYNOS5_CLKDIV_TOP0_ACLK166_MASK |
> +		EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_MASK);
> +
> +	tmp |= int_freq[div_index].clk_div_top0;
> +
> +	__raw_writel(tmp, EXYNOS5_CLKDIV_TOP0);
> +
> +	while (__raw_readl(EXYNOS5_CLKDIV_STAT_TOP0) & 0x151101)
> +		cpu_relax();
> +
> +	/* Change Divider - TOP1 */
> +	tmp = __raw_readl(EXYNOS5_CLKDIV_TOP1);
> +
> +	tmp &= ~(EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_MASK |
> +		EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_MASK |
> +		EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_MASK |
> +		EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_MASK);
> +
> +	tmp |= int_freq[div_index].clk_div_top1;
> +
> +	__raw_writel(tmp, EXYNOS5_CLKDIV_TOP1);
> +
> +	while ((__raw_readl(EXYNOS5_CLKDIV_STAT_TOP1) & 0x1110000) &&
> +		(__raw_readl(EXYNOS5_CLKDIV_STAT_TOP0) & 0x80000))
> +		cpu_relax();
> +
> +	/* Change Divider - LEX */
> +	tmp = __raw_readl(EXYNOS5_CLKDIV_LEX);
> +
> +	tmp &= ~(EXYNOS5_CLKDIV_LEX_ATCLK_LEX_MASK |
> +		EXYNOS5_CLKDIV_LEX_PCLK_LEX_MASK);
> +
> +	tmp |= int_freq[div_index].clk_div_lex;
> +
> +	__raw_writel(tmp, EXYNOS5_CLKDIV_LEX);
> +
> +	while (__raw_readl(EXYNOS5_CLKDIV_STAT_LEX) & 0x110)
> +		cpu_relax();
> +
> +	/* Change Divider - R0X */
> +	tmp = __raw_readl(EXYNOS5_CLKDIV_R0X);
> +
> +	tmp &= ~EXYNOS5_CLKDIV_R0X_PCLK_R0X_MASK;
> +
> +	tmp |= int_freq[div_index].clk_div_r0x;
> +
> +	__raw_writel(tmp, EXYNOS5_CLKDIV_R0X);
> +
> +	while (__raw_readl(EXYNOS5_CLKDIV_STAT_R0X) & 0x10)
> +		cpu_relax();
> +
> +	/* Change Divider - R1X */
> +	tmp = __raw_readl(EXYNOS5_CLKDIV_R1X);
> +
> +	tmp &= ~EXYNOS5_CLKDIV_R1X_PCLK_R1X_MASK;
> +
> +	tmp |= int_freq[div_index].clk_div_r1x;
> +
> +	__raw_writel(tmp, EXYNOS5_CLKDIV_R1X);
> +
> +	while (__raw_readl(EXYNOS5_CLKDIV_STAT_R1X) & 0x10)
> +		cpu_relax();
> +}
> +
> +static int exynos5_clk_int_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	int index;
> +
> +	for (index = 0; index < ARRAY_SIZE(int_freq); index++)
> +		if (int_freq[index].freq == rate)
> +			break;
> +
> +	if (index == ARRAY_SIZE(int_freq))
> +		return -EINVAL;
> +
> +	/* Change the system clock divider values */
> +	exynos5_int_set_clkdiv(index);
> +
> +	clk->rate = rate;
> +
> +	return 0;
> +}
> +
> +static struct clk_ops exynos5_clk_int_ops = {
> +	.get_rate = exynos5_clk_int_get_rate,
> +	.set_rate = exynos5_clk_int_set_rate
>  };
> 
>  static u32 epll_div[][6] = {
> @@ -1713,6 +1861,9 @@ void __init_or_cpufreq exynos5_setup_clocks(void)
> 
>  	clk_fout_epll.ops = &exynos5_epll_ops;
> 
> +	exynos5_int_clk.ops = &exynos5_clk_int_ops;
> +	exynos5_int_clk.rate = aclk_266;
> +
>  	if (clk_set_parent(&exynos5_clk_mout_epll.clk, &clk_fout_epll))
>  		printk(KERN_ERR "Unable to set parent %s of clock %s.\n",
>  				clk_fout_epll.name,
> exynos5_clk_mout_epll.clk.name);
> diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
> index 73b940f..6b7d4ee 100644
> --- a/arch/arm/mach-exynos/common.c
> +++ b/arch/arm/mach-exynos/common.c
> @@ -282,6 +282,31 @@ static struct map_desc exynos5_iodesc[] __initdata =
> {
>  		.pfn		= __phys_to_pfn(EXYNOS5_PA_UART),
>  		.length		= SZ_512K,
>  		.type		= MT_DEVICE,
> +	}, {
> +		.virtual        = (unsigned long)S5P_VA_PPMU_CPU,
> +		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_CPU),
> +		.length         = SZ_8K,
> +		.type		= MT_DEVICE,
> +	}, {
> +		.virtual        = (unsigned long)S5P_VA_PPMU_DDR_C,
> +		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_DDR_C),
> +		.length         = SZ_8K,
> +		.type           = MT_DEVICE,
> +	}, {
> +		.virtual        = (unsigned long)S5P_VA_PPMU_DDR_R1,
> +		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_DDR_R1),
> +		.length         = SZ_8K,
> +		.type           = MT_DEVICE,
> +	}, {
> +		.virtual        = (unsigned long)S5P_VA_PPMU_DDR_L,
> +		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_DDR_L),
> +		.length         = SZ_8K,
> +		.type           = MT_DEVICE,
> +	}, {
> +		.virtual        = (unsigned long)S5P_VA_PPMU_RIGHT,
> +		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_RIGHT),
> +		.length         = SZ_8K,
> +		.type           = MT_DEVICE,
>  	},
>  };
> 
> diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-
> exynos/include/mach/map.h
> index cbb2852..8c8de91 100644
> --- a/arch/arm/mach-exynos/include/mach/map.h
> +++ b/arch/arm/mach-exynos/include/mach/map.h
> @@ -228,6 +228,12 @@
>  #define EXYNOS4_PA_SDRAM		0x40000000
>  #define EXYNOS5_PA_SDRAM		0x40000000
> 
> +#define EXYNOS5_PA_PPMU_DDR_C		0x10C40000
> +#define EXYNOS5_PA_PPMU_DDR_R1		0x10C50000
> +#define EXYNOS5_PA_PPMU_CPU		0x10C60000
> +#define EXYNOS5_PA_PPMU_DDR_L		0x10CB0000
> +#define EXYNOS5_PA_PPMU_RIGHT		0x13660000
> +
>  /* Compatibiltiy Defines */
> 
>  #define S3C_PA_HSMMC0			EXYNOS4_PA_HSMMC(0)
> diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h
> b/arch/arm/mach-exynos/include/mach/regs-clock.h
> index d36ad76..bad3cd3 100644
> --- a/arch/arm/mach-exynos/include/mach/regs-clock.h
> +++ b/arch/arm/mach-exynos/include/mach/regs-clock.h
> @@ -323,6 +323,9 @@
>  #define EXYNOS5_CLKDIV_PERIC5
EXYNOS_CLKREG(0x1056C)
>  #define EXYNOS5_SCLK_DIV_ISP			EXYNOS_CLKREG(0x10580)
> 
> +#define EXYNOS5_CLKDIV_STAT_TOP0		EXYNOS_CLKREG(0x10610)
> +#define EXYNOS5_CLKDIV_STAT_TOP1		EXYNOS_CLKREG(0x10614)
> +
>  #define EXYNOS5_CLKGATE_IP_ACP
EXYNOS_CLKREG(0x08800)
>  #define EXYNOS5_CLKGATE_IP_ISP0
EXYNOS_CLKREG(0x0C800)
>  #define EXYNOS5_CLKGATE_IP_ISP1
EXYNOS_CLKREG(0x0C804)
> @@ -337,6 +340,18 @@
>  #define EXYNOS5_CLKGATE_IP_PERIS		EXYNOS_CLKREG(0x10960)
>  #define EXYNOS5_CLKGATE_BLOCK
EXYNOS_CLKREG(0x10980)
> 
> +#define EXYNOS5_CLKGATE_BUS_SYSLFT		EXYNOS_CLKREG(0x08920)
> +
> +#define EXYNOS5_CLKOUT_CMU_TOP
EXYNOS_CLKREG(0x10A00)
> +
> +#define EXYNOS5_CLKDIV_LEX			EXYNOS_CLKREG(0x14500)
> +#define EXYNOS5_CLKDIV_STAT_LEX
EXYNOS_CLKREG(0x14600)
> +
> +#define EXYNOS5_CLKDIV_R0X			EXYNOS_CLKREG(0x18500)
> +#define EXYNOS5_CLKDIV_STAT_R0X
EXYNOS_CLKREG(0x18600)
> +
> +#define EXYNOS5_CLKDIV_R1X			EXYNOS_CLKREG(0x1C500)
> +#define EXYNOS5_CLKDIV_STAT_R1X
EXYNOS_CLKREG(0x1C600)
>  #define EXYNOS5_BPLL_CON0			EXYNOS_CLKREG(0x20110)
>  #define EXYNOS5_CLKSRC_CDREX			EXYNOS_CLKREG(0x20200)
>  #define EXYNOS5_CLKDIV_CDREX			EXYNOS_CLKREG(0x20500)
> @@ -347,6 +362,39 @@
> 
>  #define EXYNOS5_EPLLCON0_LOCKED_SHIFT		(29)
> 
> +#define EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_SHIFT	(28)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_MASK	(0x7 <<
> EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_SHIFT)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK333_SHIFT	(20)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK333_MASK	(0x7 <<
> EXYNOS5_CLKDIV_TOP0_ACLK333_SHIFT)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK266_SHIFT	(16)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK266_MASK	(0x7 <<
> EXYNOS5_CLKDIV_TOP0_ACLK266_SHIFT)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK200_SHIFT	(12)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK200_MASK	(0x7 <<
> EXYNOS5_CLKDIV_TOP0_ACLK200_SHIFT)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK166_SHIFT	(8)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK166_MASK	(0x7 <<
> EXYNOS5_CLKDIV_TOP0_ACLK166_SHIFT)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK66_SHIFT	(0)
> +#define EXYNOS5_CLKDIV_TOP0_ACLK66_MASK		(0x7 <<
> EXYNOS5_CLKDIV_TOP0_ACLK66_SHIFT)
> +
> +#define EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_SHIFT	(24)
> +#define EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_MASK	(0x7 <<
> EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_SHIFT)
> +#define EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_SHIFT	(20)
> +#define EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_MASK	(0x7 <<
> EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_SHIFT)
> +#define EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_SHIFT	(16)
> +#define EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_MASK	(0x7 <<
> EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_SHIFT)
> +#define EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_SHIFT	(12)
> +#define EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_MASK	(0x7 <<
> EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_SHIFT)
> +
> +#define EXYNOS5_CLKDIV_LEX_ATCLK_LEX_SHIFT	(8)
> +#define EXYNOS5_CLKDIV_LEX_ATCLK_LEX_MASK	(0x7 <<
> EXYNOS5_CLKDIV_LEX_ATCLK_LEX_SHIFT)
> +#define EXYNOS5_CLKDIV_LEX_PCLK_LEX_SHIFT	(4)
> +#define EXYNOS5_CLKDIV_LEX_PCLK_LEX_MASK	(0x7 <<
> EXYNOS5_CLKDIV_LEX_PCLK_LEX_SHIFT)
> +
> +#define EXYNOS5_CLKDIV_R0X_PCLK_R0X_SHIFT	(4)
> +#define EXYNOS5_CLKDIV_R0X_PCLK_R0X_MASK	(0x7 <<
> EXYNOS5_CLKDIV_R0X_PCLK_R0X_SHIFT)
> +
> +#define EXYNOS5_CLKDIV_R1X_PCLK_R1X_SHIFT	(4)
> +#define EXYNOS5_CLKDIV_R1X_PCLK_R1X_MASK	(0x7 <<
> EXYNOS5_CLKDIV_R1X_PCLK_R1X_SHIFT)
> +
>  #define PWR_CTRL1_CORE2_DOWN_RATIO		(7 << 28)
>  #define PWR_CTRL1_CORE1_DOWN_RATIO		(7 << 16)
>  #define PWR_CTRL1_DIV2_DOWN_EN			(1 << 9)
> diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-
> samsung/include/plat/map-s5p.h
> index 038aa96..28bef98 100644
> --- a/arch/arm/plat-samsung/include/plat/map-s5p.h
> +++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
> @@ -42,6 +42,12 @@
> 
>  #define S5P_VA_AUDSS		S3C_ADDR(0x02830000)
> 
> +#define S5P_VA_PPMU_CPU		S3C_ADDR(0x02840000)
> +#define S5P_VA_PPMU_DDR_C	S3C_ADDR(0x02842000)
> +#define S5P_VA_PPMU_DDR_R1	S3C_ADDR(0x02844000)
> +#define S5P_VA_PPMU_DDR_L	S3C_ADDR(0x02846000)
> +#define S5P_VA_PPMU_RIGHT	S3C_ADDR(0x02848000)
> +
>  #define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
>  #define VA_VIC0			VA_VIC(0)
>  #define VA_VIC1			VA_VIC(1)
> --
> 1.7.8.6

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Abhilash Kesavan Dec. 12, 2012, 3:03 a.m. UTC | #2
On Tue, Dec 11, 2012 at 5:29 AM, Jonghwan Choi <jhbird.choi@samsung.com> wrote:
> Hi Abhilash Kesavan.
Hi Mr Choi,

Thanks for your comments.
>
>
>> +     /* Change Divider - LEX */
>> +     tmp = __raw_readl(EXYNOS5_CLKDIV_LEX);
>> +
>> +     tmp &= ~(EXYNOS5_CLKDIV_LEX_ATCLK_LEX_MASK |
>> +             EXYNOS5_CLKDIV_LEX_PCLK_LEX_MASK);
>> +
>> +     tmp |= int_freq[div_index].clk_div_lex;
>> +
>> +     __raw_writel(tmp, EXYNOS5_CLKDIV_LEX);
>> +
>
> I knew that only ATCLK_LEX & PCLK_LEX divider value are in CLKDIV_LEX
> register. (Others are reserved and value is 0)
> So, I think
> "
> tmp = int_freq[div_index].clk_div_lex;
> __raw_writel(tmp, EXYNOS5_CLKDIV_LEX);
> "
> Is enough.
>
>> +     tmp = __raw_readl(EXYNOS5_CLKDIV_LEX);
>> +
>> +     tmp &= ~(EXYNOS5_CLKDIV_LEX_ATCLK_LEX_MASK |
>> +             EXYNOS5_CLKDIV_LEX_PCLK_LEX_MASK);
> -> not need.
>
>
>
>> +     while (__raw_readl(EXYNOS5_CLKDIV_STAT_LEX) & 0x110)
>> +             cpu_relax();
>> +
>> +     /* Change Divider - R0X */
>> +     tmp = __raw_readl(EXYNOS5_CLKDIV_R0X);
>> +
>> +     tmp &= ~EXYNOS5_CLKDIV_R0X_PCLK_R0X_MASK;
>> +
>> +     tmp |= int_freq[div_index].clk_div_r0x;
>> +
>> +     __raw_writel(tmp, EXYNOS5_CLKDIV_R0X);
>> +
>
> Same here
>
>
>> +     while (__raw_readl(EXYNOS5_CLKDIV_STAT_R0X) & 0x10)
>> +             cpu_relax();
>> +
>> +     /* Change Divider - R1X */
>> +     tmp = __raw_readl(EXYNOS5_CLKDIV_R1X);
>> +
>> +     tmp &= ~EXYNOS5_CLKDIV_R1X_PCLK_R1X_MASK;
>> +
>> +     tmp |= int_freq[div_index].clk_div_r1x;
>> +
>> +     __raw_writel(tmp, EXYNOS5_CLKDIV_R1X);
>> +
>
> Same here
>
>> +     while (__raw_readl(EXYNOS5_CLKDIV_STAT_R1X) & 0x10)
>> +             cpu_relax();
>
> How about your opinion?
I have verified the registers against the 5250 User Manual. You are
right on all counts.
I will fix them all and re-post.
>
> thanks
Regards,
Abhilash
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c
index 5c63bc7..f00b259 100644
--- a/arch/arm/mach-exynos/clock-exynos5.c
+++ b/arch/arm/mach-exynos/clock-exynos5.c
@@ -109,6 +109,11 @@  static struct clk exynos5_clk_sclk_usbphy = {
 	.rate		= 48000000,
 };
 
+/* Virtual Bus INT clock */
+static struct clk exynos5_int_clk = {
+	.name		= "int_clk",
+};
+
 static int exynos5_clksrc_mask_top_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_TOP, clk, enable);
@@ -1519,6 +1524,149 @@  static struct clk *exynos5_clks[] __initdata = {
 	&clk_fout_cpll,
 	&clk_fout_mpll_div2,
 	&exynos5_clk_armclk,
+	&exynos5_int_clk,
+};
+
+#define INT_FREQ(f, a0, a1, a2, a3, a4, a5, b0, b1, b2, b3, \
+			c0, c1, d0, e0) \
+	{ \
+		.freq = (f) * 1000000, \
+		.clk_div_top0 = ((a0) << 0 | (a1) << 8 | (a2) << 12 | \
+				(a3) << 16 | (a4) << 20 | (a5) << 28), \
+		.clk_div_top1 = ((b0) << 12 | (b1) << 16 | (b2) << 20 | \
+				(b3) << 24), \
+		.clk_div_lex = ((c0) << 4 | (c1) << 8), \
+		.clk_div_r0x = ((d0) << 4), \
+		.clk_div_r1x = ((e0) << 4), \
+	}
+
+static struct {
+	unsigned long freq;
+	u32 clk_div_top0;
+	u32 clk_div_top1;
+	u32 clk_div_lex;
+	u32 clk_div_r0x;
+	u32 clk_div_r1x;
+} int_freq[] = {
+	/*
+	 * values:
+	 * freq
+	 * clock divider for ACLK66, ACLK166, ACLK200, ACLK266,
+			ACLK333, ACLK300_DISP1
+	 * clock divider for ACLK300_GSCL, ACLK400_IOP, ACLK400_ISP, ACLK66_PRE
+	 * clock divider for PCLK_LEX, ATCLK_LEX
+	 * clock divider for ACLK_PR0X
+	 * clock divider for ACLK_PR1X
+	 */
+	INT_FREQ(266, 1, 1, 3, 2, 0, 0, 0, 1, 1, 5, 1, 0, 1, 1),
+	INT_FREQ(200, 1, 2, 4, 3, 1, 0, 0, 3, 2, 5, 1, 0, 1, 1),
+	INT_FREQ(160, 1, 3, 4, 4, 2, 0, 0, 3, 3, 5, 1, 0, 1, 1),
+	INT_FREQ(133, 1, 3, 5, 5, 2, 1, 1, 4, 4, 5, 1, 0, 1, 1),
+	INT_FREQ(100, 1, 7, 7, 7, 7, 3, 7, 7, 7, 5, 1, 0, 1, 1),
+};
+
+static unsigned long exynos5_clk_int_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+static void exynos5_int_set_clkdiv(unsigned int div_index)
+{
+	unsigned int tmp;
+
+	/* Change Divider - TOP0 */
+	tmp = __raw_readl(EXYNOS5_CLKDIV_TOP0);
+
+	tmp &= ~(EXYNOS5_CLKDIV_TOP0_ACLK266_MASK |
+		EXYNOS5_CLKDIV_TOP0_ACLK200_MASK |
+		EXYNOS5_CLKDIV_TOP0_ACLK66_MASK |
+		EXYNOS5_CLKDIV_TOP0_ACLK333_MASK |
+		EXYNOS5_CLKDIV_TOP0_ACLK166_MASK |
+		EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_MASK);
+
+	tmp |= int_freq[div_index].clk_div_top0;
+
+	__raw_writel(tmp, EXYNOS5_CLKDIV_TOP0);
+
+	while (__raw_readl(EXYNOS5_CLKDIV_STAT_TOP0) & 0x151101)
+		cpu_relax();
+
+	/* Change Divider - TOP1 */
+	tmp = __raw_readl(EXYNOS5_CLKDIV_TOP1);
+
+	tmp &= ~(EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_MASK |
+		EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_MASK |
+		EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_MASK |
+		EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_MASK);
+
+	tmp |= int_freq[div_index].clk_div_top1;
+
+	__raw_writel(tmp, EXYNOS5_CLKDIV_TOP1);
+
+	while ((__raw_readl(EXYNOS5_CLKDIV_STAT_TOP1) & 0x1110000) &&
+		(__raw_readl(EXYNOS5_CLKDIV_STAT_TOP0) & 0x80000))
+		cpu_relax();
+
+	/* Change Divider - LEX */
+	tmp = __raw_readl(EXYNOS5_CLKDIV_LEX);
+
+	tmp &= ~(EXYNOS5_CLKDIV_LEX_ATCLK_LEX_MASK |
+		EXYNOS5_CLKDIV_LEX_PCLK_LEX_MASK);
+
+	tmp |= int_freq[div_index].clk_div_lex;
+
+	__raw_writel(tmp, EXYNOS5_CLKDIV_LEX);
+
+	while (__raw_readl(EXYNOS5_CLKDIV_STAT_LEX) & 0x110)
+		cpu_relax();
+
+	/* Change Divider - R0X */
+	tmp = __raw_readl(EXYNOS5_CLKDIV_R0X);
+
+	tmp &= ~EXYNOS5_CLKDIV_R0X_PCLK_R0X_MASK;
+
+	tmp |= int_freq[div_index].clk_div_r0x;
+
+	__raw_writel(tmp, EXYNOS5_CLKDIV_R0X);
+
+	while (__raw_readl(EXYNOS5_CLKDIV_STAT_R0X) & 0x10)
+		cpu_relax();
+
+	/* Change Divider - R1X */
+	tmp = __raw_readl(EXYNOS5_CLKDIV_R1X);
+
+	tmp &= ~EXYNOS5_CLKDIV_R1X_PCLK_R1X_MASK;
+
+	tmp |= int_freq[div_index].clk_div_r1x;
+
+	__raw_writel(tmp, EXYNOS5_CLKDIV_R1X);
+
+	while (__raw_readl(EXYNOS5_CLKDIV_STAT_R1X) & 0x10)
+		cpu_relax();
+}
+
+static int exynos5_clk_int_set_rate(struct clk *clk, unsigned long rate)
+{
+	int index;
+
+	for (index = 0; index < ARRAY_SIZE(int_freq); index++)
+		if (int_freq[index].freq == rate)
+			break;
+
+	if (index == ARRAY_SIZE(int_freq))
+		return -EINVAL;
+
+	/* Change the system clock divider values */
+	exynos5_int_set_clkdiv(index);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+static struct clk_ops exynos5_clk_int_ops = {
+	.get_rate = exynos5_clk_int_get_rate,
+	.set_rate = exynos5_clk_int_set_rate
 };
 
 static u32 epll_div[][6] = {
@@ -1713,6 +1861,9 @@  void __init_or_cpufreq exynos5_setup_clocks(void)
 
 	clk_fout_epll.ops = &exynos5_epll_ops;
 
+	exynos5_int_clk.ops = &exynos5_clk_int_ops;
+	exynos5_int_clk.rate = aclk_266;
+
 	if (clk_set_parent(&exynos5_clk_mout_epll.clk, &clk_fout_epll))
 		printk(KERN_ERR "Unable to set parent %s of clock %s.\n",
 				clk_fout_epll.name, exynos5_clk_mout_epll.clk.name);
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 73b940f..6b7d4ee 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -282,6 +282,31 @@  static struct map_desc exynos5_iodesc[] __initdata = {
 		.pfn		= __phys_to_pfn(EXYNOS5_PA_UART),
 		.length		= SZ_512K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual        = (unsigned long)S5P_VA_PPMU_CPU,
+		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_CPU),
+		.length         = SZ_8K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual        = (unsigned long)S5P_VA_PPMU_DDR_C,
+		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_DDR_C),
+		.length         = SZ_8K,
+		.type           = MT_DEVICE,
+	}, {
+		.virtual        = (unsigned long)S5P_VA_PPMU_DDR_R1,
+		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_DDR_R1),
+		.length         = SZ_8K,
+		.type           = MT_DEVICE,
+	}, {
+		.virtual        = (unsigned long)S5P_VA_PPMU_DDR_L,
+		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_DDR_L),
+		.length         = SZ_8K,
+		.type           = MT_DEVICE,
+	}, {
+		.virtual        = (unsigned long)S5P_VA_PPMU_RIGHT,
+		.pfn            = __phys_to_pfn(EXYNOS5_PA_PPMU_RIGHT),
+		.length         = SZ_8K,
+		.type           = MT_DEVICE,
 	},
 };
 
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index cbb2852..8c8de91 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -228,6 +228,12 @@ 
 #define EXYNOS4_PA_SDRAM		0x40000000
 #define EXYNOS5_PA_SDRAM		0x40000000
 
+#define EXYNOS5_PA_PPMU_DDR_C		0x10C40000
+#define EXYNOS5_PA_PPMU_DDR_R1		0x10C50000
+#define EXYNOS5_PA_PPMU_CPU		0x10C60000
+#define EXYNOS5_PA_PPMU_DDR_L		0x10CB0000
+#define EXYNOS5_PA_PPMU_RIGHT		0x13660000
+
 /* Compatibiltiy Defines */
 
 #define S3C_PA_HSMMC0			EXYNOS4_PA_HSMMC(0)
diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h
index d36ad76..bad3cd3 100644
--- a/arch/arm/mach-exynos/include/mach/regs-clock.h
+++ b/arch/arm/mach-exynos/include/mach/regs-clock.h
@@ -323,6 +323,9 @@ 
 #define EXYNOS5_CLKDIV_PERIC5			EXYNOS_CLKREG(0x1056C)
 #define EXYNOS5_SCLK_DIV_ISP			EXYNOS_CLKREG(0x10580)
 
+#define EXYNOS5_CLKDIV_STAT_TOP0		EXYNOS_CLKREG(0x10610)
+#define EXYNOS5_CLKDIV_STAT_TOP1		EXYNOS_CLKREG(0x10614)
+
 #define EXYNOS5_CLKGATE_IP_ACP			EXYNOS_CLKREG(0x08800)
 #define EXYNOS5_CLKGATE_IP_ISP0			EXYNOS_CLKREG(0x0C800)
 #define EXYNOS5_CLKGATE_IP_ISP1			EXYNOS_CLKREG(0x0C804)
@@ -337,6 +340,18 @@ 
 #define EXYNOS5_CLKGATE_IP_PERIS		EXYNOS_CLKREG(0x10960)
 #define EXYNOS5_CLKGATE_BLOCK			EXYNOS_CLKREG(0x10980)
 
+#define EXYNOS5_CLKGATE_BUS_SYSLFT		EXYNOS_CLKREG(0x08920)
+
+#define EXYNOS5_CLKOUT_CMU_TOP			EXYNOS_CLKREG(0x10A00)
+
+#define EXYNOS5_CLKDIV_LEX			EXYNOS_CLKREG(0x14500)
+#define EXYNOS5_CLKDIV_STAT_LEX			EXYNOS_CLKREG(0x14600)
+
+#define EXYNOS5_CLKDIV_R0X			EXYNOS_CLKREG(0x18500)
+#define EXYNOS5_CLKDIV_STAT_R0X			EXYNOS_CLKREG(0x18600)
+
+#define EXYNOS5_CLKDIV_R1X			EXYNOS_CLKREG(0x1C500)
+#define EXYNOS5_CLKDIV_STAT_R1X			EXYNOS_CLKREG(0x1C600)
 #define EXYNOS5_BPLL_CON0			EXYNOS_CLKREG(0x20110)
 #define EXYNOS5_CLKSRC_CDREX			EXYNOS_CLKREG(0x20200)
 #define EXYNOS5_CLKDIV_CDREX			EXYNOS_CLKREG(0x20500)
@@ -347,6 +362,39 @@ 
 
 #define EXYNOS5_EPLLCON0_LOCKED_SHIFT		(29)
 
+#define EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_SHIFT	(28)
+#define EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_MASK	(0x7 << EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_SHIFT)
+#define EXYNOS5_CLKDIV_TOP0_ACLK333_SHIFT	(20)
+#define EXYNOS5_CLKDIV_TOP0_ACLK333_MASK	(0x7 << EXYNOS5_CLKDIV_TOP0_ACLK333_SHIFT)
+#define EXYNOS5_CLKDIV_TOP0_ACLK266_SHIFT	(16)
+#define EXYNOS5_CLKDIV_TOP0_ACLK266_MASK	(0x7 << EXYNOS5_CLKDIV_TOP0_ACLK266_SHIFT)
+#define EXYNOS5_CLKDIV_TOP0_ACLK200_SHIFT	(12)
+#define EXYNOS5_CLKDIV_TOP0_ACLK200_MASK	(0x7 << EXYNOS5_CLKDIV_TOP0_ACLK200_SHIFT)
+#define EXYNOS5_CLKDIV_TOP0_ACLK166_SHIFT	(8)
+#define EXYNOS5_CLKDIV_TOP0_ACLK166_MASK	(0x7 << EXYNOS5_CLKDIV_TOP0_ACLK166_SHIFT)
+#define EXYNOS5_CLKDIV_TOP0_ACLK66_SHIFT	(0)
+#define EXYNOS5_CLKDIV_TOP0_ACLK66_MASK		(0x7 << EXYNOS5_CLKDIV_TOP0_ACLK66_SHIFT)
+
+#define EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_SHIFT	(24)
+#define EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_MASK	(0x7 << EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_SHIFT)
+#define EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_SHIFT	(20)
+#define EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_MASK	(0x7 << EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_SHIFT)
+#define EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_SHIFT	(16)
+#define EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_MASK	(0x7 << EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_SHIFT)
+#define EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_SHIFT	(12)
+#define EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_MASK	(0x7 << EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_SHIFT)
+
+#define EXYNOS5_CLKDIV_LEX_ATCLK_LEX_SHIFT	(8)
+#define EXYNOS5_CLKDIV_LEX_ATCLK_LEX_MASK	(0x7 << EXYNOS5_CLKDIV_LEX_ATCLK_LEX_SHIFT)
+#define EXYNOS5_CLKDIV_LEX_PCLK_LEX_SHIFT	(4)
+#define EXYNOS5_CLKDIV_LEX_PCLK_LEX_MASK	(0x7 << EXYNOS5_CLKDIV_LEX_PCLK_LEX_SHIFT)
+
+#define EXYNOS5_CLKDIV_R0X_PCLK_R0X_SHIFT	(4)
+#define EXYNOS5_CLKDIV_R0X_PCLK_R0X_MASK	(0x7 << EXYNOS5_CLKDIV_R0X_PCLK_R0X_SHIFT)
+
+#define EXYNOS5_CLKDIV_R1X_PCLK_R1X_SHIFT	(4)
+#define EXYNOS5_CLKDIV_R1X_PCLK_R1X_MASK	(0x7 << EXYNOS5_CLKDIV_R1X_PCLK_R1X_SHIFT)
+
 #define PWR_CTRL1_CORE2_DOWN_RATIO		(7 << 28)
 #define PWR_CTRL1_CORE1_DOWN_RATIO		(7 << 16)
 #define PWR_CTRL1_DIV2_DOWN_EN			(1 << 9)
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index 038aa96..28bef98 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -42,6 +42,12 @@ 
 
 #define S5P_VA_AUDSS		S3C_ADDR(0x02830000)
 
+#define S5P_VA_PPMU_CPU		S3C_ADDR(0x02840000)
+#define S5P_VA_PPMU_DDR_C	S3C_ADDR(0x02842000)
+#define S5P_VA_PPMU_DDR_R1	S3C_ADDR(0x02844000)
+#define S5P_VA_PPMU_DDR_L	S3C_ADDR(0x02846000)
+#define S5P_VA_PPMU_RIGHT	S3C_ADDR(0x02848000)
+
 #define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
 #define VA_VIC0			VA_VIC(0)
 #define VA_VIC1			VA_VIC(1)