linux启动初始化步骤(九)----电源管理相关函数

参考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(&notifier_policy_block,
				CPUFREQ_POLICY_NOTIFIER);
	if (ret)
		return ret;

	ret = cpufreq_register_notifier(&notifier_trans_block,
				CPUFREQ_TRANSITION_NOTIFIER);
	if (ret) {
		cpufreq_unregister_notifier(&notifier_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);
}

猜你喜欢

转载自blog.csdn.net/qq_40788950/article/details/84618703