/*!
 * This function disables the DVFS module.
 */
void stop_dvfs(void)
{
	u32 reg = 0;
	unsigned long flags;
	u32 curr_cpu;
	unsigned long old_loops_per_jiffy;

	if (dvfs_core_is_active) {

		/* Mask dvfs irq, disable DVFS */
		reg = __raw_readl(dvfs_data->membase
				  + MXC_DVFSCORE_CNTR);
		/* FSVAIM=1 */
		reg |= MXC_DVFSCNTR_FSVAIM;
		__raw_writel(reg, dvfs_data->membase
				  + MXC_DVFSCORE_CNTR);

		curr_wp = 0;
		if (!high_bus_freq_mode)
			set_high_bus_freq(1);

		curr_cpu = clk_get_rate(cpu_clk);

		if (curr_cpu != cpu_wp_tbl[curr_wp].cpu_rate)
			set_cpu_freq(curr_wp);

		if (cpufreq_trig_needed == 1) {
			/*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;
		}

		spin_lock_irqsave(&mxc_dvfs_core_lock, flags);

		reg = __raw_readl(dvfs_data->membase
				  + MXC_DVFSCORE_CNTR);
		reg = (reg & ~MXC_DVFSCNTR_DVFEN);
		__raw_writel(reg, dvfs_data->membase
				  + MXC_DVFSCORE_CNTR);

		spin_unlock_irqrestore(&mxc_dvfs_core_lock, flags);

		dvfs_core_is_active = 0;

		clk_disable(dvfs_clk);
		}

	printk(KERN_DEBUG "DVFS is stopped\n");
}
Пример #2
0
/*!
 * This function disables the DVFS module.
 */
void stop_dvfs(void)
{
	u32 reg = 0;
	unsigned long flags;
	u32 curr_cpu;
	int cpu;
#ifndef CONFIG_SMP
	unsigned long old_loops_per_jiffy;
#endif

	if (dvfs_core_is_active) {

		/* Mask dvfs irq, disable DVFS */
		reg = __raw_readl(dvfs_data->membase
				  + MXC_DVFSCORE_CNTR);
		/* FSVAIM=1 */
		reg |= MXC_DVFSCNTR_FSVAIM;
		__raw_writel(reg, dvfs_data->membase
				  + MXC_DVFSCORE_CNTR);

		curr_op = 0;
		mutex_lock(&bus_freq_mutex);
		if (!high_bus_freq_mode) {
			mutex_unlock(&bus_freq_mutex);
			set_high_bus_freq(1);
		} else
			mutex_unlock(&bus_freq_mutex);

		curr_cpu = clk_get_rate(cpu_clk);
		if (curr_cpu != cpu_op_tbl[curr_op].cpu_rate) {
			set_cpu_freq(curr_op);

			/*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
		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
		}
		spin_lock_irqsave(&mxc_dvfs_core_lock, flags);

		reg = __raw_readl(dvfs_data->membase
				  + MXC_DVFSCORE_CNTR);
		reg = (reg & ~MXC_DVFSCNTR_DVFEN);
		__raw_writel(reg, dvfs_data->membase
				  + MXC_DVFSCORE_CNTR);

		spin_unlock_irqrestore(&mxc_dvfs_core_lock, flags);

		dvfs_core_is_active = 0;

		clk_disable(dvfs_clk);
	}

	printk(KERN_DEBUG "DVFS is stopped\n");
}
Пример #3
0
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();
}