[PATCH] ARM: s3c24xx: Add special bus clock ratio mode support for S3C2410A
Alexander Shiyan
shc_work at mail.ru
Sun Mar 3 11:22:06 EST 2013
This patch adds a special bus clock ratio mode support (1:4:4) for
S3C2410A CPU targets. This mode means that the HCLK and PCLK frequency
is the same as the FCLK/4.
Signed-off-by: Alexander Shiyan <shc_work at mail.ru>
---
arch/arm/mach-s3c24xx/cpufreq-s3c2410.c | 36 ++++++++++++++-----------
arch/arm/mach-s3c24xx/include/mach/regs-clock.h | 1 +
arch/arm/mach-s3c24xx/include/mach/regs-gpio.h | 1 +
arch/arm/mach-s3c24xx/s3c2410.c | 11 ++++++--
4 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/arch/arm/mach-s3c24xx/cpufreq-s3c2410.c b/arch/arm/mach-s3c24xx/cpufreq-s3c2410.c
index cfa0dd8..0890ab7 100644
--- a/arch/arm/mach-s3c24xx/cpufreq-s3c2410.c
+++ b/arch/arm/mach-s3c24xx/cpufreq-s3c2410.c
@@ -24,22 +24,25 @@
#include <asm/mach/map.h>
#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
#include <plat/cpu.h>
#include <plat/clock.h>
#include <plat/cpu-freq-core.h>
-/* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */
-
static void s3c2410_cpufreq_setdivs(struct s3c_cpufreq_config *cfg)
{
u32 clkdiv = 0;
- if (cfg->divs.h_divisor == 2)
- clkdiv |= S3C2410_CLKDIVN_HDIVN;
+ if (cfg->divs.h_divisor == 4) {
+ clkdiv = S3C2410_CLKDIVN_HDIVN1;
+ } else {
+ if (cfg->divs.h_divisor == 2)
+ clkdiv = S3C2410_CLKDIVN_HDIVN;
- if (cfg->divs.p_divisor != cfg->divs.h_divisor)
- clkdiv |= S3C2410_CLKDIVN_PDIVN;
+ if (cfg->divs.p_divisor != cfg->divs.h_divisor)
+ clkdiv |= S3C2410_CLKDIVN_PDIVN;
+ }
__raw_writel(clkdiv, S3C2410_CLKDIVN);
}
@@ -48,27 +51,27 @@ static int s3c2410_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg)
{
unsigned long hclk, fclk, pclk;
unsigned int hdiv, pdiv;
- unsigned long hclk_max;
fclk = cfg->freq.fclk;
- hclk_max = cfg->max.hclk;
-
- cfg->freq.armclk = fclk;
-
- s3c_freq_dbg("%s: fclk is %lu, max hclk %lu\n",
- __func__, fclk, hclk_max);
hdiv = (fclk > cfg->max.hclk) ? 2 : 1;
hclk = fclk / hdiv;
+ pdiv = (hclk > cfg->max.pclk) ? 2 : 1;
+ pclk = hclk / pdiv;
+
+ if ((samsung_cpu_id == S3C2410_GSTATUS1_2410A) &&
+ ((hclk > cfg->max.hclk) || (pclk > cfg->max.pclk))) {
+ hdiv = 4;
+ hclk = fclk / 4;
+ pdiv = 1;
+ pclk = fclk / 4;
+ }
if (hclk > cfg->max.hclk) {
s3c_freq_dbg("%s: hclk too big\n", __func__);
return -EINVAL;
}
- pdiv = (hclk > cfg->max.pclk) ? 2 : 1;
- pclk = hclk / pdiv;
-
if (pclk > cfg->max.pclk) {
s3c_freq_dbg("%s: pclk too big\n", __func__);
return -EINVAL;
@@ -77,6 +80,7 @@ static int s3c2410_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg)
pdiv *= hdiv;
/* record the result */
+ cfg->freq.armclk = fclk;
cfg->divs.p_divisor = pdiv;
cfg->divs.h_divisor = hdiv;
diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-clock.h b/arch/arm/mach-s3c24xx/include/mach/regs-clock.h
index 3415b60..15b707b 100644
--- a/arch/arm/mach-s3c24xx/include/mach/regs-clock.h
+++ b/arch/arm/mach-s3c24xx/include/mach/regs-clock.h
@@ -62,6 +62,7 @@
#define S3C2410_CLKDIVN_PDIVN (1<<0)
#define S3C2410_CLKDIVN_HDIVN (1<<1)
+#define S3C2410_CLKDIVN_HDIVN1 (1<<2)
#define S3C2410_CLKSLOW_UCLK_OFF (1<<7)
#define S3C2410_CLKSLOW_MPLL_OFF (1<<5)
diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
index c2ef016..ff8ef6a 100644
--- a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
@@ -571,6 +571,7 @@
#define S3C2410_GSTATUS1_IDMASK (0xffff0000)
#define S3C2410_GSTATUS1_2410 (0x32410000)
+#define S3C2410_GSTATUS1_2410A (0x32410002)
#define S3C2410_GSTATUS1_2412 (0x32412001)
#define S3C2410_GSTATUS1_2416 (0x32416003)
#define S3C2410_GSTATUS1_2440 (0x32440000)
diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c
index 9ebef95..c512dac 100644
--- a/arch/arm/mach-s3c24xx/s3c2410.c
+++ b/arch/arm/mach-s3c24xx/s3c2410.c
@@ -35,6 +35,7 @@
#include <plat/cpu-freq.h>
#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
#include <plat/regs-serial.h>
#include <plat/s3c2410.h>
@@ -104,8 +105,14 @@ void __init_or_cpufreq s3c2410_setup_clocks(void)
/* work out clock scalings */
- hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1);
- pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1);
+ if ((samsung_cpu_id == S3C2410_GSTATUS1_2410A) &&
+ (tmp & S3C2410_CLKDIVN_HDIVN1)) {
+ hclk = fclk / 4;
+ pclk = fclk / 4;
+ } else {
+ hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1);
+ pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1);
+ }
/* print brieft summary of clocks, etc */
--
1.7.12.4
More information about the linux-arm-kernel
mailing list