首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

电源管理与LINUX

电源管理与LINUX

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
返回列表