platform driver驱动,下面这样的方式是其中一种注册方式, 驱动会注册到形如**__initcall**的段中,然后在start_kernel时进行调用。
static struct platform_driver tegra_ahb_driver = {
.probe = tegra_ahb_probe,
.driver = {
.name = DRV_NAME,
.of_match_table = tegra_ahb_of_match,
.pm = &tegra_ahb_pm,
},
};
module_platform_driver(tegra_ahb_driver);
调用关系如下,在initcall_levels这个结构体中,保存了每个section的起始与结束地址
static initcall_entry_t *initcall_levels[] __initdata = {
__initcall0_start,
__initcall1_start,
__initcall2_start,
__initcall3_start,
__initcall4_start,
__initcall5_start,
__initcall6_start,
__initcall7_start,
__initcall_end,
};
start_kernel
arch_call_rest_init
rest_init
kernel_init
kernel_init_freeable
do_basic_setup
do_initcalls
static void __init do_initcall_level(int level)
{
initcall_entry_t *fn;
strcpy(initcall_command_line, saved_command_line);
parse_args(initcall_level_names[level],
initcall_command_line, __start___param,
__stop___param - __start___param,
level, level,
NULL, &repair_env_string);
trace_initcall_level(initcall_level_names[level]);
for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
do_one_initcall(initcall_from_entry(fn));
}
其中就会调用platform_driver_register,调用关系如下, 最终就会调用之前注册的probe函数,观察probe函数的入参dev,那么dev是什么时候分配的?
platform_driver_register
__platform_driver_register
driver_register
bus_add_driver
driver_attach
bus_for_each_dev
__driver_attach
device_driver_attach
driver_probe_device
driver_probe_device
really_probe
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
以arm64为例,简单过一下通过device tree动态生成device的过程
- 解析设备树
start_kernel
setup_arch
setup_machine_fdt
unflatten_device_tree
__unflatten_device_tree
unflatten_dt_nodes
populate_node
of_node_init
populate_properties
- 生成platform device
of_platform_default_populate_init
of_platform_default_populate
of_platform_populate
of_platform_bus_create
of_platform_device_create_pdata
of_device_alloc
of_device_add
device_add