参考http://www.wowotech.net/sort/linux_kenrel博文的内容
Linux电源管理是一个比较庞大的子系统,涉及到供电(power supply)、充电(Charger)、时钟(Clock)、频率(Frequency)、电压(Voltage)、睡眠/唤醒(Suspend/Resume)等方方面面。
Power Supply,是一个供用户空间程序监控系统的供电状态(电池供电,USB供电,AC供电等等)的class.通俗的讲,它是一个Battery&Charger驱动的Framework
Clock Framework,Clock驱动的Framework,用于统一管理系统的时钟资源
Regulator Framework,Volatage/Current Regulator驱动的Framework。该驱动用于调节CPU等模块的电压和电流值
Dynamic Tick/Clock Event,在传统的Linux Kernel中,系统Tick是固定周期(如10ms)的,因此每个一个Tick,就会产生一个Timer中断。这会唤醒处于Idle或者Sleep状态的CPU,而很多时候这种唤醒是没有意义的。因此新的Kernel就提出了Dynamic Tick的概念,Tick不再是周期性的,而是根据系统中定时器的情况,不规律的产生,这样可以减少很多无用的Timer中断
CPU Idle,用于控制CPU Idle状态的Framework
Generic PM,传统意义上的Power Management,如Power Off、Suspend to RAM、Suspend to DISK、Hibernate等
Runtime PM and Wakelock,运行时的Power Management,不再需要用户程序的干涉,由kernel统一调度,实时的关闭或打开设备,以便在使用性能和省电性能之间找到最佳的平衡。
CPU Freq/Device Freq,用于实现CPU以及Device频率调整的Framework
OPP(Operating Performance Point),是指可以使SOCs或者Devices正常工作的电压和频率组合。内核提供这一个Layer,是为了在众多的电压和频率组合中,筛选出一些相对固定的组合,从而使事情变得更为简答一些二。
PM QOS,所谓的PM QOS,是指系统在指定的运行状态下(不同电压、频率、不同模式之间切换,等等)的工作质量,包括latency、timeout、throughout三个参数,单位分别为us,us和kb.s。通过QOS,可以分析,改善系统的性能。
电源模块的相关初始化:
static int __init pm_init(void)
{
int error = pm_start_workqueue();
if (error)
return error;
hibernate_image_size_init();
hibernate_reserved_size_init();
power_kobj = kobject_create_and_add("power", NULL);
if (!power_kobj)
return -ENOMEM;
return sysfs_create_group(power_kobj, &attr_group);
}
电源管理有关的代码,kernel目录下:
Cpu_pm.c (kernel):core_initcall(cpu_pm_init);//优先级为1
电源管理有关的代码,kernel\power目录下:
Main.c (kernel\power):core_initcall(pm_init);//优先级为1
Main.c (kernel\power):late_initcall(pm_debugfs_init);//优先级为7
Qos.c (kernel\power):late_initcall(pm_qos_power_init);//优先级为7
电源管理有关的代码,drivers\base\power目录下
Wakeup.c (drivers\base\power):postcore_initcall(wakeup_sources_debugfs_init);//优先级为2
电源管理有关的代码,drivers\cpuidle目录下(按调用顺序):
Cpuidle.c (drivers\cpuidle):core_initcall(cpuidle_init);//优先级为1
Ladder.c (drivers\cpuidle\governors):module_init(init_ladder);//优先级为6
Menu.c (drivers\cpuidle\governors):module_init(init_menu);//优先级为6
电源管理有关的代码,drivers\cpufreq目录下(按调用顺序):
Cpufreq.c (drivers\cpufreq):pure_initcall(init_cpufreq_transition_notifier_list);//优先级为0
Cpufreq.c (drivers\cpufreq):core_initcall(cpufreq_core_init);//优先级为1
Cpufreq_performance.c (drivers\cpufreq):fs_initcall(cpufreq_gov_performance_init);//优先级为5
Cpufreq_userspace.c (drivers\cpufreq):fs_initcall(cpufreq_gov_userspace_init);//优先级为5
Cpufreq_stats.c (drivers\cpufreq):module_init(cpufreq_stats_init);//优先级为6
Cpufreq_powersave.c (drivers\cpufreq):module_init(cpufreq_gov_powersave_init);//优先级为6
Cpufreq_conservative.c (drivers\cpufreq):module_init(cpufreq_gov_dbs_init);//优先级为6
Cpufreq_ondemand.c (drivers\cpufreq):module_init(cpufreq_gov_dbs_init);//优先级为6
优先级为0的的函数:
static int __init init_cpufreq_transition_notifier_list(void)
{
srcu_init_notifier_head(&cpufreq_transition_notifier_list);
init_cpufreq_transition_notifier_list_called = true;
return 0;
}
优先级为1的的函数:
Cpu_pm.c (kernel):core_initcall(cpu_pm_init)
static int cpu_pm_init(void)
{
register_syscore_ops(&cpu_pm_syscore_ops);
return 0;
}
Cpuidle.c (drivers\cpuidle):core_initcall(cpuidle_init);
/**
* cpuidle_init - core initializer
*/
static int __init cpuidle_init(void)
{
int ret;
if (cpuidle_disabled())
return -ENODEV;
ret = cpuidle_add_interface(cpu_subsys.dev_root);
if (ret)
return ret;
latency_notifier_init(&cpuidle_latency_notifier);
return 0;
}
Cpufreq.c (drivers\cpufreq):core_initcall(cpufreq_core_init);
static int __init cpufreq_core_init(void)
{
int cpu;
for_each_possible_cpu(cpu) {
per_cpu(cpufreq_policy_cpu, cpu) = -1;
init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
}
cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
BUG_ON(!cpufreq_global_kobject);
register_syscore_ops(&cpufreq_syscore_ops);
return 0;
}
优先级为2的函数:
Wakeup.c (drivers\base\power):postcore_initcall(wakeup_sources_debugfs_init);
static int __init wakeup_sources_debugfs_init(void)
{
wakeup_sources_stats_dentry = debugfs_create_file("wakeup_sources",
S_IRUGO, NULL, NULL, &wakeup_sources_stats_fops);
return 0;
}
优先级为5的函数:
Cpufreq_performance.c (drivers\cpufreq):fs_initcall(cpufreq_gov_performance_init);
static int __init cpufreq_gov_performance_init(void)
{
return cpufreq_register_governor(&cpufreq_gov_performance);
}
Cpufreq_userspace.c (drivers\cpufreq):fs_initcall(cpufreq_gov_userspace_init);
优先级为6的函数:
Ladder.c (drivers\cpuidle\governors):module_init(init_ladder);
/**
* init_ladder - initializes the governor
*/
static int __init init_ladder(void)
{
return cpuidle_register_governor(&ladder_governor);
}
Menu.c (drivers\cpuidle\governors):module_init(init_menu);
/**
* init_menu - initializes the governor
*/
static int __init init_menu(void)
{
return cpuidle_register_governor(&menu_governor);
}
Cpufreq_stats.c (drivers\cpufreq):module_init(cpufreq_stats_init);
static int __init cpufreq_stats_init(void)
{
int ret;
unsigned int cpu;
spin_lock_init(&cpufreq_stats_lock);
ret = cpufreq_register_notifier(¬ifier_policy_block,
CPUFREQ_POLICY_NOTIFIER);
if (ret)
return ret;
ret = cpufreq_register_notifier(¬ifier_trans_block,
CPUFREQ_TRANSITION_NOTIFIER);
if (ret) {
cpufreq_unregister_notifier(¬ifier_policy_block,
CPUFREQ_POLICY_NOTIFIER);
return ret;
}
register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
for_each_online_cpu(cpu) {
cpufreq_update_policy(cpu);
}
return 0;
}
Cpufreq_powersave.c (drivers\cpufreq):module_init(cpufreq_gov_powersave_init);
static int __init cpufreq_gov_powersave_init(void)
{
return cpufreq_register_governor(&cpufreq_gov_powersave);
}
Cpufreq_conservative.c (drivers\cpufreq):module_init(cpufreq_gov_dbs_init);
static int __init cpufreq_gov_dbs_init(void)
{
return cpufreq_register_governor(&cpufreq_gov_conservative);
}
Cpufreq_ondemand.c (drivers\cpufreq):module_init(cpufreq_gov_dbs_init);
static int __init cpufreq_gov_dbs_init(void)
{
u64 idle_time;
int cpu = get_cpu();
idle_time = get_cpu_idle_time_us(cpu, NULL);
put_cpu();
if (idle_time != -1ULL) {
/* Idle micro accounting is supported. Use finer thresholds */
dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
dbs_tuners_ins.down_differential =
MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
/*
* In nohz/micro accounting case we set the minimum frequency
* not depending on HZ, but fixed (very low). The deferred
* timer might skip some samples if idle/sleeping as needed.
*/
min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
} else {
/* For correct statistics, we need 10 ticks for each measure */
min_sampling_rate =
MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
}
return cpufreq_register_governor(&cpufreq_gov_ondemand);
}
/* 这个文件包含了和中断有关的电源管理*/
Pm.c (kernel\irq):device_initcall(irq_pm_init_ops);
static int __init irq_pm_init_ops(void)
{
register_syscore_ops(&irq_pm_syscore_ops);
return 0;
}
优先级为7的函数
Main.c (kernel\power):late_initcall(pm_debugfs_init);
static int __init pm_debugfs_init(void)
{
debugfs_create_file("suspend_stats", S_IFREG | S_IRUGO,
NULL, NULL, &suspend_stats_operations);
return 0;
}
Qos.c (kernel\power):late_initcall(pm_qos_power_init);
static int __init pm_qos_power_init(void)
{
int ret = 0;
ret = register_pm_qos_misc(&cpu_dma_pm_qos);
if (ret < 0) {
printk(KERN_ERR "pm_qos_param: cpu_dma_latency setup failed\n");
return ret;
}
ret = register_pm_qos_misc(&network_lat_pm_qos);
if (ret < 0) {
printk(KERN_ERR "pm_qos_param: network_latency setup failed\n");
return ret;
}
ret = register_pm_qos_misc(&network_throughput_pm_qos);
if (ret < 0)
printk(KERN_ERR
"pm_qos_param: network_throughput setup failed\n");
return ret;
}
Pm.c (arch\arm\mach-davinci):late_initcall(davinci_pm_init);
static int __init davinci_pm_init(void)
{
return platform_driver_probe(&davinci_pm_driver, davinci_pm_probe);
}