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 <jean-hugues.deschenes@octasic.com>");
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) 

http://blog.csdn.net/zengxianyang/article/details/50732929  DT驱动写法

http://blog.csdn.net/21cnbao/article/details/8457546  DT宋宝华 

http://www.cnblogs.com/dyllove98/archive/2013/07/03/3170178.html 获取DT资源

http://blog.csdn.net/zqixiao_09/article/details/50888795      platform_device字符驱动

原文地址:https://www.cnblogs.com/chencesc/p/6210754.html