标题:
电源管理与LINUX
[打印本页]
作者:
look_w
时间:
2017-10-19 13:55
标题:
电源管理与LINUX
4.Linux cupfreq driver
Linux有专门的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]
viewplain
copy
print
?
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
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0