首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

powerpc linux下dts解析过程详解更新

powerpc linux下dts解析过程详解更新

本帖最后由 look_w 于 2017-10-24 15:45 编辑

四. 将allnodes显示在/proc/device-tree目录下start_kernel() -->
#ifdef CONFIG_PROC_FS
proc_root_init(); -->
#endif
#ifdef CONFIG_PROC_DEVICETREE

#endif
proc_device_tree_add_node(root, proc_device_tree);

此时将在/proc/device-tree目录下生成设备节点
# ls -al /proc/device-tree





五. of_platform_bus_type的注册/初始化 -------------------------------------------------------------------
arch/powerpc/kernel/of_platform.c
struct bus_type of_platform_bus_type = {
       .uevent   = of_device_uevent,
};
EXPORT_SYMBOL(of_platform_bus_type);

static int __init of_bus_driver_init(void)
{
   return of_bus_type_init(&of_platform_bus_type, "of_platform");
}
postcore_initcall(of_bus_driver_init);

of_platform_bus_type总线注册完毕。
此时/sys/bus/目录下将会有of_platform


六. 将allnodes设备节点添加到总线of_platform_bus_type
-------------------------------------------------------------------
arch/powerpc/platform/85xx/mpc85Xx_ads.c


static int __init declare_of_platform_devices(void)
{

of_platform_bus_probe(NULL, of_bus_ids, NULL);



return 0;
}
machine_device_initcall(mpc85xx_ads, declare_of_platform_devices);

declare_of_platform_devices() --> of_platform_bus_probe(NULL, of_bus_ids, NULL)

arch/powerpc/kernel/of_platform.c
遍历第一步中在内存中生成链表的所有soc的子节点,将所有的soc子节点设备添加到of_platform总线。
int of_platform_bus_probe(struct device_node *root,

const struct of_device_id *matches,

struct device *parent)
{

struct device_node *child;

struct of_device *dev;

int rc = 0;



if (matches == NULL)

matches = of_default_bus_ids;

if (matches == OF_NO_DEEP_PROBE)

return -EINVAL;

if (root == NULL)

root = of_find_node_by_path("/");

else

of_node_get(root);



pr_debug("of_platform_bus_probe()\n");

pr_debug(" starting at: %s\n", root->full_name);



/* Do a self check of bus type, if there's a match, create

* children

*/

if (of_match_node(matches, root)) {

pr_debug(" root match, create all sub devices\n");

dev = of_platform_device_create(root, NULL, parent);

if (dev == NULL) {

rc = -ENOMEM;

goto bail;

}

pr_debug(" create all sub busses\n");

rc = of_platform_bus_create(root, matches, &dev->dev);

goto bail;

}

for_each_child_of_node(root, child) {

if (!of_match_node(matches, child))

continue;



pr_debug("  match: %s\n", child->full_name);

dev = of_platform_device_create(child, NULL, parent);

if (dev == NULL)

rc = -ENOMEM;

else

rc = of_platform_bus_create(child, matches, &dev->dev);

if (rc) {

of_node_put(child);

break;

}

}
bail:

of_node_put(root);

return rc;
}
EXPORT_SYMBOL(of_platform_bus_probe);
--> of_platform_device_create--> of_device_register() --> device_add()

of_platform总线上的所有设备添加完毕,e0024000.ethernet,e0024520.mdio等设备现在都在总线上。至此设备节点将出现在/sys/devices/platform/













七、实例 1、mdio总线的注册
/driver/net/phy_device.c

subsys_initcall(phy_init)
phy_init --> mdio_bus_init --> bus_register(&mdio_bus_type)

总线注册后,在总线上注册了一个默认的phy的驱动 genphy_driver:

.phy_id      = 0xffffffff,
.phy_id_mask = 0xffffffff,
.name        = "Generic phy",

mdio总线注册完毕。
/sys/bus/mdio


2、 mdio总线上驱动的添加
--------------------------------------------

/driver/net/phy/marvell.c
module_init(marvell_init)
marvell_init() -->
phy_driver_register(&marvell_drivers) -->
driver_register()

前面第三步,注册mdio总线后,已经添加了一个默认的phy的驱动,现在要将所有的phy驱动添加到总线上,这里将所有的marvell的phy都添加。

这步过后,内核的/sys/bus/mdio/driver里面就有了各种phy的驱动,但这时还没有和具体的设备绑定。


3、 of_platform总线上mdio设备驱动(该驱动的目的是在mdio总线上添加phy设备)的添加,并绑定设备:e0024520.mdio和e0025520.mdio
/driver/net/fsl_pq_mdio.c
module_init(fsl_pq_mdio_init)
fsl_pq_mdio_init --> of_register_platform_driver(&fsl_pq_mdio_driver) --> of_register_driver --> driver_register --> bus_add_driver --> driver_attach

遍历整个of_platform总线,寻找与之相匹配的设备,找到e0024520.mdio
driver_attach --> __driver_attach --> driver_match_device
将driver的match_table里的信息和dev_nod中的做比较,若符合就进入driver的probe,也就是fsl_pq_mdio_probe。

现在of_platform总线上的设备e0024520.mdio和e0025520.mdio已经绑定了驱动。
4、 mdio总线上的设备的添加,寻找并绑定相应的驱动。
/driver/net/fsl_pq_mdio.c
fsl_pq_mdio_probe --> of_mdiobus_register --> phy_device_register --> device_register(&phydev->dev) --> device_add --> bus_probe_device --> device_attach -->bus_for_each_drv
扫描mdio总线上的所有的驱动,若找到匹配的,就绑定,并probe。
__device_attach --> driver_probe_device --> really_probe --> phy_probe

将所有的phy和tbi-phy的设备都添加到mdio总线上,并且两个phy设备和两个tbi-phy设备都会根据其自己的phyID找到各自的驱动
返回列表