Cpufreq framework 分析-2

来源:互联网 发布:免费好用的mac清理软件 编辑:程序博客网 时间:2024/05/16 03:14

cpufreq 是如何来设置cpu频率的,通过哪里来做实际的频率设置

看下面的代码.

这个init 回调函数在cpufreq_register_driver(&msm_cpufreq_driver); 向core 层注册driver的时候执行.static struct cpufreq_driver msm_cpufreq_driver = {    /* lps calculations are handled here. */    .flags      = CPUFREQ_STICKY | CPUFREQ_CONST_LOOPS,    .init       = **msm_cpufreq_init**,    .verify     = msm_cpufreq_verify,    .target     = msm_cpufreq_target,    .get        = msm_cpufreq_get_freq,    .name       = "msm",    .attr       = msm_freq_attr,};static int msm_cpufreq_init(struct cpufreq_policy *policy){    int cur_freq;    int index;    int ret = 0;    struct cpufreq_frequency_table *table =            per_cpu(freq_table, policy->cpu);    int cpu;    /*     * In some SoC, some cores are clocked by same source, and their     * frequencies can not be changed independently. Find all other     * CPUs that share same clock, and mark them as controlled by     * same policy.     */    for_each_possible_cpu(cpu)        if (cpu_clk[cpu] == cpu_clk[policy->cpu])            cpumask_set_cpu(cpu, policy->cpus);    if (cpufreq_frequency_table_cpuinfo(policy, table))        pr_err("cpufreq: failed to get policy min/max\n");    cur_freq = clk_get_rate(cpu_clk[policy->cpu])/1000;    if (cpufreq_frequency_table_target(policy, table, cur_freq,        CPUFREQ_RELATION_H, &index) &&        cpufreq_frequency_table_target(policy, table, cur_freq,        CPUFREQ_RELATION_L, &index)) {        pr_info("cpufreq: cpu%d at invalid freq: %d\n",                policy->cpu, cur_freq);        return -EINVAL;    }    /*     * Call set_cpu_freq unconditionally so that when cpu is set to     * online, frequency limit will always be updated.     */    ret = set_cpu_freq(policy, table[index].frequency,               table[index].driver_data);    if (ret)        return ret;    pr_debug("cpufreq: cpu%d init at %d switching to %d\n",            policy->cpu, cur_freq, table[index].frequency);    policy->cur = table[index].frequency;    cpufreq_frequency_table_get_attr(table, policy->cpu);    return 0;}

这个msm_cpufreq_target 是在每次CPU频率变化是通过core层或者sys 控制当前频率变化时调用.

static int msm_cpufreq_target(struct cpufreq_policy *policy,                unsigned int target_freq,                unsigned int relation){    int ret = 0;    int index;    struct cpufreq_frequency_table *table;    mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);    if (target_freq == policy->cur)        goto done;    if (per_cpu(cpufreq_suspend, policy->cpu).device_suspended) {        pr_debug("cpufreq: cpu%d scheduling frequency change "                "in suspend.\n", policy->cpu);        ret = -EFAULT;        goto done;    }// 获取table     table = cpufreq_frequency_get_table(policy->cpu);    if (cpufreq_frequency_table_target(policy, table, target_freq, relation,            &index)) {        pr_err("cpufreq: invalid target_freq: %d\n", target_freq);        ret = -EINVAL;        goto done;    }    pr_debug("CPU[%d] target %d relation %d (%d-%d) selected %d\n",        policy->cpu, target_freq, relation,        policy->min, policy->max, table[index].frequency);// 最终来设置检查后么有没问题的频率到cpu硬件.    ret = set_cpu_freq(policy, table[index].frequency,               table[index].driver_data);done:    mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);    return ret;}
0 0