linux platform设备与驱动

  

174 struct platform_driver {
175     int (*probe)(struct platform_device *);
176     int (*remove)(struct platform_device *);
177     void (*shutdown)(struct platform_device *);
178     int (*suspend)(struct platform_device *, pm_message_t state);
179     int (*resume)(struct platform_device *);
180     struct device_driver driver;
181     const struct platform_device_id *id_table;
182     bool prevent_deferred_probe;
183 };
 259 struct device_driver {
 260     const char      *name;
 261     struct bus_type     *bus;
 262
 263     struct module       *owner;
 264     const char      *mod_name;  /* used for built-in modules */
 265
 266     bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */
 267     enum probe_type probe_type;
 268
 269     const struct of_device_id   *of_match_table;    //device tree通过这个去匹配
 270     const struct acpi_device_id *acpi_match_table;
 271
 272     int (*probe) (struct device *dev);
 273     int (*remove) (struct device *dev);
 274     void (*shutdown) (struct device *dev);
 275     int (*suspend) (struct device *dev, pm_message_t state);
 276     int (*resume) (struct device *dev);
 277     const struct attribute_group **groups;
 278
 279     const struct dev_pm_ops *pm;
 280
 281     struct driver_private *p;
 282 };
 22 struct platform_device {
 23     const char  *name;
 24     int     id;
 25     bool        id_auto;
 26     struct device   dev;
 27     u32     num_resources;
 28     struct resource *resource;
 29
 30     const struct platform_device_id *id_entry;
 31     char *driver_override; /* Driver name to force a match */
 32
 33     /* MFD cell pointer */
 34     struct mfd_cell *mfd_cell;
 35
 36     /* arch specific additions */
 37     struct pdev_archdata    archdata;
 38 };

以上是头文件的结构体定义

129 static const struct of_device_id dw_spi_mmio_of_match[] = {
130     { .compatible = "snps,dw-apb-ssi", },
131     { /* end of table */}
132 };
133 MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
134
135 static struct platform_driver dw_spi_mmio_driver = {
136     .probe      = dw_spi_mmio_probe,
137     .remove     = dw_spi_mmio_remove,
138     .driver     = {
139         .name   = DRIVER_NAME,
140         .of_match_table = dw_spi_mmio_of_match,
141     },
142 };
143 module_platform_driver(dw_spi_mmio_driver);
144
145 MODULE_AUTHOR("Jean-Hugues Deschenes <[email protected]>");
146 MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
147 MODULE_LICENSE("GPL v2");

以前的写法 : 

    struct platform_device s3c_device_usb = {
             .name    = "s3c2410-ohci",  //s3c6410-usb
             .id    = -1,
             .num_resources   = ARRAY_SIZE(s3c_usb_resource),
             .resource   = s3c_usb_resource,
             .dev              = {
                     .dma_mask = &s3c_device_usb_dmamask,
                     .coherent_dma_mask = 0xffffffffUL
                 }
    };  

有了platform_device就可以调用函数platform_add_devices向系统中添加该设备了。系统中的设备资源都可以采用这种方式列举在一起,然后成一个指针数组,如:

static struct platform_device *smdk6410_devices[] __initdata = {

......

 &s3c_device_usbgadget,
 &s3c_device_usb,  //jeff add.

......

}
   static struct platform_driver ohci_hcd_s3c2410_driver = {
         .probe  = ohci_hcd_s3c2410_drv_probe,
         .remove  = ohci_hcd_s3c2410_drv_remove,
         .shutdown = usb_hcd_platform_shutdown,
         /*.suspend = ohci_hcd_s3c2410_drv_suspend, */
         /*.resume = ohci_hcd_s3c2410_drv_resume, */
         .driver  = {
              .owner = THIS_MODULE,
              .name = "s3c2410-ohci",
            },
    };  

(1)在内核初始化时kernel_init()->do_basic_setup()->driver_init()->platform_bus_init()初始化platform_bus(虚拟总线);

(2)设备注册的时候platform_device_register()->platform_device_add()->(pdev->dev.bus = &platform_bus_type)把设备挂在虚拟的platform bus下;

(3)驱动注册的时候platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev(),对每个挂在虚拟的 platform bus的设备作__driver_attach()->driver_probe_device(),判断drv->bus->match()是否存在并且是否执行成功,此时通过指针执行platform_match, 比较strncmp(pdev->name, drv->name, BUS_ID_SIZE),如果相符就调用really_probe(实际就是执行的相应设备的platform_driver->probe(platform_device), 注意platform_drv_probe的_dev参数是由bus_for_each_dev的next_device获得)开始真正的探测加载,如果probe成功则绑定该设备到该驱动。

      当进入probe函数后,需要获取设备的资源信息,根据参数type所指定类型,例如IORESOURCE_MEM,来分别获取指定的资源。
struct resource * platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num);当然,也可以固定资源类型,如获取资源中的中断号:struct int platform_get_irq(struct platform_device *dev, unsigned int num);

      probe函数一般完成硬件设备使能,struct resource的获取以及虚拟地址的动态映射和具体类型设备的注册(因为平台设备只是一种虚拟的设备类型);remove函数完成硬件设备的关闭,struct resource以及虚拟地址的动态映射的释放和具体类型设备的注销。只要和内核本身运行依赖性不大的外围设备 ( 换句话说只要不在内核运行所需的一个最小系统之内的设备 ), 相对独立的拥有各自独自的资源 (addresses and IRQs) ,都可以用platform_driver 实现。如:lcd,usb,uart 等,都可以用platfrom_driver 写,而timer,irq等最小系统之内的设备则最好不用platfrom_driver 机制,实际上内核实现也是这样的。

http://blog.csdn.net/zhandoushi1982/article/details/5130207

http://blog.csdn.net/lichengtongxiazai/article/details/38941997    DT书写规范

http://www.right.com.cn/forum/thread-146260-1-1.html   DT(2) 

时间: 2024-08-03 04:31:03

linux platform设备与驱动的相关文章

Linux Platform设备驱动学习与小结

Platform 设备先被注册然后platfrom驱动加载时会调用驱动程序中的probe()入口函数,扫描系统中已注册的设备,通过.Name域找到匹配设备后将驱动和设备绑定.一个驱动可以对应多个设备,但是一个设备只对一个驱动.Linux下的虚拟总线platform对应设备platform_device,对应的驱动为platform_driver.一个很不恰当的例子:设备好比男人,驱动好比女人,platform作为媒人,将两个对上眼的(name域相同)的相匹配到一起.然后男人(device)到她(

Linux platform设备简介

Technorati 标签: Linux platform     Linux在2.6内核中,针对一系列设备驱动,提供新的管理框架,成为platform机制,推出的目的,在于隔离驱动的资源和实现,使得驱动更加独立,驱动使用的资源统一由内核来管理,这些资源包括驱动所使用的内存地址.中断号等等.     要为不同的驱动程序提供一个框架,首先要抽象出不同驱动所共有的东西,简单来说,驱动程序驱动外部硬件正常工作,一般的,一个硬件外设只能有一个驱动,不同的硬件外设需要不同的驱动程序.对于具有某一类共同功能

linux platform设备驱动之match自动匹配

<span style="font-size:14px;">struct platform_device { // linux/platform_device.h const char * name; int id; struct device dev; u32 num_resources; struct resource * resource; struct platform_device_id *id_entry; /* arch specific additions

二、设备和驱动的注册时序

一.引言 在platform驱动程序框架中,我们了解到,platform设备和驱动最终会挂载在platform总线上,platform总线会对设备和驱动进行匹配.那么设备和驱动是怎么注册到platform框架中去的,其先后顺序又是怎样的? 二.设备和驱动注册 platform_device_register注册设备 1 /** 2 * platform_device_register - add a platform-level device 3 * @pdev: platform device

【linux设备模型】之platform设备驱动

一.platform总线.设备和驱动 platform是一种虚拟总线,对应的设备称为platform_device,对应的驱动称为platform_driver. platform_device定义在<linux/platform_device.h>中: 1 struct platform_device { 2 const char * name; 3 int id; 4 struct device dev; 5 u32 num_resources; 6 struct resource * r

Linux Platform devices 平台设备驱动

设备总线驱动模型:http://blog.csdn.net/lizuobin2/article/details/51570196 本文主要参考:http://www.wowotech.net/device_model/platform_device.html platform平台设备驱动是基于设备总线驱动模型的,它只不过是将 device 进一步封装成为 platform_device,将 device_driver 进一步封装成为 platform_device_driver,前面已经分析过设

linux设备驱动归纳总结(九):1.platform总线的设备和驱动【转】

本文转载自:http://blog.chinaunix.net/uid-25014876-id-111745.html linux设备驱动归纳总结(九):1.platform总线的设备和驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 这一节可以理解是第八章的延伸,从这节开始介绍platform设备驱动. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Linux 设备驱动开发 —— platform设备驱动应用实例解析

前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 -- platform 设备驱动 ,下面将通过一个实例来深入我们的学习. 一.platform 驱动的工作过程 platform模型驱动编程,platform 驱动只是在字符设备驱动外套一层platform_driver 的外壳. 在一般情况下,2.6内核中已经初始化并挂载了一条platform总线在sysfs文件系统中.那么我们编写platform模型驱动时,需要完成两个工作: a -- 实现platform驱动 架构就

PLATFORM设备驱动

字符设备,杂项设备虽然简单,但是在工程中,比如SDK中,通常都使用platform设备驱动来实现硬件驱动,为什么呢?先看看platform设备驱动的结构: platform由两部分组成:设备--platform_device和驱动--platform_driver.它们之间通过platform总线来绑定,这个我们不需要关心,内核里面的东西. platform总线是一个虚拟的总线,跟其他总线(比如:I2C,SPI,USB,PCIE)一样,当系统注册一个设备(platform_device)的时候,