-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ARM: S3C2410: CPUFREQ: Add core support.
Add core support for frequency scaling on the S3C2410 SoC. Signed-off-by: Ben Dooks <ben@simtec.co.uk> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
- Loading branch information
Ben Dooks
authored and
Ben Dooks
committed
Jul 30, 2009
1 parent
831a6fc
commit a24c091
Showing
6 changed files
with
241 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* linux/arch/arm/mach-s3c2410/cpu-freq.c | ||
* | ||
* Copyright (c) 2006,2008 Simtec Electronics | ||
* http://armlinux.simtec.co.uk/ | ||
* Ben Dooks <ben@simtec.co.uk> | ||
* | ||
* S3C2410 CPU Frequency scaling | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/ioport.h> | ||
#include <linux/cpufreq.h> | ||
#include <linux/sysdev.h> | ||
#include <linux/clk.h> | ||
#include <linux/err.h> | ||
#include <linux/io.h> | ||
|
||
#include <asm/mach/arch.h> | ||
#include <asm/mach/map.h> | ||
|
||
#include <mach/regs-clock.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.p_divisor != cfg->divs.h_divisor) | ||
clkdiv |= S3C2410_CLKDIVN_PDIVN; | ||
|
||
__raw_writel(clkdiv, S3C2410_CLKDIVN); | ||
} | ||
|
||
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; | ||
|
||
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; | ||
} | ||
|
||
pdiv *= hdiv; | ||
|
||
/* record the result */ | ||
cfg->divs.p_divisor = pdiv; | ||
cfg->divs.h_divisor = hdiv; | ||
|
||
return 0 ; | ||
} | ||
|
||
static struct s3c_cpufreq_info s3c2410_cpufreq_info = { | ||
.max = { | ||
.fclk = 200000000, | ||
.hclk = 100000000, | ||
.pclk = 50000000, | ||
}, | ||
|
||
/* transition latency is about 5ms worst-case, so | ||
* set 10ms to be sure */ | ||
.latency = 10000000, | ||
|
||
.locktime_m = 150, | ||
.locktime_u = 150, | ||
.locktime_bits = 12, | ||
|
||
.need_pll = 1, | ||
|
||
.name = "s3c2410", | ||
.calc_iotiming = s3c2410_iotiming_calc, | ||
.set_iotiming = s3c2410_iotiming_set, | ||
.get_iotiming = s3c2410_iotiming_get, | ||
.resume_clocks = s3c2410_setup_clocks, | ||
|
||
.set_fvco = s3c2410_set_fvco, | ||
.set_refresh = s3c2410_cpufreq_setrefresh, | ||
.set_divs = s3c2410_cpufreq_setdivs, | ||
.calc_divs = s3c2410_cpufreq_calcdivs, | ||
}; | ||
|
||
static int s3c2410_cpufreq_add(struct sys_device *sysdev) | ||
{ | ||
return s3c_cpufreq_register(&s3c2410_cpufreq_info); | ||
} | ||
|
||
static struct sysdev_driver s3c2410_cpufreq_driver = { | ||
.add = s3c2410_cpufreq_add, | ||
}; | ||
|
||
static int __init s3c2410_cpufreq_init(void) | ||
{ | ||
return sysdev_driver_register(&s3c2410_sysclass, | ||
&s3c2410_cpufreq_driver); | ||
} | ||
|
||
arch_initcall(s3c2410_cpufreq_init); | ||
|
||
static int s3c2410a_cpufreq_add(struct sys_device *sysdev) | ||
{ | ||
/* alter the maximum freq settings for S3C2410A. If a board knows | ||
* it only has a maximum of 200, then it should register its own | ||
* limits. */ | ||
|
||
s3c2410_cpufreq_info.max.fclk = 266000000; | ||
s3c2410_cpufreq_info.max.hclk = 133000000; | ||
s3c2410_cpufreq_info.max.pclk = 66500000; | ||
s3c2410_cpufreq_info.name = "s3c2410a"; | ||
|
||
return s3c2410_cpufreq_add(sysdev); | ||
} | ||
|
||
static struct sysdev_driver s3c2410a_cpufreq_driver = { | ||
.add = s3c2410a_cpufreq_add, | ||
}; | ||
|
||
static int __init s3c2410a_cpufreq_init(void) | ||
{ | ||
return sysdev_driver_register(&s3c2410a_sysclass, | ||
&s3c2410a_cpufreq_driver); | ||
} | ||
|
||
arch_initcall(s3c2410a_cpufreq_init); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* linux/arch/arm/plat-s3c24xx/s3c2410-cpufreq-utils.c | ||
* | ||
* Copyright (c) 2009 Simtec Electronics | ||
* http://armlinux.simtec.co.uk/ | ||
* Ben Dooks <ben@simtec.co.uk> | ||
* | ||
* S3C24XX CPU Frequency scaling - utils for S3C2410/S3C2440/S3C2442 | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/errno.h> | ||
#include <linux/cpufreq.h> | ||
#include <linux/io.h> | ||
|
||
#include <mach/map.h> | ||
#include <mach/regs-mem.h> | ||
#include <mach/regs-clock.h> | ||
|
||
#include <plat/cpu-freq-core.h> | ||
|
||
/** | ||
* s3c2410_cpufreq_setrefresh - set SDRAM refresh value | ||
* @cfg: The frequency configuration | ||
* | ||
* Set the SDRAM refresh value appropriately for the configured | ||
* frequency. | ||
*/ | ||
void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) | ||
{ | ||
struct s3c_cpufreq_board *board = cfg->board; | ||
unsigned long refresh; | ||
unsigned long refval; | ||
|
||
/* Reduce both the refresh time (in ns) and the frequency (in MHz) | ||
* down to ensure that we do not overflow 32 bit numbers. | ||
* | ||
* This should work for HCLK up to 133MHz and refresh period up | ||
* to 30usec. | ||
*/ | ||
|
||
refresh = (cfg->freq.hclk / 100) * (board->refresh / 10); | ||
refresh = DIV_ROUND_UP(refresh, (1000 * 1000)); /* apply scale */ | ||
refresh = (1 << 11) + 1 - refresh; | ||
|
||
s3c_freq_dbg("%s: refresh value %lu\n", __func__, refresh); | ||
|
||
refval = __raw_readl(S3C2410_REFRESH); | ||
refval &= ~((1 << 12) - 1); | ||
refval |= refresh; | ||
__raw_writel(refval, S3C2410_REFRESH); | ||
} | ||
|
||
/** | ||
* s3c2410_set_fvco - set the PLL value | ||
* @cfg: The frequency configuration | ||
*/ | ||
void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg) | ||
{ | ||
__raw_writel(cfg->pll.index, S3C2410_MPLLCON); | ||
} |