Example #1
0
static void reduce_bus_freq_handler(struct work_struct *work)
{
    unsigned long reg;

    if (low_bus_freq_mode || !low_freq_bus_used())
        return;

    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;
    }

    clk_enable(pll3);

    if (lp_audio_freq) {
        /* Need to ensure that PLL2_PFD_400M is kept ON. */
        clk_enable(pll2_400);
        update_ddr_freq(50000000);
        audio_bus_freq_mode = 1;
        low_bus_freq_mode = 0;
    } else {
        update_ddr_freq(24000000);
        if (audio_bus_freq_mode)
            clk_disable(pll2_400);
        low_bus_freq_mode = 1;
        audio_bus_freq_mode = 0;
    }

    if (med_bus_freq_mode)
        clk_disable(pll2_400);

    high_bus_freq_mode = 0;
    med_bus_freq_mode = 0;

    if (cpu_is_mx6q()) {
        /* Power gate the PU LDO. */
        org_ldo = reg = __raw_readl(ANADIG_REG_CORE);
        reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
        __raw_writel(reg, ANADIG_REG_CORE);
    }
    clk_disable(pll3);
    mutex_unlock(&bus_freq_mutex);

}
Example #2
0
static ssize_t bus_freq_scaling_enable_store(struct device *dev,
				 struct device_attribute *attr,
				 const char *buf, size_t size)
{
	if (strncmp(buf, "1", 1) == 0) {
#ifdef CONFIG_MX6_VPU_352M
		if (cpu_is_mx6q())
			/*do not enable bus freq*/
			bus_freq_scaling_is_active = 0;
		printk(KERN_WARNING "Bus frequency can't be enabled if using VPU 352M!\n");
		return size;
#else
		bus_freq_scaling_is_active = 1;
#endif
		set_high_bus_freq(0);
		/* Make sure system can enter low bus mode if it should be in
		low bus mode */
		if (low_freq_bus_used() && !low_bus_freq_mode)
			set_low_bus_freq();
	} else if (strncmp(buf, "0", 1) == 0) {
		if (bus_freq_scaling_is_active)
			set_high_bus_freq(1);
		bus_freq_scaling_is_active = 0;
	}
	return size;
}
Example #3
0
static void reduce_bus_freq_handler(struct work_struct *work)
{
	mutex_lock(&bus_freq_mutex);

	if (!low_freq_bus_used()) {
		mutex_unlock(&bus_freq_mutex);
		return;
	}
	/* If we are already in audio bus freq mode,
	  * just return if lp_audio_freq is true.
	  */
	if (audio_bus_freq_mode && lp_audio_freq) {
		mutex_unlock(&bus_freq_mutex);
		return;
	}

	/* If we dont want to transition from low bus to
	  * audio bus mode and are already in
	  *low bus mode, then return.
	  */
	if (!lp_audio_freq && low_bus_freq_mode) {
		mutex_unlock(&bus_freq_mutex);
		return;
	}
	reduce_bus_freq();

	mutex_unlock(&bus_freq_mutex);
}
Example #4
0
static void dvfs_core_work_handler(struct work_struct *work)
{
	u32 fsvai;
	u32 reg;
	u32 curr_cpu;
	int ret = 0;
	int maxf = 0, minf = 0;
	int low_freq_bus_ready = 0;
	int bus_incr = 0, cpu_dcr = 0;

	low_freq_bus_ready = low_freq_bus_used();

	/* Check DVFS frequency adjustment interrupt status */
	reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
	fsvai = (reg & MXC_DVFSCNTR_FSVAI_MASK) >> MXC_DVFSCNTR_FSVAI_OFFSET;
	/* Check FSVAI, FSVAI=0 is error */
	if (fsvai == FSVAI_FREQ_NOCHANGE) {
		/* Do nothing. Freq change is not required */
		goto END;
	}
	curr_cpu = clk_get_rate(cpu_clk);

	/* If FSVAI indicate freq down,
	   check arm-clk is not in lowest frequency 200 MHz */
	if (fsvai == FSVAI_FREQ_DECREASE) {
		if (curr_cpu == cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate) {
			minf = 1;
			if (low_bus_freq_mode)
				goto END;
		} else {
			/* freq down */
			curr_wp++;
			if (curr_wp >= cpu_wp_nr) {
				curr_wp = cpu_wp_nr - 1;
				goto END;
			}

			if (curr_wp == cpu_wp_nr - 1 && !low_freq_bus_ready) {
				minf = 1;
				dvfs_load_config(1);
			} else {
				cpu_dcr = 1;
			}
		}
	} else {
		if (curr_cpu == cpu_wp_tbl[0].cpu_rate) {
			maxf = 1;
			goto END;
		} else {
			if (!high_bus_freq_mode) {
				/* bump up LP freq first. */
				bus_incr = 1;
				dvfs_load_config(2);
			} else {
				/* freq up */
				curr_wp = 0;
				maxf = 1;
				dvfs_load_config(0);
			}
		}
	}

	low_freq_bus_ready = low_freq_bus_used();
	if ((curr_wp == cpu_wp_nr - 1) && (!low_bus_freq_mode)
	    && (low_freq_bus_ready) && !bus_incr) {
		if (cpu_dcr)
			ret = set_cpu_freq(curr_wp);
		if (!cpu_dcr) {
			set_low_bus_freq();
			dvfs_load_config(3);
		} else {
			dvfs_load_config(2);
			cpu_dcr = 0;
		}
	} else {
		if (!high_bus_freq_mode)
			set_high_bus_freq(1);

		if (!bus_incr)
			ret = set_cpu_freq(curr_wp);
		bus_incr = 0;
	}


END:	/* Set MAXF, MINF */
	reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
	reg = (reg & ~(MXC_DVFSCNTR_MAXF_MASK | MXC_DVFSCNTR_MINF_MASK));
	reg |= maxf << MXC_DVFSCNTR_MAXF_OFFSET;
	reg |= minf << MXC_DVFSCNTR_MINF_OFFSET;

	/* Enable DVFS interrupt */
	/* FSVAIM=0 */
	reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
	reg |= FSVAI_FREQ_NOCHANGE;
	/* LBFL=1 */
	reg = (reg & ~MXC_DVFSCNTR_LBFL);
	reg |= MXC_DVFSCNTR_LBFL;
	__raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR);
	/*Unmask GPC1 IRQ */
	reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
	reg &= ~MXC_GPCCNTR_GPCIRQM;
	__raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);

#if defined(CONFIG_CPU_FREQ)
	if (cpufreq_trig_needed == 1) {
		cpufreq_trig_needed = 0;
		cpufreq_update_policy(0);
	}
#endif
}
Example #5
0
void bus_freq_update(struct clk *clk, bool flag)
{
	mutex_lock(&bus_freq_mutex);

	if (flag) {
		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);
		} 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())
						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 {
		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 {
			/* 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);
				}
			}
		}
	}
	mutex_unlock(&bus_freq_mutex);
	return;
}
static void dvfs_core_work_handler(struct work_struct *work)
{
	u32 fsvai;
	u32 reg;
	u32 curr_cpu = 0;
	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
	int cpu;

	low_freq_bus_ready = low_freq_bus_used();

	/* Check DVFS frequency adjustment interrupt status */
	reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
	fsvai = (reg & MXC_DVFSCNTR_FSVAI_MASK) >> MXC_DVFSCNTR_FSVAI_OFFSET;
	/* Check FSVAI, FSVAI=0 is error */
	if (fsvai == FSVAI_FREQ_NOCHANGE) {
		/* Do nothing. Freq change is not required */
		goto END;
	}
	curr_cpu = clk_get_rate(cpu_clk);
	/* If FSVAI indicate freq down,
	   check arm-clk is not in lowest frequency*/
	if (fsvai == FSVAI_FREQ_DECREASE) {
		if (curr_cpu <= cpu_op_tbl[cpu_op_nr - 1].cpu_rate) {
			minf = 1;
			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++;
			maxf = 0;
			if (curr_op >= cpu_op_nr) {
				curr_op = cpu_op_nr - 1;
				goto END;
			}
			cpu_dcr = 1;
			dvfs_load_config(curr_op);
		}
	} else {
		if (curr_cpu == cpu_op_tbl[0].cpu_rate) {
			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. */
				bus_incr = 1;
				dvfs_load_config(cpu_op_nr);
			} else {
				/* freq up */
				curr_op = 0;
				maxf = 1;
				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) {
		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) {
			set_low_bus_freq();
			dvfs_load_config(cpu_op_nr + 1);
		}
		mutex_unlock(&bus_freq_mutex);
	} else {
		if (!high_bus_freq_mode) {
			mutex_unlock(&bus_freq_mutex);
			set_high_bus_freq(1);
		} else
			mutex_unlock(&bus_freq_mutex);
		if (!bus_incr)
			ret = set_cpu_freq(curr_op);
		bus_incr = 0;
	}

END:
	if (cpufreq_trig_needed == 1) {
		/*Fix loops-per-jiffy */
#ifdef CONFIG_SMP
		for_each_online_cpu(cpu)
			per_cpu(cpu_data, cpu).loops_per_jiffy =
			dvfs_cpu_jiffies(per_cpu(cpu_data, cpu).loops_per_jiffy,
				curr_cpu / 1000, clk_get_rate(cpu_clk) / 1000);
#else
		u32 old_loops_per_jiffy = loops_per_jiffy;

		loops_per_jiffy =
			dvfs_cpu_jiffies(old_loops_per_jiffy,
				curr_cpu/1000, clk_get_rate(cpu_clk) / 1000);
#endif
#if defined (CONFIG_CPU_FREQ)
		/* Fix CPU frequency for CPUFREQ. */
		for (cpu = 0; cpu < num_online_cpus(); cpu++)
			cpufreq_get(cpu);
#endif
		cpufreq_trig_needed = 0;
	}

	/* Set MAXF, MINF */
	reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
	reg = (reg & ~(MXC_DVFSCNTR_MAXF_MASK | MXC_DVFSCNTR_MINF_MASK));
	reg |= maxf << MXC_DVFSCNTR_MAXF_OFFSET;
	reg |= minf << MXC_DVFSCNTR_MINF_OFFSET;

	/* Enable DVFS interrupt */
	/* FSVAIM=0 */
	reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
	reg |= FSVAI_FREQ_NOCHANGE;
	/* LBFL=1 */
	reg = (reg & ~MXC_DVFSCNTR_LBFL);
	reg |= MXC_DVFSCNTR_LBFL;
	__raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR);
	/*Unmask GPC1 IRQ */
	reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset);
	reg &= ~MXC_GPCCNTR_GPCIRQM;
	__raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset);

}
static void dvfs_core_work_handler(struct work_struct *work)
{
	u32 fsvai;
	u32 reg;
	u32 curr_cpu;
	int ret = 0;
	int low_freq_bus_ready = 0;
	int bus_incr = 0, cpu_dcr = 0;
	unsigned long old_loops_per_jiffy;

	GALLEN_DBGLOCAL_BEGIN();

	low_freq_bus_ready = low_freq_bus_used();
	curr_cpu = clk_get_rate(cpu_clk);

	/* Check DVFS frequency adjustment interrupt status */
	reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
	fsvai = (reg & MXC_DVFSCNTR_FSVAI_MASK) >> MXC_DVFSCNTR_FSVAI_OFFSET;
	/* Check FSVAI, FSVAI=0 is error */
	if (fsvai == FSVAI_FREQ_NOCHANGE) {
		GALLEN_DBGLOCAL_RUNLOG(0);
		/* Do nothing. Freq change is not required */
		goto END;
	}

	curr_cpu = clk_get_rate(cpu_clk);
	/* If FSVAI indicate freq down,
	   check arm-clk is not in lowest frequency*/
	if (fsvai == FSVAI_FREQ_DECREASE) {
		GALLEN_DBGLOCAL_RUNLOG(1);
		if (curr_cpu == cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate) {
			GALLEN_DBGLOCAL_RUNLOG(2);
			minf = 1;
			if (low_bus_freq_mode) {
				GALLEN_DBGLOCAL_RUNLOG(3);
				goto END;
			}
		} else {
			GALLEN_DBGLOCAL_RUNLOG(4);
			/* freq down */
			curr_wp++;
			maxf = 0;
			if (curr_wp >= cpu_wp_nr) {
				GALLEN_DBGLOCAL_RUNLOG(5);
				curr_wp = cpu_wp_nr - 1;
				goto END;
			}

			cpu_dcr = 1;
			dvfs_load_config(curr_wp);
		}
	} else {
		GALLEN_DBGLOCAL_RUNLOG(6);
		if (curr_cpu == cpu_wp_tbl[0].cpu_rate) {
			GALLEN_DBGLOCAL_RUNLOG(7);
			maxf = 1;
			goto END;
		} else {
			GALLEN_DBGLOCAL_RUNLOG(8);
			if (!high_bus_freq_mode &&
				dvfs_config_setpoint == (cpu_wp_nr + 1)) {
				GALLEN_DBGLOCAL_RUNLOG(9);
				/* bump up LP freq first. */
				bus_incr = 1;
				dvfs_load_config(cpu_wp_nr);
			} else {
				GALLEN_DBGLOCAL_RUNLOG(10);
				/* freq up */
				curr_wp = 0;
				maxf = 1;
				minf = 0;
				dvfs_load_config(0);
			}
		}
	}

	low_freq_bus_ready = low_freq_bus_used();
	if ((curr_wp == cpu_wp_nr - 1) && (!low_bus_freq_mode)
	    && (low_freq_bus_ready) && !bus_incr) {
		GALLEN_DBGLOCAL_RUNLOG(11);
		if (!minf) {
			GALLEN_DBGLOCAL_RUNLOG(12);
			set_cpu_freq(curr_wp);
		}
		/* If dvfs_core_wp is greater than cpu_wp_nr, it implies
		 * we support LPAPM mode for this platform.
		 */
		if (dvfs_core_wp > cpu_wp_nr) {
			GALLEN_DBGLOCAL_RUNLOG(13);
			set_low_bus_freq();
			dvfs_load_config(cpu_wp_nr + 1);
		}
	} else {
		GALLEN_DBGLOCAL_RUNLOG(14);
		if (!high_bus_freq_mode) {
			GALLEN_DBGLOCAL_RUNLOG(15);
			set_high_bus_freq(1);
		}
		if (!bus_incr) {
			GALLEN_DBGLOCAL_RUNLOG(16);
			ret = set_cpu_freq(curr_wp);
		}
		bus_incr = 0;
	}

	printk("current wp=%d\n",curr_wp);

	if (cpufreq_trig_needed == 1) {
		GALLEN_DBGLOCAL_RUNLOG(17);
		/*Fix loops-per-jiffy */
		old_loops_per_jiffy = loops_per_jiffy;

		loops_per_jiffy =
			dvfs_cpu_jiffies(old_loops_per_jiffy,
				curr_cpu/1000, clk_get_rate(cpu_clk) / 1000);

#if defined(CONFIG_CPU_FREQ)
		/* Fix CPU frequency for CPUFREQ. */
		cpufreq_get(0);
#endif
		cpufreq_trig_needed = 0;
	}

END:
	/* Set MAXF, MINF */
	reg = __raw_readl(dvfs_data->membase + MXC_DVFSCORE_CNTR);
	reg = (reg & ~(MXC_DVFSCNTR_MAXF_MASK | MXC_DVFSCNTR_MINF_MASK));
	reg |= maxf << MXC_DVFSCNTR_MAXF_OFFSET;
	reg |= minf << MXC_DVFSCNTR_MINF_OFFSET;

	/* Enable DVFS interrupt */
	/* FSVAIM=0 */
	reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
	reg |= FSVAI_FREQ_NOCHANGE;
	/* LBFL=1 */
	reg = (reg & ~MXC_DVFSCNTR_LBFL);
	reg |= MXC_DVFSCNTR_LBFL;
	__raw_writel(reg, dvfs_data->membase + MXC_DVFSCORE_CNTR);
	/*Unmask GPC1 IRQ */
	reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset);
	reg &= ~MXC_GPCCNTR_GPCIRQM;
	__raw_writel(reg, gpc_base + dvfs_data->gpc_cntr_offset);

	GALLEN_DBGLOCAL_END();
}