转自:http://blog.chinaunix.net/space.php?uid=20643761&do=blog&id=1594837
platform_device_add最终还是调用老接口device_add,只是多了将resource注册进内核的步骤。
platform_driver_register也是调用driver_register,而且在driver_register中,会调用到driver的probe函数。
platform_device_register()注册过程
------------------------------------
/*
arch/arm/mach-s3c2410/mach-smdk2410.c */
struct platform_device
s3c_device_i2c = {
.name = "s3c2410-i2c",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_i2c_resource),
.resource =
s3c_i2c_resource,
};
/*
*
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); //初始化设备结构
return platform_device_add(pdev); //添加一个片上的设备到设备层
}
/**
* platform_device_add - add a
platform device to device hierarchy
* @pdev: platform device we're
adding
*
* This is part 2 of
platform_device_register(), though may be called
* separately _iff_ pdev was
allocated by platform_device_alloc().
*/
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)
snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d",
pdev->name,
pdev->id); /* 若支持同类多个设备,则用pdev->name和pdev->id在总线上标识该设备 */
else
strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE); /* 否则,用pdev->name(如"s3c2410-i2c")在总线上标识该设备 */
for (i = 0; i <
pdev->num_resources; i++) { /* 遍历资源数,并为各自在总线地址空间请求分配 */
struct resource
*p, *r = &pdev->resource[i];
if (r->name
== NULL)
r->name = pdev->dev.bus_id;
p =
r->parent;
if (!p)
{
if
(r->flags & IORESOURCE_MEM)
p = &iomem_resource; /* 作为IO内存资源分配 */
else
if (r->flags & IORESOURCE_IO)
p = &ioport_resource; /* 作为IO Port资源分配 */
}
if (p && insert_resource(p, r)) { /* 将新的resource插入内核resource tree */
printk(KERN_ERR
"%s: failed to claim resource
%d\n",
pdev->dev.bus_id,
i);
ret =
-EBUSY;
goto
failed;
}
}
pr_debug("Registering
platform device '%s'. Parent at %s\n",
pdev->dev.bus_id,
pdev->dev.parent->bus_id);
ret = device_add(&pdev->dev);
if (ret ==
0)
return
ret;
failed:
while (--i >=
0)
if
(pdev->resource[i].flags &
(IORESOURCE_MEM|IORESOURCE_IO))
release_resource(&pdev->resource[i]);
return
ret;
}
这里发现,添加device到内核最终还是调用的device_add函数。Platform_device_add和device_add最主要的区别是多了一步insert_resource(p,
r)即将platform资源(resource)添加进内核,由内核统一管理。
platform_driver_register()注册过程
--------------------------------------
static struct platform_driver s3c2410_i2c_driver =
{
.probe =
s3c24xx_i2c_probe,
.remove =
s3c24xx_i2c_remove,
.resume =
s3c24xx_i2c_resume,
.driver = {
.owner = THIS_MODULE,
.name = "s3c2410-i2c",
},
};
platform_driver_register(&s3c2410fb_driver)----->
driver_register(&drv->driver)----->
bus_add_driver(drv)----->
driver_attach(drv)----->
bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)----->
__driver_attach(struct device * dev, void * data)----->
driver_probe_device(drv, dev)----->
really_probe(dev, drv)----->
在really_probe()中:为设备指派管理该设备的驱动:dev->driver = drv, 调用probe()函数初始化设备:drv->probe(dev)