summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhou Jingyu <b02241@freescale.com>2009-09-15 17:56:31 +0800
committerZhou Jingyu <b02241@freescale.com>2009-09-18 17:05:24 +0800
commitbd04b0611b90bdc0d8a3afe588c3c3f5bdb2d199 (patch)
treec4089fbd653c7812edd4831dc5571346bda05247
parent9fee1397ee241041c6f4eef8b49117ce21be1012 (diff)
ENGR00116507 imx233: Add 24MHZ cpu profile
Add 24MHZ cpu profile Signed-off-by: Zhou Jingyu <Jingyu.Zhou@freescale.com>
-rw-r--r--arch/arm/mach-stmp3xxx/cpufreq.c85
1 files changed, 77 insertions, 8 deletions
diff --git a/arch/arm/mach-stmp3xxx/cpufreq.c b/arch/arm/mach-stmp3xxx/cpufreq.c
index 800258008d59..8acdc1e10678 100644
--- a/arch/arm/mach-stmp3xxx/cpufreq.c
+++ b/arch/arm/mach-stmp3xxx/cpufreq.c
@@ -37,8 +37,11 @@
#include <mach/regulator.h>
#include <mach/power.h>
#include <mach/regs-digctl.h>
+#include <mach/regs-clkctrl.h>
#define VERY_HI_RATE 2000000000
+#define CLKCTRL_PLL_PWD_BIT 16
+#define CLKCTRL_PLL_BYPASS 0x1ff
static struct profile {
int cpu;
@@ -48,12 +51,22 @@ static struct profile {
int vddd;
int vddd_bo;
int cur;
+ int vddio;
+ int vdda;
+ int pll_off;
} profiles[] = {
- { 64000, 64000, 48000, 3, 1000000, 925000, 150000 },
- { 261820, 130910, 130910, 0, 1225000, 1125000, 173000 },
- { 360000, 120000, 120000, 0, 1350000, 1250000, 200000 },
- { 392730, 130910, 130910, 0, 1400000, 1300000, 225000 },
- { 454740, 151580, 151580, 0, 1550000, 1450000, 355000 },
+ { 24000, 24000, 24000, 3, 1000000,
+ 925000, 150000, 3075000, 1725000, 1 },
+ { 64000, 64000, 48000, 3, 1000000,
+ 925000, 150000, 3300000, 1750000, 0 },
+ { 261820, 130910, 130910, 0, 1225000,
+ 1125000, 173000, 3300000, 1750000, 0 },
+ { 360000, 120000, 120000, 0, 1350000,
+ 1250000, 200000, 3300000, 1750000, 0 },
+ { 392730, 130910, 130910, 0, 1400000,
+ 1300000, 225000, 3300000, 1750000, 0 },
+ { 454740, 151580, 151580, 0, 1550000,
+ 1450000, 355000, 3300000, 1750000, 0 },
};
static struct stmp3xxx_cpufreq {
@@ -66,6 +79,8 @@ static struct stmp3xxx_cpufreq {
spinlock_t lock;
} cpufreq_bdata;
+static u32 clkseq_setting;
+
static int reg_callback(struct notifier_block *, unsigned long, void *);
static int init_reg_callback(struct notifier_block *, unsigned long, void *);
@@ -149,7 +164,7 @@ static unsigned int stmp3xxx_getspeed(unsigned int cpu)
static int set_op(unsigned int target_freq)
{
struct clk *cpu_clk, *ahb_clk, *emi_clk;
- struct regulator *vddd, *vdddbo, *cur_limit;
+ struct regulator *vddd, *vdddbo, *cur_limit, *vddio, *vdda;
struct cpufreq_freqs freqs;
int ret = 0, i;
@@ -175,6 +190,16 @@ static int set_op(unsigned int target_freq)
vdddbo = regulator_get(NULL, "vddd_bo");
if (IS_ERR(vdddbo))
vdddbo = NULL;
+ vddio = regulator_get(NULL, "vddio");
+ if (IS_ERR(vddio)) {
+ vddio = NULL;
+ pr_warning("unable to get vddio");
+ }
+ vdda = regulator_get(NULL, "vdda");
+ if (IS_ERR(vdda)) {
+ vdda = NULL;
+ pr_warning("unable to get vddio");
+ }
freqs.old = clk_get_rate(cpu_clk);
freqs.cpu = 0;
@@ -213,6 +238,14 @@ static int set_op(unsigned int target_freq)
i, freqs.old, freqs.new);
spin_lock(&cpufreq_bdata.lock);
+
+ if (freqs.old == 24000 && freqs.new > 24000) {
+ /* turn pll on */
+ HW_CLKCTRL_PLLCTRL0_SET(CLKCTRL_PLL_PWD_BIT);
+ udelay(10);
+ } else if (freqs.old > 24000 && freqs.new == 24000)
+ clkseq_setting = HW_CLKCTRL_CLKSEQ_RD();
+
if (cur_limit && (freqs.old < freqs.new)) {
ret = regulator_set_current_limit(cur_limit, profiles[i].cur, profiles[i].cur);
if (ret)
@@ -230,23 +263,48 @@ static int set_op(unsigned int target_freq)
BF_DIGCTL_ARMCACHE_CACHE_SS(ss) |
BF_DIGCTL_ARMCACHE_DTAG_SS(ss) |
BF_DIGCTL_ARMCACHE_ITAG_SS(ss));
- if (vddd && vdddbo) {
+ if (vddd && vdddbo && vddio && vdda) {
ret = regulator_set_voltage(vddd, profiles[i].vddd, profiles[i].vddd);
if (ret)
ret = regulator_set_voltage(vddd,
profiles[i].vddd,
profiles[i].vddd);
regulator_set_voltage(vdddbo, profiles[i].vddd_bo, profiles[i].vddd_bo);
+
+ ret = regulator_set_voltage(vddio, profiles[i].vddio,
+ profiles[i].vddio);
+ if (ret)
+ ret = regulator_set_voltage(vddio,
+ profiles[i].vddio,
+ profiles[i].vddio);
+ ret = regulator_set_voltage(vdda, profiles[i].vdda,
+ profiles[i].vdda);
+ if (ret)
+ ret = regulator_set_voltage(vdda,
+ profiles[i].vdda,
+ profiles[i].vdda);
}
} else {
int ss = profiles[i].ss;
- if (vddd && vdddbo) {
+ if (vddd && vdddbo && vddio && vdda) {
ret = regulator_set_voltage(vddd, profiles[i].vddd, profiles[i].vddd);
if (ret)
ret = regulator_set_voltage(vddd,
profiles[i].vddd,
profiles[i].vddd);
regulator_set_voltage(vdddbo, profiles[i].vddd_bo, profiles[i].vddd_bo);
+ ret = regulator_set_voltage(vddio, profiles[i].vddio,
+ profiles[i].vddio);
+ if (ret)
+ ret = regulator_set_voltage(vddio,
+ profiles[i].vddio,
+ profiles[i].vddio);
+ ret = regulator_set_voltage(vdda, profiles[i].vdda,
+ profiles[i].vdda);
+ if (ret)
+ ret = regulator_set_voltage(vdda,
+ profiles[i].vdda,
+ profiles[i].vdda);
}
HW_DIGCTL_ARMCACHE_WR(BF_DIGCTL_ARMCACHE_VALID_SS(ss) |
BF_DIGCTL_ARMCACHE_DRTY_SS(ss) |
@@ -259,6 +317,13 @@ static int set_op(unsigned int target_freq)
}
udelay(100);
+ if (freqs.old > 24000 && freqs.new == 24000) {
+ /* turn pll off */
+ HW_CLKCTRL_PLLCTRL0_CLR(CLKCTRL_PLL_PWD_BIT);
+ HW_CLKCTRL_CLKSEQ_WR(CLKCTRL_PLL_BYPASS);
+ } else if (freqs.old == 24000 && freqs.new > 24000)
+ HW_CLKCTRL_CLKSEQ_WR(clkseq_setting);
+
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
if (cur_limit && (freqs.old > freqs.new)) /* will not fail */
@@ -270,6 +335,10 @@ out_cur:
spin_unlock(&cpufreq_bdata.lock);
if (vddd)
regulator_put(vddd);
+ if (vddio)
+ regulator_put(vddio);
+ if (vdda)
+ regulator_put(vdda);
out_vddd:
clk_put(emi_clk);
out_emi: