dev = of_device_alloc(np, bus_id, parent); // alloc设备, 设备初始化. 返回dev, 所有的设备都可认为是platform_device, 跳到3-1-1-1看看函数做了什么事情
if (!dev)
return NULL;
#if defined(CONFIG_MICROBLAZE)
dev->archdata.dma_mask = 0xffffffffUL;
#endif
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); // dev->dev 是 struct device. 继续初始化
dev->dev.bus = &platform_bus_type; //
dev->dev.platform_data = platform_data;
printk("[%s %s %d] of_device_add(device register) np->name = %s\n", __FILE__, __func__, __LINE__, np->name);
if (of_device_add(dev) != 0) { // 注册device, of_device_add(...) --> device_add(...) // This is part 2 of device_register()
platform_device_put(dev);
return NULL;
}
3-1-1-1. drivers/of/platform.c : of_device_alloc(...)
1) alloc platform_device *dev
2) 如果有reg和interrupts的相关属性, 运行of_address_to_resource 和 of_irq_to_resource_table, 加入到dev->resource
dev->num_resources = num_reg + num_irq;
dev->resource = res;
for (i = 0; i < num_reg; i++, res++) {
rc = of_address_to_resource(np, i, res);
/* printk("[%s %s %d] res->name = %s, res->start = 0x%X, res->end = 0x%X\n", __FILE__, __func__, __LINE__, res->name, res->start, res->end); */
WARN_ON(rc);
}
WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
3) dev->dev.of_node = of_node_get(np);
// 这个node属性里有compatible属性, 这个属性从dts来, 后续driver匹配device时, 就是通过这一属性进匹配
// 我们可以通过添加下面一句话来查看compatible.
// printk("[%s %s %d] bus->name = %s, of_get_property(...) = %s\n", __FILE__, __func__, __LINE__, np->name, (char*)of_get_property(np, "compatible", NULL));
// node 再给dev, 后续给驱动注册使用.
4) 运行 of_device_make_bus_id 设定device的名字, 如: soc.2 或 ac000000.serial 等
3-2-1. drivers/of/platform.c :
以 compatible = "simple-bus"的节点的子节点都会以这个节点作为父节点在这步注册设备.
这是实际的板载设备, 也是最终目的.