linux ------ platform device 与 platform driver

本文详细介绍了 Linux 中 platform bus 的工作原理,包括 platform_device 和 platform_driver 的数据结构、注册流程及开发步骤。platform bus 机制简化了设备资源的管理,并实现了设备与驱动之间的灵活绑定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    从Linux2.6内核起,引入一套新的驱动管理和注册机制:platform_device 和 platform_driver 。Linux 中大部分的设备驱动,都可以使用这套机制,设备用 platform_device 表示;驱动用 platform_driver 进行注册。

    Linux platform driver 机制和传统的device driver机制(即:通过 driver_register 函数进行注册)相比,一个十分明显的优势在于platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序中用使用这些资源时,通过platform device提供的标准接口进行申请并使用。

    platform 是一个虚拟的地址总线,相比 PCI、USB,它主要用于描述SOC上的片上资源。platform 所描述的资源有一个共同点:在CPU 的总线上直接取址。平台设备会分到一个名称(用在驱动绑定中)以及一系列诸如地址和中断请求号(IRQ)之类的资源。

     一. platform 虚拟总线

           系统中为platform总线定义了一个bus_type的实例platform_bus_type, 其代码如下:

           struct bus_type platform_bus_type = {
                     .name  = "platform",                           //platform 总线名称
                     .dev_attrs = platform_dev_attrs,      //platform device 属性
                     .match  = platform_match,               //platform 匹配函数,这个结构的重点
                     .uevent  = platform_uevent,
                     .pm  = &platform_dev_pm_ops,
            };

           处理函数match()表明了platform_device和platform_driver之间如何匹配代码如下:

           static int platform_match(struct device *dev, struct device_driver *drv)
           {
                   struct platform_device *pdev;
                   pdev = container_of(dev, struct platform_device, dev);
                   return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
           }

           匹配platform_device和platform_driver主要看二者的name字段是否相同。

     二. platform device

           1. 数据结构

               struct platform_device {
                       const char * name;             //platform 设备名称
                       int  id;                                     //id表示,如果值为-1表示设备名是唯一的,如果非负值,表示同名字的第几个设备,比如name="a", id=0, 表示设备a/0。
                       struct device dev;                 //一般设备对象,具有一般设备的属性
                       u32  num_resources;           //资源总数
                       struct resource * resource;  //具体资源指针
                       const struct platform_device_id *id_entry;   //platform device ID表
                       struct mfd_cell *mfd_cell;
                       struct pdev_archdata archdata;
               };

               可以把platform devce理解理解为device的一个子类,它具有一般device的特性,只是多了resource管理相关的一些属性,把相关资源注册到内核进行管理。

           2. 相关函数

               (1).  platform_add_devices

                       int platform_add_devices(struct platform_device **devs, int num)
                       {
                              int i, ret = 0;
                              for (i = 0; i < num; i++) {
                                     ret = platform_device_register(devs[i]);
                                     if (ret) {
                                              while (--i >= 0)
                                                      platform_device_unregister(devs[i]);
                                              break;
                                     }
                             }
                             return ret;
                       }

                       该函数的第一个参数为平台设备数组的指针,第二个参数为平台设备的数量,它内部调用了platform_device_register()函 数用于注册单个的平台设备。
                       platform_device的定义通常在BSP的板文件中实现,在板文件中,将platform_device归纳为一个数组,最终通过 platform_add_devices()函数统一注册。platform_add_devices()函数可以将平台设备添加到系统中。

               (2).  platform_device_register

                       int platform_device_register(struct platform_device *pdev)
                      {
                              device_initialize(&pdev->dev);
                              arch_setup_pdev_archdata(pdev);
                              return platform_device_add(pdev);
                      }

                      这个函数调用platform_device_add把platform device加入系统,它跟device_add最主要的区别是多了一步insert_resource(p, r),即将platform资源(resource)添加进内核,由内核统一管理。

     三. platform driver

           1. 数据结构

               struct platform_driver {
                      int (*probe)(struct platform_device *);
                      int (*remove)(struct platform_device *);
                      void (*shutdown)(struct platform_device *);
                      int (*suspend)(struct platform_device *, pm_message_t state);
                      int (*resume)(struct platform_device *);
                      struct device_driver driver;
                      const struct platform_device_id *id_table;
                };

                当platform driver注册成功时,会调用 platform_driver 结构元素 probe 函数指针。

           2. 相关函数

                int platform_driver_register(struct platform_driver *drv)
                {
                      drv->driver.bus = &platform_bus_type;
                      if (drv->probe)
                            drv->driver.probe = platform_drv_probe;
                      if (drv->remove)
                            drv->driver.remove = platform_drv_remove;
                      if (drv->shutdown)
                            drv->driver.shutdown = platform_drv_shutdown;
                      return driver_register(&drv->driver);
                }
                在驱动程序的初始化函数中,调用了platform_driver_register()注册 platform_driver 。需要注意的是:platform_driver 和 platform_device 中的 name 变量的值必须是相同的。这样在 platform_driver_register() 注册时,会将当前注册的 platform_driver 中的 name 变量的值和已注册的所有 platform_device 中的 name 变量的值进行比较,只有找到具有相同名称的 platform_device 才能注册成功。

                 platform_driver_register()的注册过程:
                          1 platform_driver_register(&s3c2410fb_driver)
                          2 driver_register(&drv->driver)
                          3 bus_add_driver(drv)
                          4 driver_attach(drv)
                          5 bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)
                          6 __driver_attach(struct device * dev, void * data)
                          7 driver_probe_device(drv, dev)
                          8 really_probe(dev, drv)
                          在really_probe()中,为设备指派管理该设备的驱动:dev->driver = drv, 调用probe()函数初始化设备:drv->probe(dev)

     四.  platform总线上设备驱动开发步骤

            1. 包含头文件

                 #include <linux/platform_device.h>

            2. 在板文件中初始化 resource 结构变量

                 static struct resource msm_fb_resources[] = {
                         {
                                .flags = IORESOURCE_DMA,
                         }
                 };

            3. 在板文件中初始化 platform_device 结构变量

                 static struct platform_device msm_fb_device = {
                           .name              = "msm_fb",
                           .id                = 0,
                           .num_resources     = ARRAY_SIZE(msm_fb_resources),
                           .resource          = msm_fb_resources,
                           .dev.platform_data = &msm_fb_pdata,
                 };

            4. 向系统注册设备:platform_device_register

                 platform_device_register(&msm_fb_device);

            5. 实现的结构体platform_driver

                 static struct platform_driver msm_fb_driver = {
                        .probe = msm_fb_probe,
                        .remove = msm_fb_remove,
                 #ifndef CONFIG_HAS_EARLYSUSPEND
                        .suspend = msm_fb_suspend,
                        .resume = msm_fb_resume,
                #endif
                        .shutdown = NULL,
                        .driver = {
                                 /* Driver name must match the device name added in platform.c. */
                                 .name = "msm_fb",
                                 .pm = &msm_fb_dev_pm_ops,
                          },
                 };

            6. 调用 platform_driver_register 注册platform driver

                 static int msm_fb_register_driver(void)
                 {
                         return platform_driver_register(&msm_fb_driver);
                 }

 

        Platform device 和 Platform driver实际上是cpu总线可以直接寻址的设备和驱动,他们挂载在一个虚拟的总线platform_bus_type上,是一种bus-specific设备和驱动。与其他bus-specific驱动比如pci是一样的。所有的设备通过bus_id挂在总线上,多个device可以共用一个driver,但是一个device不可以对应多个driver。驱动去注册时候会根据设备名寻找设备,没有设备会注册失败,注册的过程会通过probe来进行相应资源的申请,以及硬件的初始化,如果probe执行成功,则device和driver的绑定就成功了。设备注册的时候同样会在总线上寻找相应的驱动,如果找到他也会试图绑定,绑定的过程同样是执行probe。

         

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值