platform _device和platform_driver注册过程

来源:互联网 发布:java前端和后端分离 编辑:程序博客网 时间:2024/04/29 07:55

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_attach(struct device * dev, void * data)----->(此处调用了platform_match函数,做匹配

driver_probe_device(drv, dev)----->
really_probe(dev, drv)----->

在really_probe()中:为设备指派管理该设备的驱动:dev->driver = drv, 调用probe()函数初始化设备:drv->probe(dev)