summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gong <b38343@freescale.com>2013-10-23 17:42:55 +0800
committerRichard Liu <r66033@freescale.com>2013-10-23 18:00:26 +0800
commitd3d6949649c522ae692287de2b12c744676076aa (patch)
tree1119e6c86796f975d1700114363ff5735179245a
parent5be7e0e0b0f4f1039ecf07aeef7346fe2285e053 (diff)
ENGR00278452 PU: fix system hang if run Audio loop test
cpufreq and pu power management will oprate the same register, it looks should keep them operating in order not concurrent. Then use the cpufreq mutex in xPU driver to make sure. Another code bug is in pu power management which base regulator framework, we set the reister directly not regulator, then there is the chance set_volatage will miss the chance if this time voltage setting as the last time setting before PU disable, but we have to do this, so add regulator_sync_voltage to force sync the voltage setting. The drawback is setting twice... Note: This patch is temporary and supposed to be replaced it once we find the root cause. Signed-off-by: Robin Gong <b38343@freescale.com> Acked-by: Jason Liu
-rwxr-xr-xarch/arm/plat-mxc/cpufreq.c16
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c5
-rw-r--r--drivers/mxc/vpu/mxc_vpu.c9
3 files changed, 29 insertions, 1 deletions
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
index bf34bf79ceea..2d26971a01ed 100755
--- a/arch/arm/plat-mxc/cpufreq.c
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -47,7 +47,7 @@ static u32 pre_suspend_rate;
int cpufreq_suspended;
#endif
static bool cpufreq_suspend;
-static struct mutex set_cpufreq_lock;
+struct mutex set_cpufreq_lock;
extern struct regulator *cpu_regulator;
extern struct regulator *soc_regulator;
@@ -108,6 +108,13 @@ int set_cpu_freq(int freq)
"COULD NOT SET PU VOLTAGE!!!!\n");
goto err2;
}
+ /*
+ * Force sync setting PU since regulator mabye maintain
+ * the old volatage setting before disable PU, then will
+ * miss this time setting if the two setting is same.
+ * So do force sync again here.
+ */
+ regulator_sync_voltage(pu_regulator);
}
ret = regulator_set_voltage(cpu_regulator, gp_volt,
gp_volt);
@@ -148,6 +155,13 @@ int set_cpu_freq(int freq)
"COULD NOT SET PU VOLTAGE!!!!\n");
goto err7;
}
+ /*
+ * Force sync setting PU since regulator mabye maintain
+ * the old volatage setting before disable PU, then will
+ * miss this time setting if the two setting is same.
+ * So do force sync again here.
+ */
+ regulator_sync_voltage(pu_regulator);
}
/* Check if the bus freq can be decreased.*/
bus_freq_update(cpu_clk, false);
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
index 58a2d5e344e8..1afd1332eae5 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
@@ -6801,6 +6801,7 @@ gckOS_GetThreadID(
**
** Nothing.
*/
+extern struct mutex set_cpufreq_lock;
gceSTATUS
gckOS_SetGPUPower(
IN gckOS Os,
@@ -6843,8 +6844,10 @@ gckOS_SetGPUPower(
if((Power == gcvTRUE) && (oldPowerState == gcvFALSE))
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+ mutex_lock(&set_cpufreq_lock);
if(!IS_ERR(Os->device->gpu_regulator))
regulator_enable(Os->device->gpu_regulator);
+ mutex_unlock(&set_cpufreq_lock);
#else
imx_gpc_power_up_pu(true);
#endif
@@ -6960,8 +6963,10 @@ gckOS_SetGPUPower(
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+ mutex_lock(&set_cpufreq_lock);
if(!IS_ERR(Os->device->gpu_regulator))
regulator_disable(Os->device->gpu_regulator);
+ mutex_unlock(&set_cpufreq_lock);
#else
imx_gpc_power_up_pu(false);
#endif
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c
index 8a219db2e4a5..03f2be8c8b67 100644
--- a/drivers/mxc/vpu/mxc_vpu.c
+++ b/drivers/mxc/vpu/mxc_vpu.c
@@ -113,6 +113,7 @@ static int vpu_jpu_irq;
static unsigned int regBk[64];
static struct regulator *vpu_regulator;
static unsigned int pc_before_suspend;
+extern struct mutex set_cpufreq_lock;
#define READ_REG(x) __raw_readl(vpu_base + x)
#define WRITE_REG(val, x) __raw_writel(val, vpu_base + x)
@@ -252,8 +253,10 @@ static int vpu_open(struct inode *inode, struct file *filp)
mutex_lock(&vpu_data.lock);
if (open_count++ == 0) {
+ mutex_lock(&set_cpufreq_lock);
if (!IS_ERR(vpu_regulator))
regulator_enable(vpu_regulator);
+ mutex_unlock(&set_cpufreq_lock);
#ifdef CONFIG_SOC_IMX6Q
clk_enable(vpu_clk);
@@ -634,8 +637,10 @@ static int vpu_release(struct inode *inode, struct file *filp)
for (i = 0; i < vpu_clk_usercount; i++)
clk_disable(vpu_clk);
+ mutex_lock(&set_cpufreq_lock);
if (!IS_ERR(vpu_regulator))
regulator_disable(vpu_regulator);
+ mutex_unlock(&set_cpufreq_lock);
}
mutex_unlock(&vpu_data.lock);
@@ -924,8 +929,10 @@ static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
/* If VPU is working before suspend, disable
* regulator to make usecount right. */
+ mutex_lock(&set_cpufreq_lock);
if (!IS_ERR(vpu_regulator))
regulator_disable(vpu_regulator);
+ mutex_unlock(&set_cpufreq_lock);
}
mutex_unlock(&vpu_data.lock);
@@ -952,8 +959,10 @@ static int vpu_resume(struct platform_device *pdev)
/* If VPU is working before suspend, enable
* regulator to make usecount right. */
+ mutex_lock(&set_cpufreq_lock);
if (!IS_ERR(vpu_regulator))
regulator_enable(vpu_regulator);
+ mutex_unlock(&set_cpufreq_lock);
if (vpu_plat->pg)
vpu_plat->pg(0);