Device 与 platform device的不同(一)[通俗易懂]

发布时间:2025-12-09 14:16:27 浏览次数:4

Device 与 platform device 在注册方法上有所不同。

Device 注册有两步,platform device注册也有两步,它们第一步相同,都是initialize设备,

但第二步有所不同,Device是直接调用device_add()函数来add设备,而platform device则调用platform_device_add()函数。

实际上,platform_device_add()里面也嵌套了device_add()函数(红色部分),不过在device_add()被调用之前,platform device要先注册它的resources。

就是下面蓝色的部分。

>>>>>>>>>>>>>>>>>>>> device的注册 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

void device_register(struct device *dev)

{

device_initialize(dev);

returndevice_add(dev);

}

>>>>>>>>>>>>>>>>>>>>>>device_register的第一步, 初始化device>>>>>>>>>>>>>>>>>>>>

void device_initialize(struct device *dev)

{

dev->kobj.kset = device_kset;

kboject_init(&dev->kobj, &device_ktype);

INIT_LIST_HEAD(&dev->dma_pools);

mutex_init(&dev->mutex);

lockdep_set_novalidate_class(&dev->mutex);

spin_lock_init(&dev->devres_lock);

INIT_LIST_HEAD(&dev->devres_head);

device_pm_init(dev);

set_dev_node(dev, -1);

}

>>>>>>>>备注: struct device_private *p;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

struct device_private { //hold the private to the driver core portions of the device structure

struct klist klist_children; //containing all children of this device

struct klist_node knode_parent; //node in sibling list

struct klist_node knode_driver; //node in driver list

struct klist_node knode_bus; //node in bus list

void *driver_data; //private pointer for driver specific info.

struct device *device; //pointer back to the struct class that this structure is associated with

}; // Nothing outside of the driver core should ever touch these fields.

>>>>>>>>>>>>>>>>>device_register的第二步, 添加device>>>>>>>>>>>>>>>>>>>>>>>>>

int device_add(struct device *dev)

{

struct device *parent =NULL;

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;

}

/* for statically allocated devices, which should all be converted some day, we need to initialize the name. We prevent reading back the name, and force the use of dev_name() */

if(dev->init_name){

dev_set_name(dev, “%s”, dev->init_name);

dev->init_name =NULL;

}

if(!dev_name(dev)){

error = – EINVAL;

goto name_error;

}

pr_debug(“device: ‘%s’ : %s\n”, dev_name(dev), __func__);

parent = getdevce(dev->parent);

setup_parent(dev, parent);

/*use paent 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 = kboject_add(&dev->kobj, dev->kobj.parent, NULL);

if(error)

goto Error;

//notify platform of device entry

if(platform_notify)

platform_notify(dev);

erro = device_create_file(dev, &uevent_attr);

if(error)

goto attrError;

if(MAJOR(dev->devt)){

error = device_create_file(dev, &devt_attr);

if(error)

goto ueventattrError;

error = device_create_sys_dev_entry(dev);

if(error)

goto devtattrError;

devtmpfs_create_node(dev);

}

error = device_add_class_symlinks(dev);

if(error)

goto SymlinkError;

error =device_add_attrs(dev);

if(error)

goto AttrsError;

error = bus_add_device(dev);

if(error)

goto BusError;

error = dpm_sysfs_add(dev);

if(error)

goto DPMError;

device_pm_add(dev);

//Notify clients of device addtion. This call must come after dpm_sysf_add() and before kobject_uevent().

if(dev->bus)

blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev);

kobject_uevent(&dev->kobj, KOBJ_ADD);

bus_probe_device(dev);

if(parent)

klist_add_tail(&dev->p->knode_parent, &parent->p->klist_children);

if(dev->class){

mutex_lock(&dev->class->p->class_mutex);

//tie the class to the device

klist_add_tail(&dev->knode_class, &dev->class->p->class_devices);

list_for_each_entry(class_intf, &dev->class->p->class_interfaces, node);

if(class_intf->add_dev)

class_intf->add_dev(dev, class_intf);

mutex_unlock(&dev->class->class_mutex);

}

done:

put_device(dev);

return error;

DPMError:

bus_remove_device(dev);

BusError:

device_remove_attrs(dev);

AttrsError:

device_remove_class_syslinks(dev);

SymlinkError:

if(MAJOR(dev->devt))

devtmpfs_delete_node(dev);

if(MAJOR(dev->devt))

device_remover_file(dev, &devt_attr);

ueventattrError:

device_remove_file(dev, &uevent_attr);

attrError:

kobject_uevent(&dev->kobj, KOBJ_REMOVE);

kobject_del(&dev->kobj);

Error:

cleanup_device_parent(dev);

if(parent)

put_device(parent);

name_error:

kfree(dev->p);

dev-> = NULL;

goto done;

}

>>>>>>>>>>>>>>> platform_device 的注册>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

// platform_device_register – add a platform-level device @pdev: platform device we’re adding

int platform_device_register(struct platform_device *pdev)

{

device_initialize(&pdev->dev); //第一步与device完全相同

return platform_device_add(pdev);

}

>>>>>>>>>>>>>>>>>>>platform_device_add()>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

int platform_device_add(struct platform_device *pdev)

{

int i, ret = 0;

if(!pdev)

return -EINVAL;

if(!pdev->dev.parent)

pdev->dev.parent = &platform_bus;

pdev->dev.bus = &platform_bus_type;

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 = -; i < pdev->num_resources; i++){

struct resource *p, *r = &pdev->resource[i];

if( r->name == NULL )

r->name = dev_name(&pdev->dev);

r->name = dev_name(&pdev->dev);

p = r->parent;

if(!p){

if(resource_type(r) == IORESOURCE_MEM)

p = &iomem_resource;

else if (resource_type(r) == IORESOURCE_IO)

p = &ioport_resource;

}

if( p && insert_resource(p, r)){

printk(KERN_ERR “%s: failed to claim resource %d\n”, dev_name(&pdev->dev), i);

ret = -EBUSY;

goto failed;

}

}

pr_debug(“Registering platform device ‘%s’. Parent at %s\n”, dev_name(&pdev->dev), dev_name(pdev->dev.parent));

ret = device_add(&pdev->dev);

if(ret == 0)

return ret;

failed:

while( –i>=0){

struct resource *r = &pdev->resource[i];

unsigned long type = resouce_type(r);

if(type==IORESOURCE_MEM)||type==IORESOURCE_IO)

release_resource(r);

}

return ret;

}

}

需要做网站?需要网络推广?欢迎咨询客户经理 13272073477