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;
spin_unlock_irqrestore(&freq_lock, flags);
}
-
high_bus_freq_mode = 0;
mutex_unlock(&bus_freq_mutex);
}
{
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;
clk_disable(pll3);
}
-
- mutex_unlock(&bus_freq_mutex);
return 0;
}
/* 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))
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);
+ }
}
}
}
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. */
/* Enable the PLL output now*/
reg = __raw_readl(pllbase);
+ reg &= ~ANADIG_PLL_BYPASS;
reg |= ANADIG_PLL_ENABLE;
__raw_writel(reg, pllbase);
*/
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 */
/* 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);
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);
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;
__raw_writel((1 << (clk->enable_shift + 7)),
(int)clk->enable_reg + 8);
+ udelay(3);
return 0;
}
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. */
/* Enable the PLL output now*/
reg = __raw_readl(pllbase);
+ reg &= ~ANADIG_PLL_BYPASS;
reg |= ANADIG_PLL_ENABLE;
__raw_writel(reg, pllbase);
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)) {
*/
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. */
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);
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;
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)
{
#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);
}
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;