summaryrefslogtreecommitdiff
path: root/arch/arm/plat-mxc/dvfs_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-mxc/dvfs_core.c')
-rwxr-xr-xarch/arm/plat-mxc/dvfs_core.c72
1 files changed, 58 insertions, 14 deletions
diff --git a/arch/arm/plat-mxc/dvfs_core.c b/arch/arm/plat-mxc/dvfs_core.c
index b5cfba1a5047..bdf91df941f5 100755
--- a/arch/arm/plat-mxc/dvfs_core.c
+++ b/arch/arm/plat-mxc/dvfs_core.c
@@ -47,6 +47,7 @@
#include <mach/hardware.h>
#include <mach/mxc_dvfs.h>
+#include <mach/clock.h>
#define MXC_DVFSTHRS_UPTHR_MASK 0x0FC00000
#define MXC_DVFSTHRS_UPTHR_OFFSET 22
@@ -84,7 +85,7 @@
#define CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER 0x4
#define CCM_CDHIPR_ARM_PODF_BUSY 0x10000
-int cpufreq_trig_needed;
+static int cpufreq_trig_needed;
int dvfs_core_is_active;
static struct mxc_dvfs_platform_data *dvfs_data;
static struct device *dvfs_dev;
@@ -114,6 +115,9 @@ static struct delayed_work dvfs_core_handler;
*/
static struct clk *pll1_sw_clk;
static struct clk *cpu_clk;
+#ifdef CONFIG_ARCH_MX5
+static struct clk *gpu_clk;
+#endif
static struct clk *dvfs_clk;
static int cpu_op_nr;
@@ -190,6 +194,7 @@ static int mx5_set_cpu_freq(int op)
int podf;
int vinc = 0;
int ret = 0;
+ int retry_count = 0;
int org_cpu_rate;
unsigned long rate = 0;
int gp_volt = 0;
@@ -258,6 +263,7 @@ static int mx5_set_cpu_freq(int op)
udelay(10);
spin_unlock_irqrestore(&mxc_dvfs_core_lock, flags);
+ clk_set_rate(cpu_clk, rate);
if (rate < org_cpu_rate) {
ret = regulator_set_voltage(cpu_regulator, gp_volt,
gp_volt);
@@ -272,11 +278,19 @@ static int mx5_set_cpu_freq(int op)
reg = __raw_readl(ccm_base + dvfs_data->ccm_cdcr_offset);
reg &= ~(CCM_CDCR_SW_DVFS_EN);
reg |= en_sw_dvfs;
- clk_set_rate(cpu_clk, rate);
} else {
podf = cpu_op_tbl[op].cpu_podf;
gp_volt = cpu_op_tbl[op].cpu_voltage;
+ /* Get ARM_PODF */
+ reg = __raw_readl(ccm_base + dvfs_data->ccm_cacrr_offset);
+ arm_podf = reg & 0x07;
+ if (podf == arm_podf) {
+ printk(KERN_DEBUG
+ "No need to change freq and voltage!!!!\n");
+ return 0;
+ }
+
/* Change arm_podf only */
/* set ARM_FREQ_SHIFT_DIVIDER */
reg = __raw_readl(ccm_base + dvfs_data->ccm_cdcr_offset);
@@ -291,14 +305,6 @@ static int mx5_set_cpu_freq(int op)
reg |= CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER;
__raw_writel(reg, ccm_base + dvfs_data->ccm_cdcr_offset);
- /* Get ARM_PODF */
- reg = __raw_readl(ccm_base + dvfs_data->ccm_cacrr_offset);
- arm_podf = reg & 0x07;
- if (podf == arm_podf) {
- printk(KERN_DEBUG
- "No need to change freq and voltage!!!!\n");
- return 0;
- }
/* Check if FSVAI indicate freq up */
if (podf < arm_podf) {
ret = regulator_set_voltage(cpu_regulator, gp_volt,
@@ -356,7 +362,10 @@ static int mx5_set_cpu_freq(int op)
/* Wait for arm podf Enable */
while ((__raw_readl(gpc_base + dvfs_data->gpc_cntr_offset) &
MXC_GPCCNTR_STRT) == MXC_GPCCNTR_STRT) {
- printk(KERN_DEBUG "Waiting arm_podf enabled!\n");
+ if (retry_count)
+ printk(KERN_DEBUG "Waiting arm_podf enabled!\n");
+
+ retry_count++;
udelay(10);
}
spin_unlock_irqrestore(&mxc_dvfs_core_lock, flags);
@@ -586,7 +595,12 @@ static void dvfs_core_work_handler(struct work_struct *work)
int ret = 0;
int low_freq_bus_ready = 0;
int bus_incr = 0, cpu_dcr = 0;
+#ifdef CONFIG_ARCH_MX5
+ int disable_dvfs_irq = 0;
+#endif
+#ifdef CONFIG_CPU_FREQ
int cpu;
+#endif
low_freq_bus_ready = low_freq_bus_used();
@@ -599,6 +613,31 @@ static void dvfs_core_work_handler(struct work_struct *work)
goto END;
}
curr_cpu = clk_get_rate(cpu_clk);
+
+#ifdef CONFIG_ARCH_MX5
+ if (clk_get_usecount(gpu_clk)) {
+ maxf = 1;
+ if (curr_cpu != cpu_op_tbl[0].cpu_rate) {
+ curr_op = 0;
+ minf = 0;
+ dvfs_load_config(0);
+ if (!high_bus_freq_mode)
+ set_high_bus_freq(1);
+ set_cpu_freq(curr_op);
+ }
+ /* If we enable DVFS's irq, the irq will keep coming,
+ * and will consume about 3-40% cpu usage, we disable
+ * dvfs 's irq here, and let it check the status every
+ * 100 msecs. If gpu clk have count to 0, it will
+ * enable dvfs's irq let it do what it want.*/
+ schedule_delayed_work(&dvfs_core_handler,
+ msecs_to_jiffies(100));
+ disable_dvfs_irq = 1;
+ goto END;
+ } else
+ disable_dvfs_irq = 0;
+#endif
+
/* If FSVAI indicate freq down,
check arm-clk is not in lowest frequency*/
if (fsvai == FSVAI_FREQ_DECREASE) {
@@ -699,8 +738,11 @@ END:
/* Enable DVFS interrupt */
/* FSVAIM=0 */
- reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
- reg |= FSVAI_FREQ_NOCHANGE;
+#ifdef CONFIG_ARCH_MX5
+ if (!disable_dvfs_irq)
+#endif
+ reg = ((reg & ~MXC_DVFSCNTR_FSVAIM) | FSVAI_FREQ_NOCHANGE);
+
/* LBFL=1 */
reg = (reg & ~MXC_DVFSCNTR_LBFL);
reg |= MXC_DVFSCNTR_LBFL;
@@ -723,7 +765,7 @@ void stop_dvfs(void)
u32 curr_cpu;
int cpu;
#ifndef CONFIG_SMP
- unsigned long old_loops_per_jiffy;
+ u32 old_loops_per_jiffy;
#endif
if (dvfs_core_is_active) {
@@ -767,6 +809,8 @@ void stop_dvfs(void)
for (cpu = 0; cpu < num_online_cpus(); cpu++)
cpufreq_get(cpu);
#endif
+ if (cpufreq_trig_needed == 1)
+ cpufreq_trig_needed = 0;
}
spin_lock_irqsave(&mxc_dvfs_core_lock, flags);