@@ -29,6 +29,8 @@
#include <linux/smp.h>
#include <linux/sched.h>
#include <linux/cpufreq.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
#include <linux/compiler.h>
#include <linux/slab.h>
@@ -105,8 +107,12 @@ static u8 OSC_UUID[16] = {0x9F, 0x2C, 0x9B, 0x63, 0x91, 0x70, 0x1f, 0x49,
struct pcc_cpu {
u32 input_offset;
u32 output_offset;
+ u64 prev_time;
};
+static u32 max_time_between_cmds = 0;
+static u32 min_time_between_cmds = 0;
+
static struct pcc_cpu __percpu *pcc_cpu_info;
static int pcc_cpufreq_verify(struct cpufreq_policy *policy)
@@ -137,7 +143,7 @@ static inline void pcc_clear_mapping(void)
pcch_virt_addr = NULL;
}
-static unsigned int pcc_get_freq(unsigned int cpu)
+static unsigned int real_pcc_get_freq(unsigned int cpu)
{
struct pcc_cpu *pcc_cpu_data;
unsigned int curr_freq;
@@ -185,6 +191,8 @@ static unsigned int pcc_get_freq(unsigned int cpu)
" capped at %d\n", cpu, curr_freq);
}
+ pcc_cpu_data->prev_time = get_jiffies_64();
+
spin_unlock(&pcc_lock);
return curr_freq;
@@ -194,6 +202,32 @@ cmd_incomplete:
return 0;
}
+static unsigned int pcc_get_freq(unsigned int cpu)
+{
+ struct pcc_cpu *pcc_cpu_data;
+ unsigned int curr_freq;
+ u64 cur_time;
+ u32 diff_time;
+
+ pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu);
+ cur_time = get_jiffies_64();
+ diff_time = jiffies_to_usecs(cur_time - pcc_cpu_data->prev_time);
+
+ if (diff_time > max_time_between_cmds) {
+ curr_freq = real_pcc_get_freq(cpu);
+ cur_time = get_jiffies_64();
+ diff_time =
+ jiffies_to_usecs(cur_time - pcc_cpu_data->prev_time);
+ }
+
+ if (diff_time < min_time_between_cmds)
+ msleep((min_time_between_cmds - diff_time) / 1000);
+
+ curr_freq = real_pcc_get_freq(cpu);
+
+ return curr_freq;
+}
+
static int pcc_cpufreq_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
@@ -521,6 +555,9 @@ static int __init pcc_cpufreq_probe(void)
goto pcch_free;
}
+ max_time_between_cmds = ioread32(&pcch_hdr->maximum_time);
+ min_time_between_cmds = ioread32(&pcch_hdr->minimum_time);
+
printk(KERN_DEBUG "pcc-cpufreq: (v%s) driver loaded with frequency"
" limits: %d MHz, %d MHz\n", PCC_VERSION,
ioread32(&pcch_hdr->minimum_frequency),