设备模型初始化-(02)
文章目录
一、platform_bus_init
linux内核启动过程中使用platform_bus_init()
初始化platform总线(/drivers/base/platform.c),定义如下:
int __init platform_bus_init(void)
{
int error;
early_platform_cleanup();
error = device_register(&platform_bus);
if (error)
return error;
error = bus_register(&platform_bus_type);
if (error)
device_unregister(&platform_bus);
of_platform_register_reconfig_notifier();
return error;
}
第5行代码,使用early_platform_cleanup()
清除早期的platform设备相关的内存。
第7行代码,使用device_register()
注册platform_bus设备,platform_bus
定义如下:
struct device platform_bus = {
.init_name = "platform",
};
EXPORT_SYMBOL_GPL(platform_bus);
第10行代码,使用bus_register()
注册platform_bus总线。platform_bus_type
定义如下:
struct bus_type platform_bus_type = {
.name = "platform",
.dev_groups = platform_dev_groups,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
二、cpu_dev_init
linux内核启动过程中使用cpu_dev_init()
初始化cpu设备,定义如下(/drivers/base/cpu.c):
void __init cpu_dev_init(void)
{
if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
panic("Failed to register CPU subsystem");
cpu_dev_register_generic();
}
上述代码调用subsys_system_register()
将cpu注册到/sys/devices/system/
子系统。cpu_subsys
如下定义:
struct bus_type cpu_subsys = {
.name = "cpu",
.dev_name = "cpu",
.match = cpu_subsys_match,
#ifdef CONFIG_HOTPLUG_CPU
.online = cpu_subsys_online,
.offline = cpu_subsys_offline,
#endif
};
三、memory_dev_init
linux内核中使用memory_dev_init()
初始化内存设备,定义如下(/drivers/base/memory.c):
int __init memory_dev_init(void)
{
unsigned int i;
int ret;
int err;
unsigned long block_sz;
ret = subsys_system_register(&memory_subsys, memory_root_attr_groups);
if (ret)
goto out;
block_sz = get_memory_block_size();
sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
/*
* Create entries for memory sections that were found
* during boot and have been initialized
*/
mutex_lock(&mem_sysfs_mutex);
for (i = 0; i < NR_MEM_SECTIONS; i += sections_per_block) {
err = add_memory_block(i);
if (!ret)
ret = err;
}
mutex_unlock(&mem_sysfs_mutex);
out:
if (ret)
printk(KERN_ERR "%s() failed: %d\n", __func__, ret);
return ret;
}
上述第8行代码,使用subsys_system_register()
向sysfs注册memory
总线。
第12行使用get_memory_block_size()
获取内存的block大小,MIN_MEMORY_BLOCK_SIZE定义如下:
#define MIN_MEMORY_BLOCK_SIZE (1UL << SECTION_SIZE_BITS)
上述宏定义中SECTION_SIZE_BITS
与具体架构相关。在arm
架构下,定义如下(/arch/arm/include/asm/sparsemem.h):
#define SECTION_SIZE_BITS 28
四、container_dev_init
内核中使用container_dev_init()
函数,同样的,调用subsys_system_register()
将container注册到sysfs
中,定义如下(/drivers/base/container.c):
void __init container_dev_init(void)
{
int ret;
ret = subsys_system_register(&container_subsys, NULL);
if (ret)
pr_err("%s() failed: %d\n", __func__, ret);
}
五、of_core_init
linux内核中使用of_core_init(()
函数,进行设备树相关的核心注册,如下定义(/drivers/of/base.c):
void __init of_core_init(void)
{
struct device_node *np;
/* Create the kset, and register existing nodes */
mutex_lock(&of_mutex);
of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
if (!of_kset) {
mutex_unlock(&of_mutex);
pr_err("devicetree: failed to register existing nodes\n");
return;
}
for_each_of_allnodes(np)
__of_attach_node_sysfs(np);
mutex_unlock(&of_mutex);
/* Symlink in /proc as required by userspace ABI */
if (of_root)
proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
}
第7行代码调用kset_create_and_add()
函数创建devicetree对象集,并将其添加到sysfs
中。
第13~14行代码,是对设备树文件进行解析,并将解析出的设备节点逐一添加到sysfs
中。 for_each_of_allnodes
宏定义如下(/include/linux/of.h):
#define for_each_of_allnodes_from(from, dn) \
for (dn = __of_find_all_nodes(from); dn; dn = __of_find_all_nodes(dn))
#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn)