diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c index bde499dd02a9c6c8e3ecd2b64962efc9e4710d04..53a65fb893f6fdd7204f4cb7d157d0e6e73f51f2 100644 --- a/arch/arm/mach-mx6/bus_freq.c +++ b/arch/arm/mach-mx6/bus_freq.c @@ -69,6 +69,7 @@ int bus_freq_scaling_is_active; int lp_high_freq; int lp_med_freq; int lp_audio_freq; +int high_cpu_freq; unsigned int ddr_low_rate; unsigned int ddr_med_rate; unsigned int ddr_normal_rate; @@ -194,7 +195,6 @@ static void reduce_bus_freq_handler(struct work_struct *work) spin_unlock_irqrestore(&freq_lock, flags); } - high_bus_freq_mode = 0; mutex_unlock(&bus_freq_mutex); } @@ -225,40 +225,34 @@ int set_high_bus_freq(int high_bus_freq) { if (bus_freq_scaling_initialized && bus_freq_scaling_is_active) cancel_delayed_work_sync(&low_bus_freq_handler); - mutex_lock(&bus_freq_mutex); - if (busfreq_suspended) { - mutex_unlock(&bus_freq_mutex); + + if (busfreq_suspended) return 0; - } - if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active) { - mutex_unlock(&bus_freq_mutex); + + if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active) return 0; - } - if (high_bus_freq_mode && high_bus_freq) { - mutex_unlock(&bus_freq_mutex); + + if (high_bus_freq_mode && high_bus_freq) return 0; - } - if (med_bus_freq_mode && !high_bus_freq) { - mutex_unlock(&bus_freq_mutex); + + /* medium bus freq is only supported for MX6DQ */ + if (cpu_is_mx6q() && med_bus_freq_mode && !high_bus_freq) return 0; - } if (cpu_is_mx6dl() && high_bus_freq) high_bus_freq = 0; - if (cpu_is_mx6dl() && med_bus_freq_mode) { - mutex_unlock(&bus_freq_mutex); + if (cpu_is_mx6dl() && med_bus_freq_mode) return 0; - } + 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()) { u32 reg; unsigned long flags; @@ -321,8 +315,6 @@ int set_high_bus_freq(int high_bus_freq) clk_disable(pll3); } - - mutex_unlock(&bus_freq_mutex); return 0; } @@ -334,11 +326,8 @@ int low_freq_bus_used(void) /* We only go the lowest setpoint if ARM is also * at the lowest setpoint. */ - if ((clk_get_rate(cpu_clk) > - cpu_op_tbl[cpu_op_nr - 1].cpu_rate) - || (cpu_op_nr == 1)) { + if (high_cpu_freq) return 0; - } if ((lp_high_freq == 0) && (lp_med_freq == 0)) @@ -350,62 +339,80 @@ int low_freq_bus_used(void) 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 */ - mutex_unlock(&bus_freq_mutex); + if (clk == cpu_clk) { + /* The CPU freq is being increased. + * check if we need to increase the bus freq + */ + high_cpu_freq = 1; + if (low_bus_freq_mode || audio_bus_freq_mode) set_high_bus_freq(0); - return; - } - 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 - */ - mutex_unlock(&bus_freq_mutex); - set_high_bus_freq(1); - return; - } + } 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 (!(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) + if (clk == cpu_clk) { + /* CPU freq is dropped, check if we can + * lower the bus freq. + */ + high_cpu_freq = 0; + + if (low_freq_bus_used() && + !(low_bus_freq_mode || audio_bus_freq_mode)) set_low_bus_freq(); - else { - /* Set to either high or medium setpoint. */ - mutex_unlock(&bus_freq_mutex); - set_high_bus_freq(0); - return; + } 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()) + set_low_bus_freq(); + else { + /* Set to either high or + * medium setpoint. + */ + set_high_bus_freq(0); + } } } } diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 8835c20ad34b06945645205420f9b565636be9c1..e0348e4f2e33c956e4dcaaaf7c8cfa34f8574c8a 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -472,7 +472,6 @@ static int _clk_pll_enable(struct clk *clk) pllbase = _get_pll_base(clk); reg = __raw_readl(pllbase); - reg &= ~ANADIG_PLL_BYPASS; reg &= ~ANADIG_PLL_POWER_DOWN; /* The 480MHz PLLs have the opposite definition for power bit. */ @@ -492,6 +491,7 @@ static int _clk_pll_enable(struct clk *clk) /* Enable the PLL output now*/ reg = __raw_readl(pllbase); + reg &= ~ANADIG_PLL_BYPASS; reg |= ANADIG_PLL_ENABLE; __raw_writel(reg, pllbase); @@ -1262,14 +1262,17 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) */ if (pll1_sw_clk.parent != &pll2_pfd_400M) { pll2_pfd_400M.enable(&pll2_pfd_400M); + pll2_pfd_400M.usecount++; arm_needs_pll2_400 = true; pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd_400M); pll1_sw_clk.parent = &pll2_pfd_400M; } } else { /* Make sure PLL1 is enabled */ - if (!pll1_enabled) + if (!pll1_enabled) { pll1_sys_main_clk.enable(&pll1_sys_main_clk); + pll1_sys_main_clk.usecount = 1; + } /* Make sure PLL1 rate is what we want */ if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) { /* If pll1_sw_clk is from pll1_sys_main_clk, switch it */ @@ -1285,6 +1288,8 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) /* Make sure pll1_sw_clk is from pll1_sys_main_clk */ pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk); pll1_sw_clk.parent = &pll1_sys_main_clk; + if (arm_needs_pll2_400) + pll2_pfd_400M.usecount--; arm_needs_pll2_400 = false; if (pll2_pfd_400M.usecount == 0) pll2_pfd_400M.disable(&pll2_pfd_400M); @@ -1323,8 +1328,10 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) while (__raw_readl(MXC_CCM_CDHIPR)) ; - if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) + if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) { pll1_sys_main_clk.disable(&pll1_sys_main_clk); + pll1_sys_main_clk.usecount = 0; + } spin_unlock_irqrestore(&clk_lock, flags); diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c index 9c79f744de991f9b49bcf4337c7363d59cfd1ebd..d93320d59dd809171d9fa92be254385944deffa0 100755 --- a/arch/arm/mach-mx6/clock_mx6sl.c +++ b/arch/arm/mach-mx6/clock_mx6sl.c @@ -67,6 +67,7 @@ static struct clk pll7_usb_host_main_clk; static struct clk usdhc3_clk; static struct clk ipg_clk; static struct clk gpt_clk[]; +static struct clk ahb_clk; static struct cpu_op *cpu_op_tbl; static int cpu_op_nr; @@ -412,6 +413,7 @@ static int _clk_pfd_enable(struct clk *clk) __raw_writel((1 << (clk->enable_shift + 7)), (int)clk->enable_reg + 8); + udelay(3); return 0; } @@ -430,7 +432,6 @@ static int _clk_pll_enable(struct clk *clk) pllbase = _get_pll_base(clk); reg = __raw_readl(pllbase); - reg &= ~ANADIG_PLL_BYPASS; reg &= ~ANADIG_PLL_POWER_DOWN; /* The 480MHz PLLs have the opposite definition for power bit. */ @@ -450,6 +451,7 @@ static int _clk_pll_enable(struct clk *clk) /* Enable the PLL output now*/ reg = __raw_readl(pllbase); + reg &= ~ANADIG_PLL_BYPASS; reg |= ANADIG_PLL_ENABLE; __raw_writel(reg, pllbase); @@ -1153,6 +1155,11 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) if (i >= cpu_op_nr) return -EINVAL; + if (clk_get_rate(&ahb_clk) == 24000000) { + printk(KERN_INFO "we should not be here!!!!! AHB is at 24MHz....cpu_rate requested = %ld\n", rate); + dump_stack(); + BUG(); + } spin_lock_irqsave(&mx6sl_clk_lock, flags); if (rate <= clk_get_rate(&pll2_pfd2_400M)) { @@ -1161,14 +1168,17 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) */ if (pll1_sw_clk.parent != &pll2_pfd2_400M) { pll2_pfd2_400M.enable(&pll2_pfd2_400M); + pll2_pfd2_400M.usecount++; arm_needs_pll2_400 = true; pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd2_400M); pll1_sw_clk.parent = &pll2_pfd2_400M; } } else { /* Make sure PLL1 is enabled */ - if (!pll1_enabled) + if (!pll1_enabled) { pll1_sys_main_clk.enable(&pll1_sys_main_clk); + pll1_sys_main_clk.usecount = 1; + } if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) { if (pll1_sw_clk.parent == &pll1_sys_main_clk) { /* Change the PLL1 rate. */ @@ -1177,15 +1187,13 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) else pll1_sw_clk.set_parent(&pll1_sw_clk, &osc_clk); } - if (cpu_op_tbl[i].cpu_podf) { - __raw_writel(cpu_op_tbl[i].cpu_podf, MXC_CCM_CACRR); - while (__raw_readl(MXC_CCM_CDHIPR)) - ; - } pll1_sys_main_clk.set_rate(&pll1_sys_main_clk, cpu_op_tbl[i].pll_rate); } pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk); pll1_sw_clk.parent = &pll1_sys_main_clk; + + if (arm_needs_pll2_400) + pll2_pfd2_400M.usecount--; arm_needs_pll2_400 = false; if (pll2_pfd2_400M.usecount == 0) pll2_pfd2_400M.disable(&pll2_pfd2_400M); @@ -1224,9 +1232,10 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) while (__raw_readl(MXC_CCM_CDHIPR)) ; - if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) + if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) { pll1_sys_main_clk.disable(&pll1_sys_main_clk); - + pll1_sys_main_clk.usecount = 0; + } spin_unlock_irqrestore(&mx6sl_clk_lock, flags); return 0; diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c index ee041507038ead93746a48a5f1338cfd642c44a5..b6c1e28e4aca46f36c74f461148e49936f6cd01e 100755 --- a/arch/arm/plat-mxc/cpufreq.c +++ b/arch/arm/plat-mxc/cpufreq.c @@ -58,13 +58,7 @@ extern struct regulator *soc_regulator; extern struct regulator *pu_regulator; extern int dvfs_core_is_active; extern struct cpu_op *(*get_cpu_op)(int *op); -extern int low_bus_freq_mode; -extern int audio_bus_freq_mode; -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; +extern void bus_freq_update(struct clk *clk, bool flag); int set_cpu_freq(int freq) { @@ -95,12 +89,9 @@ 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) { - mutex_unlock(&bus_freq_mutex); - set_high_bus_freq(0); - } else - mutex_unlock(&bus_freq_mutex); + /* Check if the bus freq needs to be increased first */ + bus_freq_update(cpu_clk, true); + if (freq == cpu_op_tbl[0].cpu_rate && !IS_ERR(soc_regulator) && !IS_ERR(pu_regulator)) { ret = regulator_set_voltage(soc_regulator, soc_volt, soc_volt); @@ -152,11 +143,8 @@ int set_cpu_freq(int freq) } soc_regulator_set = 0; } - 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); + /* Check if the bus freq can be decreased.*/ + bus_freq_update(cpu_clk, false); } return ret;