[PATCH 38/133] [Jaunty SRU] ARM.imx51 Freescale:ENGR00109146 DVFS: System can not go to APM if DVFS core is enabled
Brad Figg
brad.figg at canonical.com
Thu Jul 9 16:48:28 UTC 2009
DVFS: System can not go to Audio playback mode if DVFS core is enabled.
Signed-off-by: Nancy Chen <Nancy.Chen at freescale.com>
Signed-off-by: Brad Figg <brad.figg at canonical.com>
---
arch/arm/mach-mx51/Makefile | 2 +-
arch/arm/mach-mx51/clock.c | 5 +
arch/arm/mach-mx51/devices.c | 14 ++
arch/arm/plat-mxc/clock.c | 35 ++++-
arch/arm/plat-mxc/cpufreq.c | 336 +++--------------------------------------
arch/arm/plat-mxc/dvfs_core.c | 188 +++++++++++++++--------
6 files changed, 199 insertions(+), 381 deletions(-)
diff --git a/arch/arm/mach-mx51/Makefile b/arch/arm/mach-mx51/Makefile
index 8ff16da..37f49ea 100644
--- a/arch/arm/mach-mx51/Makefile
+++ b/arch/arm/mach-mx51/Makefile
@@ -5,7 +5,7 @@
# Object file lists.
-obj-y := system.o iomux.o cpu.o mm.o clock.o devices.o serial.o dma.o lpmodes.o pm.o
+obj-y := system.o iomux.o cpu.o mm.o clock.o devices.o serial.o dma.o lpmodes.o pm.o bus_freq.o
obj-y += dummy_gpio.o
diff --git a/arch/arm/mach-mx51/clock.c b/arch/arm/mach-mx51/clock.c
index 375224e..878d413 100644
--- a/arch/arm/mach-mx51/clock.c
+++ b/arch/arm/mach-mx51/clock.c
@@ -50,6 +50,7 @@ static struct cpu_wp *cpu_wp_tbl;
int cpu_wp_nr;
extern int mxc_jtag_enabled;
+extern int cpufreq_trig_needed;
static int cpu_clk_set_wp(int wp);
extern void propagate_rate(struct clk *tclk);
@@ -3103,6 +3104,10 @@ static int cpu_clk_set_wp(int wp)
pll1_main_clk.rate = pll1_sw_clk.rate;
cpu_clk.rate = pll1_sw_clk.rate;
}
+
+#if defined(CONFIG_CPU_FREQ)
+ cpufreq_trig_needed = 1;
+#endif
return 0;
}
diff --git a/arch/arm/mach-mx51/devices.c b/arch/arm/mach-mx51/devices.c
index f882174..ab86d1f 100644
--- a/arch/arm/mach-mx51/devices.c
+++ b/arch/arm/mach-mx51/devices.c
@@ -896,6 +896,19 @@ static inline void mx51_init_lpmode(void)
(void)platform_device_register(&mx51_lpmode_device);
}
+static struct platform_device busfreq_device = {
+ .name = "busfreq",
+ .id = 0,
+ .dev = {
+ .release = mxc_nop_release,
+ },
+};
+
+static inline void mxc_init_busfreq(void)
+{
+ (void)platform_device_register(&busfreq_device);
+}
+
#if defined(CONFIG_MXC_IIM) || defined(CONFIG_MXC_IIM_MODULE)
static struct resource mxc_iim_resources[] = {
{
@@ -942,6 +955,7 @@ int __init mxc_init_devices(void)
mxc_init_spdif();
mxc_init_tve();
mx51_init_lpmode();
+ mxc_init_busfreq();
mxc_init_dvfs();
mxc_init_iim();
return 0;
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index b55a03f..c15386c 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -41,6 +41,16 @@
#include <mach/clock.h>
+#if (defined(CONFIG_ARCH_MX51) || defined(CONFIG_ARCH_MX37))
+extern int dvfs_core_is_active;
+extern void dvfs_core_set_bus_freq(void);
+#else
+int dvfs_core_is_active;
+void dvfs_core_set_bus_freq(void)
+{
+};
+#endif
+
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clockfw_lock);
@@ -159,11 +169,18 @@ int clk_enable(struct clk *clk)
spin_unlock_irqrestore(&clockfw_lock, flags);
-#if defined(CONFIG_CPU_FREQ)
if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
- && (clk_get_usecount(clk) == 1))
- cpufreq_update_policy(0);
+ && (clk_get_usecount(clk) == 1)) {
+#if defined(CONFIG_CPU_FREQ)
+ if (dvfs_core_is_active)
+ dvfs_core_set_bus_freq();
+ else
+ cpufreq_update_policy(0);
+#else
+ if (dvfs_core_is_active)
+ dvfs_core_set_bus_freq();
#endif
+ }
return ret;
}
EXPORT_SYMBOL(clk_enable);
@@ -185,12 +202,20 @@ void clk_disable(struct clk *clk)
spin_unlock_irqrestore(&clockfw_lock, flags);
-#if defined(CONFIG_CPU_FREQ)
if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
- && (clk_get_usecount(clk) == 0))
+ && (clk_get_usecount(clk) == 0)) {
+#if defined(CONFIG_CPU_FREQ)
+ if (dvfs_core_is_active)
+ dvfs_core_set_bus_freq();
+ else
cpufreq_update_policy(0);
+#else
+ if (dvfs_core_is_active)
+ dvfs_core_set_bus_freq();
#endif
+ }
}
+
EXPORT_SYMBOL(clk_disable);
/*!
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
index 5e8f977..656622a 100644
--- a/arch/arm/plat-mxc/cpufreq.c
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -36,40 +36,23 @@
#include <mach/clock.h>
#include <asm/cacheflush.h>
-int low_bus_freq_mode;
-int high_bus_freq_mode;
int cpu_freq_khz_min;
int cpu_freq_khz_max;
int arm_lpm_clk;
int arm_normal_clk;
-char *gp_reg_id = "SW1";
-char *lp_reg_id = "SW2";
-int axi_c_clk_support;
static struct clk *cpu_clk;
-static struct clk *main_bus_clk;
-static struct clk *pll2;
-static struct clk *axi_a_clk;
-static struct clk *axi_b_clk;
-static struct clk *axi_c_clk;
-static struct clk *emi_core_clk;
-static struct clk *nfc_clk;
-static struct clk *ahb_clk;
-static struct clk *vpu_clk;
-static struct clk *vpu_core_clk;
-static struct clk *arm_axi_clk;
-static struct clk *ddr_clk;
-static struct clk *ipu_clk;
-static struct clk *periph_apm_clk;
-static struct clk *lp_apm;
-static struct clk *osc;
static struct regulator *gp_regulator;
-static struct regulator *lp_regulator;
static struct cpu_wp *cpu_wp_tbl;
static struct cpufreq_frequency_table imx_freq_table[4];
-
+extern int low_bus_freq_mode;
+extern int high_bus_freq_mode;
extern int dvfs_core_is_active;
extern int cpu_wp_nr;
+extern char *gp_reg_id;
+extern int set_low_bus_freq(void);
+extern int set_high_bus_freq(void);
+extern int low_freq_bus_used(void);
#ifdef CONFIG_ARCH_MX51
extern struct cpu_wp *(*get_cpu_wp)(int *wp);
#endif
@@ -120,117 +103,6 @@ static int set_cpu_freq(int freq)
return ret;
}
-static int set_low_bus_freq(void)
-{
- int ret = 0;
- unsigned long lp_lpm_clk;
-
- struct clk *p_clk;
- struct clk *amode_parent_clk;
-
- if (axi_c_clk_support == 0)
- return 0;
-
- lp_lpm_clk = clk_get_rate(lp_apm);
- amode_parent_clk = lp_apm;
- p_clk = clk_get_parent(periph_apm_clk);
-
- /* Make sure osc_clk is the parent of lp_apm. */
- if (clk_get_parent(amode_parent_clk) != osc)
- clk_set_parent(amode_parent_clk, osc);
-
- /* Set the parent of periph_apm_clk to be lp_apm */
- clk_set_parent(periph_apm_clk, amode_parent_clk);
- amode_parent_clk = periph_apm_clk;
-
- p_clk = clk_get_parent(main_bus_clk);
- /* Set the parent of main_bus_clk to be periph_apm_clk */
- clk_set_parent(main_bus_clk, amode_parent_clk);
-
- clk_set_rate(axi_a_clk, lp_lpm_clk);
- clk_set_rate(axi_b_clk, lp_lpm_clk);
- clk_set_rate(axi_c_clk, lp_lpm_clk);
- clk_set_rate(emi_core_clk, lp_lpm_clk);
- clk_set_rate(nfc_clk, 4800000);
- clk_set_rate(ahb_clk, lp_lpm_clk);
-
- amode_parent_clk = emi_core_clk;
-
- p_clk = clk_get_parent(arm_axi_clk);
- if (p_clk != amode_parent_clk)
- clk_set_parent(arm_axi_clk, amode_parent_clk);
-
- p_clk = clk_get_parent(vpu_clk);
- if (p_clk != amode_parent_clk)
- clk_set_parent(vpu_clk, amode_parent_clk);
-
- p_clk = clk_get_parent(vpu_core_clk);
- if (p_clk != amode_parent_clk)
- clk_set_parent(vpu_core_clk, amode_parent_clk);
-
- /* Set the voltage to 1.0v for the LP domain. */
- ret = regulator_set_voltage(lp_regulator, 1000000, 1000000);
- if (ret < 0) {
- printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!!!\n");
- return ret;
- }
-
- low_bus_freq_mode = 1;
- high_bus_freq_mode = 0;
- return ret;
-}
-
-static int set_high_bus_freq(void)
-{
- struct clk *p_clk;
- struct clk *rmode_parent_clk;
- int ret = 0;
-
- if (axi_c_clk_support == 0)
- return 0;
-
- if (!low_bus_freq_mode)
- return ret;
-
- low_bus_freq_mode = 0;
-
- /* Set the voltage to 1.2v for the LP domain. */
- ret = regulator_set_voltage(lp_regulator, 1200000, 1200000);
- if (ret < 0) {
- printk(KERN_DEBUG "COULD NOT SET LP VOLTAGE!!!!!!\n");
- return ret;
- }
-
- rmode_parent_clk = pll2;
-
- /* Set the dividers before setting the parent clock. */
- clk_set_rate(axi_a_clk, 4800000);
- clk_set_rate(axi_b_clk, 4000000);
- clk_set_rate(axi_c_clk, 6000000);
-
- clk_set_rate(emi_core_clk, 4800000);
- clk_set_rate(ahb_clk, 4800000);
-
- /* Set the parent of main_bus_clk to be pll2 */
- p_clk = clk_get_parent(main_bus_clk);
- clk_set_parent(main_bus_clk, rmode_parent_clk);
- udelay(5);
- high_bus_freq_mode = 1;
- return ret;
-}
-
-static int low_freq_bus_used(void)
-{
- if (axi_c_clk_support == 0)
- return 0;
-
- if ((clk_get_usecount(ipu_clk) == 0)
- && (clk_get_usecount(vpu_clk) == 0))
- return 1;
- else
- return 0;
-}
-
static int mxc_verify_speed(struct cpufreq_policy *policy)
{
if (policy->cpu != 0)
@@ -274,6 +146,9 @@ static int mxc_set_target(struct cpufreq_policy *policy,
int low_freq_bus_ready = 0;
int ret = 0;
+ if (dvfs_core_is_active)
+ target_freq = clk_get_rate(cpu_clk) / 1000;
+
/*
* Some governors do not respects CPU and policy lower limits
* which leads to bad things (division by zero etc), ensure
@@ -299,20 +174,22 @@ static int mxc_set_target(struct cpufreq_policy *policy,
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- if ((freq_Hz == arm_lpm_clk) && (!low_bus_freq_mode)
- && (low_freq_bus_ready)) {
- set_low_bus_freq();
- if (!dvfs_core_is_active)
- ret = set_cpu_freq(freq_Hz);
- } else {
- if (!high_bus_freq_mode)
- set_high_bus_freq();
-
- if (!dvfs_core_is_active)
- ret = set_cpu_freq(freq_Hz);
- if (low_bus_freq_mode) {
- if (ret == 0)
+ if (!dvfs_core_is_active) {
+ if ((freq_Hz == arm_lpm_clk) && (!low_bus_freq_mode)
+ && (low_freq_bus_ready)) {
+ set_low_bus_freq();
+ if (!dvfs_core_is_active)
+ ret = set_cpu_freq(freq_Hz);
+ } else {
+ if (!high_bus_freq_mode)
set_high_bus_freq();
+
+ if (!dvfs_core_is_active)
+ ret = set_cpu_freq(freq_Hz);
+ if (low_bus_freq_mode) {
+ if (ret == 0)
+ set_high_bus_freq();
+ }
}
}
@@ -337,115 +214,6 @@ static int __init mxc_cpufreq_driver_init(struct cpufreq_policy *policy)
return PTR_ERR(cpu_clk);
}
- axi_c_clk = clk_get(NULL, "axi_c_clk");
- if (IS_ERR(axi_c_clk)) {
- axi_c_clk_support = 0;
- printk(KERN_ERR "%s: failed to get axi_c_clk\n", __func__);
- } else {
- axi_c_clk_support = 1;
- main_bus_clk = clk_get(NULL, "main_bus_clk");
- if (IS_ERR(main_bus_clk)) {
- printk(KERN_ERR "%s: failed to get main_bus_clk\n",
- __func__);
- return PTR_ERR(main_bus_clk);
- }
-
- pll2 = clk_get(NULL, "pll2");
- if (IS_ERR(pll2)) {
- printk(KERN_ERR "%s: failed to get pll2\n", __func__);
- return PTR_ERR(pll2);
- }
-
- axi_a_clk = clk_get(NULL, "axi_a_clk");
- if (IS_ERR(axi_a_clk)) {
- printk(KERN_ERR "%s: failed to get axi_a_clk\n",
- __func__);
- return PTR_ERR(axi_a_clk);
- }
-
- axi_b_clk = clk_get(NULL, "axi_b_clk");
- if (IS_ERR(axi_b_clk)) {
- printk(KERN_ERR "%s: failed to get axi_b_clk\n",
- __func__);
- return PTR_ERR(axi_b_clk);
- }
-
- emi_core_clk = clk_get(NULL, "emi_core_clk");
- if (IS_ERR(emi_core_clk)) {
- printk(KERN_ERR "%s: failed to get emi_core_clk\n",
- __func__);
- return PTR_ERR(emi_core_clk);
- }
-
- nfc_clk = clk_get(NULL, "nfc_clk");
- if (IS_ERR(nfc_clk)) {
- printk(KERN_ERR "%s: failed to get nfc_clk\n",
- __func__);
- return PTR_ERR(nfc_clk);
- }
-
- ahb_clk = clk_get(NULL, "ahb_clk");
- if (IS_ERR(ahb_clk)) {
- printk(KERN_ERR "%s: failed to get ahb_clk\n",
- __func__);
- return PTR_ERR(ahb_clk);
- }
-
- vpu_core_clk = clk_get(NULL, "vpu_core_clk");
- if (IS_ERR(vpu_core_clk)) {
- printk(KERN_ERR "%s: failed to get vpu_core_clk\n",
- __func__);
- return PTR_ERR(vpu_core_clk);
- }
-
- arm_axi_clk = clk_get(NULL, "arm_axi_clk");
- if (IS_ERR(arm_axi_clk)) {
- printk(KERN_ERR "%s: failed to get arm_axi_clk\n",
- __func__);
- return PTR_ERR(arm_axi_clk);
- }
-
- ddr_clk = clk_get(NULL, "ddr_clk");
- if (IS_ERR(ddr_clk)) {
- printk(KERN_ERR "%s: failed to get ddr_clk\n",
- __func__);
- return PTR_ERR(ddr_clk);
- }
-
- ipu_clk = clk_get(NULL, "ipu_clk");
- if (IS_ERR(ipu_clk)) {
- printk(KERN_ERR "%s: failed to get ipu_clk\n",
- __func__);
- return PTR_ERR(ipu_clk);
- }
-
- vpu_clk = clk_get(NULL, "vpu_clk");
- if (IS_ERR(vpu_clk)) {
- printk(KERN_ERR "%s: failed to get vpu_clk\n",
- __func__);
- return PTR_ERR(vpu_clk);
- }
-
- periph_apm_clk = clk_get(NULL, "periph_apm_clk");
- if (IS_ERR(periph_apm_clk)) {
- printk(KERN_ERR "%s: failed to get periph_apm_clk\n",
- __func__);
- return PTR_ERR(periph_apm_clk);
- }
-
- lp_apm = clk_get(NULL, "lp_apm");
- if (IS_ERR(lp_apm)) {
- printk(KERN_ERR "%s: failed to get lp_apm\n", __func__);
- return PTR_ERR(lp_apm);
- }
-
- osc = clk_get(NULL, "osc");
- if (IS_ERR(osc)) {
- printk(KERN_ERR "%s: failed to get osc\n", __func__);
- return PTR_ERR(osc);
- }
- }
-
gp_regulator = regulator_get(NULL, gp_reg_id);
if (IS_ERR(gp_regulator)) {
clk_put(cpu_clk);
@@ -453,13 +221,6 @@ static int __init mxc_cpufreq_driver_init(struct cpufreq_policy *policy)
return PTR_ERR(gp_regulator);
}
- lp_regulator = regulator_get(NULL, lp_reg_id);
- if (IS_ERR(lp_regulator)) {
- clk_put(ahb_clk);
- printk(KERN_ERR "%s: failed to get lp regulator\n", __func__);
- return PTR_ERR(lp_regulator);
- }
-
/* Set the current working point. */
cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
@@ -478,15 +239,6 @@ static int __init mxc_cpufreq_driver_init(struct cpufreq_policy *policy)
cpu_freq_khz_max = cpu_wp_tbl[i].cpu_rate / 1000;
}
- imx_freq_table[i].index = i + 1;
- imx_freq_table[i].frequency = cpu_wp_tbl[i].cpu_rate / 1000;
-
- if ((cpu_wp_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min)
- cpu_freq_khz_min = cpu_wp_tbl[i].cpu_rate / 1000;
-
- if ((cpu_wp_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max)
- cpu_freq_khz_max = cpu_wp_tbl[i].cpu_rate / 1000;
-
imx_freq_table[i].index = 0;
imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
@@ -504,35 +256,13 @@ static int __init mxc_cpufreq_driver_init(struct cpufreq_policy *policy)
ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table);
if (ret < 0) {
clk_put(cpu_clk);
- if (axi_c_clk_support != 0) {
- clk_put(main_bus_clk);
- clk_put(pll2);
- clk_put(axi_a_clk);
- clk_put(axi_b_clk);
- clk_put(axi_c_clk);
- clk_put(emi_core_clk);
- clk_put(nfc_clk);
- clk_put(ahb_clk);
- clk_put(vpu_core_clk);
- clk_put(arm_axi_clk);
- clk_put(ddr_clk);
- clk_put(ipu_clk);
- clk_put(vpu_clk);
- clk_put(periph_apm_clk);
- clk_put(lp_apm);
- clk_put(osc);
- }
-
regulator_put(gp_regulator);
- regulator_put(lp_regulator);
printk(KERN_ERR "%s: failed to register i.MXC CPUfreq\n",
__func__);
return ret;
}
cpufreq_frequency_table_get_attr(imx_freq_table, policy->cpu);
- low_bus_freq_mode = 0;
- high_bus_freq_mode = 0;
return 0;
}
@@ -548,25 +278,7 @@ static int mxc_cpufreq_driver_exit(struct cpufreq_policy *policy)
set_high_bus_freq();
clk_put(cpu_clk);
- if (axi_c_clk_support != 0) {
- clk_put(main_bus_clk);
- clk_put(pll2);
- clk_put(axi_a_clk);
- clk_put(axi_b_clk);
- clk_put(axi_c_clk);
- clk_put(emi_core_clk);
- clk_put(nfc_clk);
- clk_put(ahb_clk);
- clk_put(vpu_core_clk);
- clk_put(arm_axi_clk);
- clk_put(ddr_clk);
- clk_put(ipu_clk);
- clk_put(periph_apm_clk);
- clk_put(lp_apm);
- clk_put(osc);
- }
regulator_put(gp_regulator);
- regulator_put(lp_regulator);
return 0;
}
diff --git a/arch/arm/plat-mxc/dvfs_core.c b/arch/arm/plat-mxc/dvfs_core.c
index d246324..52b5db6 100644
--- a/arch/arm/plat-mxc/dvfs_core.c
+++ b/arch/arm/plat-mxc/dvfs_core.c
@@ -40,6 +40,7 @@
#include <linux/regulator/consumer.h>
#include <linux/input.h>
#include <linux/platform_device.h>
+#include <linux/cpufreq.h>
#define MXC_DVFSTHRS_UPTHR_MASK 0x0FC00000
#define MXC_DVFSTHRS_UPTHR_OFFSET 22
@@ -95,6 +96,7 @@ static struct cpu_wp *cpu_wp_tbl;
int dvfs_core_resume;
int curr_wp;
int dvfs_core_is_active;
+int cpufreq_trig_needed;
/*
* Clock structures
@@ -119,8 +121,43 @@ enum {
*/
#define DVFS_LTBRSR (2 << MXC_DVFSCNTR_LTBRSR_OFFSET)
+extern int low_bus_freq_mode;
+extern int high_bus_freq_mode;
+extern int set_low_bus_freq(void);
+extern int set_high_bus_freq(void);
+extern int low_freq_bus_used(void);
+
DEFINE_SPINLOCK(mxc_dvfs_core_lock);
+void dvfs_core_set_bus_freq(void)
+{
+ u32 reg;
+ int low_freq_bus_ready = 0;
+
+ /* Mask DVFS irq */
+ reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ /* FSVAIM=1 */
+ reg |= MXC_DVFSCNTR_FSVAIM;
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+
+ low_freq_bus_ready = low_freq_bus_used();
+
+ if ((curr_wp == dvfs_data->num_wp - 1) && (!low_bus_freq_mode)
+ && (low_freq_bus_ready))
+ set_low_bus_freq();
+ else if ((curr_wp == dvfs_data->num_wp - 1) && (low_bus_freq_mode)
+ && (!low_freq_bus_ready))
+ set_high_bus_freq();
+
+ /* Enable DVFS interrupt */
+ /* FSVAIM=0 */
+ reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
+ /* LBFL=1 */
+ reg = (reg & ~MXC_DVFSCNTR_LBFL);
+ reg |= MXC_DVFSCNTR_LBFL;
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+}
+
static void dvfs_load_config(void)
{
u32 reg;
@@ -137,6 +174,64 @@ static void dvfs_load_config(void)
__raw_writel(reg, dvfs_data->dvfs_coun_reg_addr);
}
+static int set_cpu_freq(int wp)
+{
+ int ret = 0;
+ int org_cpu_rate;
+ unsigned long rate = 0;
+ int gp_volt = 0;
+ u32 reg;
+
+ org_cpu_rate = clk_get_rate(cpu_clk);
+ rate = cpu_wp_tbl[wp].cpu_rate;
+
+ if (org_cpu_rate == rate)
+ return ret;
+
+ gp_volt = cpu_wp_tbl[wp].cpu_voltage;
+
+ if (gp_volt == 0)
+ return ret;
+
+ /*Set the voltage for the GP domain. */
+ if (rate > org_cpu_rate) {
+ ret = regulator_set_voltage(core_regulator, gp_volt, gp_volt);
+ if (ret < 0) {
+ printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n");
+ return ret;
+ }
+ udelay(dvfs_data->delay_time);
+ }
+
+ ret = clk_set_rate(cpu_clk, rate);
+ if (ret != 0) {
+ printk(KERN_DEBUG "cannot set CPU clock rate\n");
+ return ret;
+ }
+
+ /* START the GPC main control FSM */
+ /* set VINC */
+ reg = __raw_readl(dvfs_data->gpc_vcr_reg_addr);
+ reg &=
+ ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK |
+ MXC_GPCVCR_VCNT_MASK);
+ reg |=
+ (1 << MXC_GPCVCR_VCNTU_OFFSET) |
+ (100 << MXC_GPCVCR_VCNT_OFFSET);
+ __raw_writel(reg, dvfs_data->gpc_vcr_reg_addr);
+
+ if (rate < org_cpu_rate) {
+ ret = regulator_set_voltage(core_regulator, gp_volt, gp_volt);
+ if (ret < 0) {
+ printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n");
+ return ret;
+ }
+ udelay(dvfs_data->delay_time);
+ }
+
+ return ret;
+}
+
static int start_dvfs(void)
{
u32 reg;
@@ -236,10 +331,9 @@ static void dvfs_core_workqueue_handler(struct work_struct *work)
u32 fsvai;
u32 reg;
u32 curr_cpu;
- unsigned long rate = 0;
int ret = 0;
- int uvol;
int maxf = 0, minf = 0;
+ int low_freq_bus_ready = 0;
/* Check DVFS frequency adjustment interrupt status */
reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
@@ -267,37 +361,8 @@ static void dvfs_core_workqueue_handler(struct work_struct *work)
goto END;
}
- rate = cpu_wp_tbl[curr_wp].cpu_rate;
- uvol = cpu_wp_tbl[curr_wp].cpu_voltage;
if (curr_wp == dvfs_data->num_wp - 1)
minf = 1;
-
- ret = clk_set_rate(cpu_clk, rate);
- if (ret != 0) {
- printk(KERN_DEBUG
- "cannot set CPU clock rate\n");
- goto END;
- }
-
- /* START the GPC main control FSM */
- /* set VINC */
- reg = __raw_readl(dvfs_data->gpc_vcr_reg_addr);
- reg &=
- ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK |
- MXC_GPCVCR_VCNT_MASK);
- reg |=
- (1 << MXC_GPCVCR_VCNTU_OFFSET) |
- (100 << MXC_GPCVCR_VCNT_OFFSET);
- __raw_writel(reg, dvfs_data->gpc_vcr_reg_addr);
-
- /* Set the voltage for the GP domain. */
- ret = regulator_set_voltage(core_regulator, uvol, uvol);
- if (ret < 0) {
- printk(KERN_DEBUG
- "COULD NOT SET CORE VOLTAGE!!!!!\n");
- goto END;
- }
- udelay(dvfs_data->delay_time);
}
} else {
if (curr_cpu == cpu_wp_tbl[0].cpu_rate) {
@@ -306,37 +371,34 @@ static void dvfs_core_workqueue_handler(struct work_struct *work)
} else {
/* freq up */
curr_wp = 0;
- rate = cpu_wp_tbl[curr_wp].cpu_rate;
- /* START the GPC main control FSM */
- /* set VINC */
- reg = __raw_readl(dvfs_data->gpc_vcr_reg_addr);
- reg &=
- ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK |
- MXC_GPCVCR_VCNT_MASK);
- reg |=
- (1 << MXC_GPCVCR_VCNTU_OFFSET) |
- (100 << MXC_GPCVCR_VCNT_OFFSET);
- __raw_writel(reg, dvfs_data->gpc_vcr_reg_addr);
-
- ret = regulator_set_voltage(core_regulator,
- cpu_wp_tbl[curr_wp].cpu_voltage,
- cpu_wp_tbl[curr_wp].cpu_voltage);
- if (ret < 0) {
- printk(KERN_DEBUG
- "COULD NOT SET CORE VOLTAGE!!!!\n");
- goto END;
- }
- udelay(dvfs_data->delay_time);
-
- ret =
- clk_set_rate(cpu_clk, cpu_wp_tbl[curr_wp].cpu_rate);
- if (ret != 0)
- printk(KERN_DEBUG
- "cannot set CPU clock rate\n");
maxf = 1;
}
}
+ low_freq_bus_ready = low_freq_bus_used();
+ if ((curr_wp == dvfs_data->num_wp - 1) && (!low_bus_freq_mode)
+ && (low_freq_bus_ready)) {
+ set_low_bus_freq();
+ ret = set_cpu_freq(curr_wp);
+ } else {
+ if (!high_bus_freq_mode)
+ set_high_bus_freq();
+
+ ret = set_cpu_freq(curr_wp);
+
+ if (low_bus_freq_mode) {
+ if (ret == 0)
+ set_high_bus_freq();
+ }
+ }
+
+#if defined(CONFIG_CPU_FREQ)
+ if (cpufreq_trig_needed == 1) {
+ cpufreq_trig_needed = 0;
+ cpufreq_update_policy(0);
+ }
+#endif
+
END: /* Set MAXF, MINF */
reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
reg = (reg & ~(MXC_DVFSCNTR_MAXF_MASK | MXC_DVFSCNTR_MINF_MASK));
@@ -377,11 +439,10 @@ static void stop_dvfs(void)
curr_wp = 0;
curr_cpu = clk_get_rate(cpu_clk);
if (curr_cpu != cpu_wp_tbl[curr_wp].cpu_rate) {
- if (regulator_set_voltage(core_regulator,
- cpu_wp_tbl[curr_wp].cpu_voltage,
- cpu_wp_tbl[curr_wp].cpu_voltage) == 0)
- clk_set_rate(cpu_clk,
- cpu_wp_tbl[curr_wp].cpu_rate);
+ if (!high_bus_freq_mode)
+ set_high_bus_freq();
+
+ set_cpu_freq(curr_wp);
}
clk_disable(dvfs_clk);
@@ -496,6 +557,7 @@ static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev)
cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
curr_wp = 0;
dvfs_core_resume = 0;
+ cpufreq_trig_needed = 0;
return err;
--
1.6.0.4
More information about the kernel-team
mailing list