platform_device_rigister()过程追踪

2021-09-15  本文已影响0人  小可_34e0

参考:https://my.oschina.net/felixliang/blog/80960

void __init bcm2708_init(void)
{
 ...
    bcm_register_device(&bcm2708_bsc0_device);
    bcm_register_device(&bcm2708_bsc1_device);
...
}

int __init bcm_register_device(struct platform_device *pdev)
{
  ...
    ret = platform_device_register(pdev);
   ...
}

int platform_device_register(struct platform_device *pdev)
{
   ...
    return platform_device_add(pdev);
}

int platform_device_add(struct platform_device *pdev)
{
   ...
    pdev->dev.bus = &platform_bus_type;              //platform设备的总线类型是platform_bus

    if (pdev->id != -1)                                                     //设置设备名
        dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
    else
        dev_set_name(&pdev->dev, "%s", pdev->name);

    for (i = 0; i < pdev->num_resources; i++) {         //配置设备资源,非常重要,这里略过
        ...
    }

  ...

    ret = device_add(&pdev->dev);
   ....
}
int device_add(struct device *dev)
{
    struct device *parent = NULL;
    struct kobject *kobj;
    struct class_interface *class_intf;
    int error = -EINVAL;

    dev = get_device(dev);
    if (!dev)
        goto done;

    if (!dev->p) {
        error = device_private_init(dev);
        if (error)
            goto done;
    }

    ...

   /*在sysfs添加设备目录和属性文件*/

    parent = get_device(dev->parent);
    kobj = get_device_parent(dev, parent);
    if (kobj)
        dev->kobj.parent = kobj;

    /* use parent numa_node */
    if (parent)
        set_dev_node(dev, dev_to_node(parent));

    /* first, register with generic layer. */
    /* we require the name to be set before, and pass NULL */
    error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); //建立设备在sysfs下的目录
    if (error)
        goto Error;

    /* notify platform of device entry */
    if (platform_notify)
        platform_notify(dev);

    error = device_create_file(dev, &uevent_attr);             //添加uevent属性
    if (error)
        goto attrError;

    if (MAJOR(dev->devt)) {
        error = device_create_file(dev, &devt_attr);          //添加dev属性

       ...

    }

    error = device_add_class_symlinks(dev);                 //在目录sys/class/ 建立设备连接? 
    if (error)
        goto SymlinkError;
    error = device_add_attrs(dev);                                 //添加设备的所属class、type提供的设备属性?
    if (error)
        goto AttrsError;
    error = bus_add_device(dev);                                  //将设备添加到总线中

    if (error)
        goto BusError;
   ...
}
int bus_add_device(struct device *dev)
{
    struct bus_type *bus = bus_get(dev->bus);
    int error = 0;

    if (bus) {
        pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
        error = device_add_attrs(bus, dev);            //添加设备所属bus提供的设备属性
        if (error)
            goto out_put;
      ...
        klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices); //将设备添加到总线设备链表中
    }
    return 0;
 ...
}

/*

* bus->p->klist_devices 是连接 driver和device的桥梁。

*/

补充
关于kobject:object是Linux设备模型的基础结构,其地位类似于面向对象中的基类,通过派生出其他的类来丰富Linux设备模型的结构,如device、kset等。具体方法就是将kobject结构嵌入到上层的数据结构中,这样如果使用了该上层结构,只要访问kboject成员就可以获得kboject结构。
参考:https://www.cnblogs.com/helloahui/p/3677192.html
非常棒的kobject add分析:https://blog.csdn.net/qq_15715753/article/details/104966257

上一篇下一篇

猜你喜欢

热点阅读