4.Linux cupfreq driverLinux有专门的cpufreq子系统来针对cpu的运行状态来调节cpu的工作频率,从而降低功耗。cpufreq子系统有如下组件来描述调频过程中的各个功能模块:
- cpufreqnotifier :触发频率调节的源头
- cpufreq_policy :描述有cpu频率状态的数据结构
- cpufreqgovernor :cpu频率调控器
- cpufreq_driver :描述平台相关的cpufreq驱动的数据结构
- frequencytable :频率表
cpufreqcore跟大多数Linux子系统一样,cpufreqcore部分出要是抽象出平台无关的操作上述组件的接口。
cpufreq core 的代码在driver/cpufreq/cpufreq.c种。
cpufreq core定义了两条通知链,一条是处理cpu的工作频率切换到一个新的policy,另一条是用来处理当cpu频率切换后,受影响的设备的状态。
cpufreqcore导出了相应的注册通知的API
cpufreqcore定义了一个governor链表来保存多种频率策略。Linux内核本身也提供了多种频率调节策略,在配置内核时可选择。
在配置内核是可针对不同的需求选择不同的频率策略。就我个人的理解,在嵌入式的手持设备上,很多情况都没有使用内核提供的电源策略。governor部分,IBMLinux有一个系列文章描述的很详细。
减少 Linux电耗,第 1 部分: CPUfreq 子系统
减少 Linux耗电,第 2 部分: 一般设置和与调控器相关的设置
减少 Linux耗电,第 3 部分: 调优结果
cpufreqcore定义了静态全局结构体指针cpufreq_driver用于记录注册到cpufreqcore中的驱动:
并导出注册驱动符号用于注册平台相关驱动:
具体代码如下:
[cpp] viewplaincopyprint?
-
-
-
- int cpufreq_register_driver(struct cpufreq_driver *driver_data)
- {
- unsigned long flags;
- int ret;
-
- if (cpufreq_disabled())
- return -ENODEV;
-
- if (!driver_data || !driver_data->verify || !driver_data->init ||
- ((!driver_data->setpolicy) && (!driver_data->target)))
- return -EINVAL;
-
- pr_debug("trying to register driver %s\n", driver_data->name);
-
- if (driver_data->setpolicy)
- driver_data->flags |= CPUFREQ_CONST_LOOPS;
-
- spin_lock_irqsave(&cpufreq_driver_lock, flags);
- if (cpufreq_driver) {
- spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
- return -EBUSY;
- }
- cpufreq_driver = driver_data;
- spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-
- ret = subsys_interface_register(&cpufreq_interface);
- if (ret)
- goto err_null_driver;
-
- if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) {
- int i;
- ret = -ENODEV;
-
-
- for (i = 0; i < nr_cpu_ids; i++)
- if (cpu_possible(i) && per_cpu(cpufreq_cpu_data, i)) {
- ret = 0;
- break;
- }
-
-
- if (ret) {
- pr_debug("no CPU initialized for driver %s\n",
- driver_data->name);
- goto err_if_unreg;
- }
- }
-
- register_hotcpu_notifier(&cpufreq_cpu_notifier);
- pr_debug("driver %s up and running\n", driver_data->name);
-
- return 0;
- err_if_unreg:
- subsys_interface_unregister(&cpufreq_interface);
- err_null_driver:
- spin_lock_irqsave(&cpufreq_driver_lock, flags);
- cpufreq_driver = NULL;
- spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
- return ret;
- }
整个注册过程的关键有三部分:
a)把平台相关的structcpufreq_driver类指针driver_data赋值给全局指针cpufreq_driver
b)调用平台相关cpufreq_driver中的init成员函数
c)注册cpufreq_cpu_notifier |