summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2012-08-10 00:35:59 +0800
committerAnson Huang <b20788@freescale.com>2012-08-11 03:37:28 +0800
commitfb253b20e536d5b1cccfcf3e0f145866cf7e832b (patch)
treea5e17513cc0bbe69547e080d0391c9c67ae4777d /arch
parent2bb33d7d7cae1602602ca93c084772017bb89e62 (diff)
ENGR00220022 [MX6]Add necessary protection to bus freq variables and function
All bus freq related variables and function calls need to be protected by mutex, or these variables may be wrong and result in triggering bus freq change by mistake, it will impact many modules function. Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mx6/bus_freq.c85
-rwxr-xr-xarch/arm/plat-mxc/clock.c68
-rwxr-xr-xarch/arm/plat-mxc/cpufreq.c5
-rwxr-xr-xarch/arm/plat-mxc/dvfs_core.c16
4 files changed, 90 insertions, 84 deletions
diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c
index 12dea1474d9a..51e1d3b14e62 100644
--- a/arch/arm/mach-mx6/bus_freq.c
+++ b/arch/arm/mach-mx6/bus_freq.c
@@ -81,7 +81,7 @@ extern int update_ddr_freq(int ddr_rate);
extern int chip_rev;
extern bool arm_mem_clked_in_wait;
-struct mutex bus_freq_mutex;
+DEFINE_MUTEX(bus_freq_mutex);
struct timeval start_time;
struct timeval end_time;
@@ -113,21 +113,6 @@ static void reduce_bus_freq_handler(struct work_struct *work)
if (audio_bus_freq_mode && lp_audio_freq)
return;
- while (!mutex_trylock(&bus_freq_mutex))
- msleep(1);
-
- /* PLL3 is used in the DDR freq change process, enable it. */
-
- if (low_bus_freq_mode || !low_freq_bus_used()) {
- mutex_unlock(&bus_freq_mutex);
- return;
- }
-
- if (audio_bus_freq_mode && lp_audio_freq) {
- mutex_unlock(&bus_freq_mutex);
- return;
- }
-
if (!cpu_is_mx6sl()) {
clk_enable(pll3);
if (lp_audio_freq) {
@@ -188,8 +173,6 @@ static void reduce_bus_freq_handler(struct work_struct *work)
high_bus_freq_mode = 0;
med_bus_freq_mode = 0;
-
- mutex_unlock(&bus_freq_mutex);
}
/* Set the DDR, AHB to 24MHz.
* This mode will be activated only when none of the modules that
@@ -235,15 +218,10 @@ int set_high_bus_freq(int high_bus_freq)
if (cpu_is_mx6dl() && med_bus_freq_mode)
return 0;
- while (!mutex_trylock(&bus_freq_mutex))
- msleep(1);
-
if ((high_bus_freq_mode && (high_bus_freq || lp_high_freq)) ||
(med_bus_freq_mode && !high_bus_freq && lp_med_freq &&
- !lp_high_freq)) {
- mutex_unlock(&bus_freq_mutex);
+ !lp_high_freq))
return 0;
- }
if (cpu_is_mx6sl()) {
/* Set the voltage of VDDSOC to 1.2V as in normal mode. */
@@ -315,8 +293,6 @@ int set_high_bus_freq(int high_bus_freq)
if (cpu_is_mx6sl())
arm_mem_clked_in_wait = false;
- mutex_unlock(&bus_freq_mutex);
-
return 0;
}
@@ -341,6 +317,61 @@ int low_freq_bus_used(void)
return 0;
}
+void bus_freq_update(struct clk *clk, bool flag)
+{
+ mutex_lock(&bus_freq_mutex);
+ if (flag) {
+ /* Update count */
+ if (clk->flags & AHB_HIGH_SET_POINT)
+ lp_high_freq++;
+ else if (clk->flags & AHB_MED_SET_POINT)
+ lp_med_freq++;
+ else if (clk->flags & AHB_AUDIO_SET_POINT)
+ lp_audio_freq++;
+ /* Update bus freq */
+ if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
+ && (clk_get_usecount(clk) == 0)) {
+ if (!(clk->flags &
+ (AHB_HIGH_SET_POINT | AHB_MED_SET_POINT))) {
+ if (low_freq_bus_used()) {
+ if ((clk->flags & AHB_AUDIO_SET_POINT) & !audio_bus_freq_mode)
+ set_low_bus_freq();
+ else if (!low_bus_freq_mode)
+ set_low_bus_freq();
+ }
+ } else {
+ if ((clk->flags & AHB_MED_SET_POINT)
+ && !med_bus_freq_mode)
+ /* Set to Medium setpoint */
+ set_high_bus_freq(0);
+ else if ((clk->flags & AHB_HIGH_SET_POINT)
+ && !high_bus_freq_mode)
+ /* Currently at low or medium set point,
+ * need to set to high setpoint
+ */
+ set_high_bus_freq(1);
+ }
+ }
+ } else {
+ /* Update count */
+ if (clk->flags & AHB_HIGH_SET_POINT)
+ lp_high_freq--;
+ else if (clk->flags & AHB_MED_SET_POINT)
+ lp_med_freq--;
+ else if (clk->flags & AHB_AUDIO_SET_POINT)
+ lp_audio_freq--;
+ /* Update bus freq */
+ if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
+ && (clk_get_usecount(clk) == 0)) {
+ if (low_freq_bus_used() && !low_bus_freq_mode)
+ set_low_bus_freq();
+ else
+ /* Set to either high or medium setpoint. */
+ set_high_bus_freq(0);
+ }
+ }
+ mutex_unlock(&bus_freq_mutex);
+}
void setup_pll(void)
{
}
@@ -521,8 +552,6 @@ static int __devinit busfreq_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&low_bus_freq_handler, reduce_bus_freq_handler);
- mutex_init(&bus_freq_mutex);
-
if (!cpu_is_mx6sl())
init_mmdc_settings();
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 43d33376b52d..ee4ea63d9fdc 100755
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -45,16 +45,7 @@
#include <mach/hardware.h>
extern int dvfs_core_is_active;
-extern int lp_high_freq;
-extern int lp_med_freq;
-extern int lp_audio_freq;
-extern int audio_bus_freq_mode;
-extern int low_bus_freq_mode;
-extern int high_bus_freq_mode;
-extern int med_bus_freq_mode;
-extern int set_high_bus_freq(int high_freq);
-extern int set_low_bus_freq(void);
-extern int low_freq_bus_used(void);
+extern void bus_freq_update(struct clk *clk, bool flag);
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
@@ -113,36 +104,12 @@ int clk_enable(struct clk *clk)
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- if (clk->flags & AHB_HIGH_SET_POINT)
- lp_high_freq++;
- else if (clk->flags & AHB_MED_SET_POINT)
- lp_med_freq++;
- else if (clk->flags & AHB_AUDIO_SET_POINT)
- lp_audio_freq++;
-
- if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
- && (clk_get_usecount(clk) == 0)) {
- if (!(clk->flags &
- (AHB_HIGH_SET_POINT | AHB_MED_SET_POINT))) {
- if (low_freq_bus_used()) {
- if ((clk->flags & AHB_AUDIO_SET_POINT) & !audio_bus_freq_mode)
- set_low_bus_freq();
- else if (!low_bus_freq_mode)
- set_low_bus_freq();
- }
- } else {
- if ((clk->flags & AHB_MED_SET_POINT)
- && !med_bus_freq_mode)
- /* Set to Medium setpoint */
- set_high_bus_freq(0);
- else if ((clk->flags & AHB_HIGH_SET_POINT)
- && !high_bus_freq_mode)
- /* Currently at low or medium set point,
- * need to set to high setpoint
- */
- set_high_bus_freq(1);
- }
- }
+ if ((clk->flags & AHB_HIGH_SET_POINT) ||
+ (clk->flags & AHB_MED_SET_POINT) ||
+ (clk->flags & AHB_AUDIO_SET_POINT) ||
+ (clk->flags & CPU_FREQ_TRIG_UPDATE))
+ bus_freq_update(clk, true);
+
mutex_lock(&clocks_mutex);
ret = __clk_enable(clk);
mutex_unlock(&clocks_mutex);
@@ -168,24 +135,15 @@ void clk_disable(struct clk *clk)
if (clk == NULL || IS_ERR(clk))
return;
- if (clk->flags & AHB_HIGH_SET_POINT)
- lp_high_freq--;
- else if (clk->flags & AHB_MED_SET_POINT)
- lp_med_freq--;
- else if (clk->flags & AHB_AUDIO_SET_POINT)
- lp_audio_freq--;
-
mutex_lock(&clocks_mutex);
__clk_disable(clk);
mutex_unlock(&clocks_mutex);
- if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
- && (clk_get_usecount(clk) == 0)) {
- if (low_freq_bus_used() && !low_bus_freq_mode)
- set_low_bus_freq();
- else
- /* Set to either high or medium setpoint. */
- set_high_bus_freq(0);
- }
+
+ if ((clk->flags & AHB_HIGH_SET_POINT) ||
+ (clk->flags & AHB_MED_SET_POINT) ||
+ (clk->flags & AHB_AUDIO_SET_POINT) ||
+ (clk->flags & CPU_FREQ_TRIG_UPDATE))
+ bus_freq_update(clk, false);
}
EXPORT_SYMBOL(clk_disable);
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
index 765f05e23712..935570707e6b 100755
--- a/arch/arm/plat-mxc/cpufreq.c
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -61,6 +61,7 @@ extern int high_bus_freq_mode;
extern int set_low_bus_freq(void);
extern int set_high_bus_freq(int high_bus_speed);
extern int low_freq_bus_used(void);
+extern struct mutex bus_freq_mutex;
int set_cpu_freq(int freq)
{
@@ -86,8 +87,10 @@ int set_cpu_freq(int freq)
#endif
/*Set the voltage for the GP domain. */
if (freq > org_cpu_rate) {
+ mutex_lock(&bus_freq_mutex);
if (low_bus_freq_mode || audio_bus_freq_mode)
set_high_bus_freq(0);
+ mutex_unlock(&bus_freq_mutex);
ret = regulator_set_voltage(cpu_regulator, gp_volt,
gp_volt);
if (ret < 0) {
@@ -109,9 +112,11 @@ int set_cpu_freq(int freq)
printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n");
return ret;
}
+ mutex_lock(&bus_freq_mutex);
if (low_freq_bus_used() &&
!(low_bus_freq_mode || audio_bus_freq_mode))
set_low_bus_freq();
+ mutex_unlock(&bus_freq_mutex);
}
return ret;
diff --git a/arch/arm/plat-mxc/dvfs_core.c b/arch/arm/plat-mxc/dvfs_core.c
index a31ee9a71940..9018b49511cc 100755
--- a/arch/arm/plat-mxc/dvfs_core.c
+++ b/arch/arm/plat-mxc/dvfs_core.c
@@ -154,6 +154,7 @@ extern int high_bus_freq_mode;
extern int set_low_bus_freq(void);
extern int set_high_bus_freq(int high_bus_speed);
extern int low_freq_bus_used(void);
+extern struct mutex bus_freq_mutex;
DEFINE_SPINLOCK(mxc_dvfs_core_lock);
@@ -603,8 +604,12 @@ static void dvfs_core_work_handler(struct work_struct *work)
if (fsvai == FSVAI_FREQ_DECREASE) {
if (curr_cpu <= cpu_op_tbl[cpu_op_nr - 1].cpu_rate) {
minf = 1;
- if (low_bus_freq_mode)
+ mutex_lock(&bus_freq_mutex);
+ if (low_bus_freq_mode) {
+ mutex_unlock(&bus_freq_mutex);
goto END;
+ } else
+ mutex_unlock(&bus_freq_mutex);
} else {
/* freq down */
curr_op++;
@@ -621,6 +626,7 @@ static void dvfs_core_work_handler(struct work_struct *work)
maxf = 1;
goto END;
} else {
+ mutex_lock(&bus_freq_mutex);
if (!high_bus_freq_mode &&
dvfs_config_setpoint == (cpu_op_nr + 1)) {
/* bump up LP freq first. */
@@ -633,24 +639,30 @@ static void dvfs_core_work_handler(struct work_struct *work)
minf = 0;
dvfs_load_config(0);
}
+ mutex_unlock(&bus_freq_mutex);
}
}
low_freq_bus_ready = low_freq_bus_used();
+ mutex_lock(&bus_freq_mutex);
if ((curr_op == cpu_op_nr - 1) && (!low_bus_freq_mode)
&& (low_freq_bus_ready) && !bus_incr) {
+ mutex_unlock(&bus_freq_mutex);
if (!minf)
set_cpu_freq(curr_op);
/* If dvfs_core_op is greater than cpu_op_nr, it implies
* we support LPAPM mode for this platform.
*/
if (dvfs_core_op > cpu_op_nr) {
+ mutex_lock(&bus_freq_mutex);
set_low_bus_freq();
+ mutex_unlock(&bus_freq_mutex);
dvfs_load_config(cpu_op_nr + 1);
}
} else {
if (!high_bus_freq_mode)
set_high_bus_freq(1);
+ mutex_unlock(&bus_freq_mutex);
if (!bus_incr)
ret = set_cpu_freq(curr_op);
bus_incr = 0;
@@ -722,8 +734,10 @@ void stop_dvfs(void)
+ MXC_DVFSCORE_CNTR);
curr_op = 0;
+ mutex_lock(&bus_freq_mutex);
if (!high_bus_freq_mode)
set_high_bus_freq(1);
+ mutex_unlock(&bus_freq_mutex);
curr_cpu = clk_get_rate(cpu_clk);
if (curr_cpu != cpu_op_tbl[curr_op].cpu_rate) {