platform _device和platform_driver註冊過程
作者:Dongas
日期:08-06-28
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_probe_device(drv, dev)----->
really_probe(dev, drv)----->
在really_probe()中:爲設備指派管理該設備的驅動:dev->driver = drv, 調用probe()函數初始化設備:drv->probe(dev)