--- overclock/orig/overclock.c Tue May 25 16:06:43 2010 +++ overclock/patched/overclock.c Thu Jun 03 19:21:09 2010 @@ -128,12 +128,13 @@ #define DRIVER_AUTHOR "Tiago Sousa " #define DRIVER_DESCRIPTION "Motorola Milestone CPU overclocking" -#define DRIVER_VERSION "1.2" +#define DRIVER_VERSION "1.2(+stats patch)" #define DRIVER_DEFAULT_RATE 550000 #define DRIVER_DEFAULT_VSEL 56 #define DRIVER_DEFAULT_FREQ_TABLE_ADDR 0xc050bb68 #define DRIVER_DEFAULT_MPU_OPPS_ADDR 0xc050c888 +#define DRIVER_DEFAULT_STATS_ADDR 0xc0574910 MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESCRIPTION); @@ -144,7 +145,9 @@ static uint max_vsel = DRIVER_DEFAULT_VSEL; static uint freq_table_addr = DRIVER_DEFAULT_FREQ_TABLE_ADDR; static uint mpu_opps_addr = DRIVER_DEFAULT_MPU_OPPS_ADDR; +static uint stats_addr = DRIVER_DEFAULT_STATS_ADDR; static uint omap2_clk_init_cpufreq_table_addr = 0; +static uint cpufreq_stats_update_addr = 0; module_param(max_rate, uint, 0444); MODULE_PARM_DESC(max_rate, "The maximum MPU clock rate frequency in KHz (default 550000)"); @@ -156,6 +159,8 @@ MODULE_PARM_DESC(mpu_opps_addr, "The mpu_opps address (default 0xc050c888)"); module_param(omap2_clk_init_cpufreq_table_addr, uint, 0444); MODULE_PARM_DESC(omap2_clk_init_cpufreq_table_addr, "The omap2_clk_init_cpufreq_table function address to autodetect the other addresses (default 0, doesn't autodetect)"); +module_param(cpufreq_stats_update_addr, uint, 0444); +MODULE_PARM_DESC(cpufreq_stats_update_addr, "The cpufreq_stats_update function address to autodetect the stats address (default 0, doesn't autodetect)"); static struct cpufreq_frequency_table *freq_table; static struct omap_opp *my_mpu_opps; @@ -163,13 +168,25 @@ #define MPU_CLK "arm_fck" static struct clk *mpu_clk; +struct cpufreq_stats { + unsigned int cpu; + unsigned int total_trans; + unsigned long long last_time; + unsigned int max_state; + unsigned int state_num; + unsigned int last_index; + cputime64_t *time_in_state; + unsigned int *freq_table; +}; +static struct cpufreq_stats *stat; + #define BUF_SIZE PAGE_SIZE static char *buf; static void set_max_speed(void) { printk(KERN_INFO "overclock: setting max_rate %u and max_vsel %u\n", max_rate, max_vsel); - freq_table[0].frequency = policy->max = policy->cpuinfo.max_freq = + freq_table[0].frequency = stat->freq_table[0] = policy->max = policy->cpuinfo.max_freq = policy->user_policy.max = max_rate; my_mpu_opps[MAX_VDD1_OPP].vsel = max_vsel; my_mpu_opps[MAX_VDD1_OPP].rate = max_rate*1000; @@ -196,6 +213,22 @@ } } +static void stats_find_addr(void) +{ + unsigned char *func = (void *)cpufreq_stats_update_addr; + uint *addr; + int i; + for(i = 0; i < 100; i+=4) { + if((func[i+3] == 0xe5) /* ldr */ + && func[i+2] == 0x9f) { /* [pc, */ + addr = (void *)((uint)func)+i+8+func[i]; + stats_addr = *addr; + printk (KERN_INFO "overclock: found stats_addr at 0x%x\n", stats_addr); + break; + } + } +} + static int proc_info_read(char *buffer, char **buffer_location, off_t offset, int count, int *eof, void *data) { @@ -373,7 +406,43 @@ omap2_clk_init_cpufreq_table_addr = newaddr; if(omap2_clk_init_cpufreq_table_addr) omap2_find_addrs(); + freq_table = (void *)freq_table_addr; + my_mpu_opps = *(struct omap_opp **)mpu_opps_addr; + return len; +} + +static int proc_cpufreq_stats_update_addr_read(char *buffer, + char **buffer_location, off_t offset, int count, int *eof, + void *data) +{ + int ret; + + if (offset > 0) + ret = 0; + else + ret = scnprintf(buffer, count, "0x%x\n", + (uint)cpufreq_stats_update_addr); + + return ret; +} + +static int proc_cpufreq_stats_update_addr_write(struct file *filp, + const char __user *buffer, unsigned long len, void *data) +{ + ulong newaddr; + int result; + if(!len || len >= BUF_SIZE) + return -ENOSPC; + if(copy_from_user(buf, buffer, len)) + return -EFAULT; + buf[len] = 0; + if((result = strict_strtoul(buf, 0, &newaddr))) + return result; + cpufreq_stats_update_addr = newaddr; + if(cpufreq_stats_update_addr) + stats_find_addr(); + stat = *(struct cpufreq_stats **)stats_addr; return len; } @@ -405,7 +474,7 @@ return -EFAULT; buf[len] = 0; if(sscanf(buf, "%d %d", &index, &frequency) == 2) { - freq_table[index].frequency = frequency; + freq_table[index].frequency = stat->freq_table[index] = frequency; } else printk(KERN_INFO "overclock: insufficient parameters for freq_table\n"); @@ -464,15 +533,18 @@ static int __init overclock_init(void) { struct proc_dir_entry *proc_entry; + unsigned long addrestest; printk(KERN_INFO "overclock: %s version %s\n", DRIVER_DESCRIPTION, DRIVER_VERSION); printk(KERN_INFO "overclock: by %s\n", DRIVER_AUTHOR); if(omap2_clk_init_cpufreq_table_addr) omap2_find_addrs(); - + if(cpufreq_stats_update_addr) + stats_find_addr(); freq_table = (void *)freq_table_addr; my_mpu_opps = *(struct omap_opp **)mpu_opps_addr; + stat = *(struct cpufreq_stats **)stats_addr; policy = cpufreq_cpu_get(0); mpu_clk = clk_get(NULL, MPU_CLK); @@ -493,6 +565,8 @@ proc_entry->write_proc = proc_mpu_opps_addr_write; proc_entry = create_proc_read_entry("overclock/omap2_clk_init_cpufreq_table_addr", 0644, NULL, proc_omap2_clk_init_cpufreq_table_addr_read, NULL); proc_entry->write_proc = proc_omap2_clk_init_cpufreq_table_addr_write; + proc_entry = create_proc_read_entry("overclock/cpufreq_stats_update_addr", 0644, NULL, proc_cpufreq_stats_update_addr_read, NULL); + proc_entry->write_proc = proc_cpufreq_stats_update_addr_write; proc_entry = create_proc_read_entry("overclock/freq_table", 0644, NULL, proc_freq_table_read, NULL); proc_entry->write_proc = proc_freq_table_write; proc_entry = create_proc_read_entry("overclock/mpu_opps", 0644, NULL, proc_mpu_opps_read, NULL); @@ -508,6 +582,7 @@ remove_proc_entry("overclock/mpu_opps", NULL); remove_proc_entry("overclock/freq_table", NULL); remove_proc_entry("overclock/omap2_clk_init_cpufreq_table_addr", NULL); + remove_proc_entry("overclock/cpufreq_stats_update_addr", NULL); remove_proc_entry("overclock/mpu_opps_addr", NULL); remove_proc_entry("overclock/freq_table_addr", NULL); remove_proc_entry("overclock/max_vsel", NULL);