/*! * 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"); }
/*! * 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"); }
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(); }