linux设备注册

本文详细介绍了Linux内核4.9版本中设备注册的过程,以arm64平台为例。首先,根设备及其子设备的注册通过of_platform_default_populate()函数递归创建,检查compatible属性并调用of_device_add()进行注册。接着,分析了i2c设备的注册,从平台设备到i2c适配器的注册,包括i2c控制器设备及其子设备的注册。通过对dts中设备节点的遍历和匹配,完成设备的初始化和注册工作。
摘要由CSDN通过智能技术生成

作为一个linux驱动开发者,大家肯定会写过形形色色的驱动。一般的流程是首先在dts配置设备的相关属性,然后编写相应的driver,基于linux内核device-bus-driver架构,device和driver会在某个时候match上,然后执行driver的probe函数,完成设备的相关初始化工作。如果打开一个项目的dts,会发现里面很多设备节点,那么这些设备是以什么样的原则给注册到系统中呢?

 下文以4.9内核版本,平台为arm64 为例来讲解具体的设备注册过程。

1. 根设备及其子设备的注册

路径:drivers/of/platform.c
static int __init of_platform_default_populate_init(void)
{
        struct device_node *node;

        if (!of_have_populated_dt())
                return -ENODEV;

        /*
         * Handle ramoops explicitly, since it is inside /reserved-memory,
         * which lacks a "compatible" property.
         */
        node = of_find_node_by_path("/reserved-memory");
        if (node) {
                node = of_find_compatible_node(node, NULL, "ramoops");
                if (node)
                        of_platform_device_create(node, NULL, NULL);
        }

        /* Populate everything else. */
        of_platform_default_populate(NULL, NULL, NULL);

        return 0;
}
arch_initcall_sync(of_platform_default_populate_init);

首先单独处理了reserved-memory节点下属性为ramoops的节点,该节点主要用于保存kernel oops信息, 然后接下来调用 of_platform_default_populate()函数来处理剩余的节点。

路径:drivers/of/platform.c
int of_platform_default_populate(struct device_node *root,
                                 const struct of_dev_auxdata *lookup,
                                 struct device *parent)
{
        return of_platform_populate(root, of_default_bus_match_table, lookup,
                                    parent);
}
EXPORT_SYMBOL_GPL(of_platform_default_populate);

int of_platform_populate(struct device_node *root,
                        const struct of_device_id *matches,
                        const struct of_dev_auxdata *lookup,
                        struct device *parent)
{
        struct device_node *child;
        int rc = 0;

        root = root ? of_node_get(root) : of_find_node_by_path("/");
        if (!root)
                return -EINVAL;

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

        for_each_child_of_node(root, child) {
                rc = of_platform_bus_create(child, matches, lookup, parent, true);
                if (rc) {
                        of_node_put(child);
                        break;
                }
        }
        of_node_set_flag(root, OF_POPULATED_BUS);

        of_node_put(root);
        return rc;
}
EXPORT_SYMBOL_GPL(of_platform_populate);

 首先获取root节点的device_node, 在根节点初始化的过程中,root节点即为dts中的"/", 然后一次遍历"/"的子节点,并依次调用of_platform_bus_create函数递归的创建匹配上match的设备及其子设备。

路径:drivers/of/platform.c
static int of_platform_bus_create(struct device_node *bus,
                                  const struct of_device_id *matches,
                                  const struct of_dev_auxdata *lookup,
                                  struct device *parent, bool strict)
{
        const struct of_dev_auxdata *auxdata;
        struct device_node *child;
        struct platform_device *dev;
        const char *bus_id = NULL;
        void *platform_data = NULL;
        int rc = 0;

        /* Make sure it has a compatible property */
        if (strict 
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值