内核中的 platform总线

    一个现实的Linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI、USB、I2C、SPI 等的设备而言,这自然不是问题,但是在嵌入式系统里面,SoC 系统中集成的独立的外设控制器、挂接在SoC 内存空间的外设等确不依附于此类总线。基于这一背景,Linux 发明了一种虚拟的总线,称为platform 总线
        SOC系统中集成的独立外设单元(I2C,LCD,SPI,RTC等)都被当作平台设备来处理,而它们本身是字符型设备。
        从Linux2.6内核起,引入一套新的驱动管理和注册机制:platform_device 和 platform_driver 。Linux 中大部分的设备驱动,都可以使用这套机制,设备用 platform_device 表示;驱动用platform_driver 进行注册

      

一.platform_device

    在2.6内核中platform设备用结构体platform_device来描述,

    该结构体定义在kernelincludelinuxplatform_device.h中,
    

    struct platform_device {

           const char      * name;  //名

           int           id;    

           struct device   dev;      //内嵌设备

           u32         num_resources;   //资源个数

           struct resource       * resource;   //资源结构体

           struct platform_device_id      *id_entry;

           struct pdev_archdata     archdata;

    };

 

 在使用platform设备之前需要注册和使用完之后需要注销:platform_driver 的注册与注销:

     platform_driver_register()
     platform_driver_unregister()

    device文件模块代码:

      

  1 #include <linux/init.h>
  2 #include <linux/thread_info.h>
  3 #include <linux/module.h>
  4 #include <linux/sched.h>
  5 #include <linux/errno.h>
  6 #include <linux/kernel.h>
  7 #include <linux/module.h>
  8 #include <linux/slab.h>
  9 #include <linux/input.h>
 10 #include <linux/init.h>
 11 #include <linux/serio.h>
 12 #include <linux/delay.h>
 13 #include <linux/clk.h>
 14 #include <linux/miscdevice.h>
 15 #include <linux/io.h>
 16 #include <linux/ioport.h>
 17 #include <linux/vmalloc.h>
 18 #include <linux/dma-mapping.h>
 19 #include <linux/export.h>
 20 #include <linux/gfp.h>
 21 #include <linux/cdev.h>
 22 
 23 #include <asm/dma-mapping.h>
 24 #include <asm/uaccess.h>
 25 
 26 #include <linux/gpio.h>
 27 #include <mach/gpio.h>
 28 #include <plat/gpio-cfg.h>
 29 #include <linux/completion.h>
 30 #include <linux/miscdevice.h>
 31 #include <linux/platform_device.h>
 32 
 33 MODULE_LICENSE("GPL");
 34 MODULE_AUTHOR("bunfly");
 35 
 36 void test_release(struct device *dev)
 37 {
 38 }
 39 
 40 struct platform_device  test_device = {
 41     .name = "test_platform",
 42     .dev = {
 43         .release =  test_release,
 44     },
 45 };
 46 
 47 int test_init(void)
 48 {
 49     printk("device had regiser!
");
 50     return platform_device_register(&test_device);
 51     //注册platform设备
 52 }
 53 
 54 void test_exit(void)
 55 {
 56     platform_device_unregister(&test_device);
 57 }
 58 
 59 module_init(test_init);
 60 module_exit(test_exit);
 61 
~                                                                                                                                                                                                            
~                                                                                                                                                                                                            
~                                                                                                                                                                                                            
~                                                                                                                                                                                                            
~     

二.paltform_driver

     platform_driver 结构体     在  include/linux/platform_device.h目录下

    

    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;        //内嵌设备驱动

           struct platform_device_id *id_table;  //驱动支持项

      };

    其中,比较重要的就是probe和remove函数。

    driver代码如下:

      

 1 #include <linux/init.h>
  2 #include <linux/thread_info.h>
  3 #include <linux/module.h>
  4 #include <linux/sched.h>
  5 #include <linux/errno.h>
  6 #include <linux/kernel.h>
  7 #include <linux/module.h>
  8 #include <linux/slab.h>
  9 #include <linux/input.h>
 10 #include <linux/init.h>
 11 #include <linux/serio.h>
 12 #include <linux/delay.h>
 13 #include <linux/clk.h>
 14 #include <linux/miscdevice.h>
 15 #include <linux/io.h>
 16 #include <linux/ioport.h>
 17 #include <linux/vmalloc.h>
 18 #include <linux/dma-mapping.h>
 19 #include <linux/export.h>
 20 #include <linux/gfp.h>
 21 #include <linux/cdev.h>
 22 
 23 #include <asm/dma-mapping.h>
 24 #include <asm/uaccess.h>
 25 
 26 #include <linux/gpio.h>
 27 #include <mach/gpio.h>
 28 #include <plat/gpio-cfg.h>
 29 #include <linux/completion.h>
 30 #include <linux/miscdevice.h>
 31 #include <linux/platform_device.h>
 32 
 33 MODULE_LICENSE("GPL");
 34 MODULE_AUTHOR("bunfly");
 35 
 36 
 37 
 38 int myopen(struct inode *no, struct file *fp)
 39 {
 40     return 0;
 41 }
 42 
 43 int myrelease(struct inode *no, struct file *fp)
 44 {
 45     return 0;
 46 }
 47 
 48 
 49 int mywrite(struct file *fp, char *buf, int size, int *off)
 50 {
 51 
 52     printk("KERNEL: write....
");
 53 
 54     return 0;
 55 }
 56 
 57 int myread(struct file *fp, char *buf, int size, int *off)
 58 {
 59 
 60     return 0;
 61 }
 62 
 63 struct file_operations  myfops = {
 64     .open = myopen,
 65     .release = myrelease,
 66     .write = mywrite,
 67     .read = myread,
 68 };
 69 
 70 struct miscdevice  mymisc = {
 71     .minor = 22,
 72     .name = "mymisc",
 73     .fops = &myfops,
 74 };
 75 
 76 int test_probe(struct platform_device *pdev)
 77 {
 78     int ret = 0;
 79     misc_register(&mymisc);
 80     printk("match sucessed!
");
 81     return 0;
 82 }
 83 //注册设备驱动
 84 int test_remove(struct platform_device *pdev)
 85 {
 86     misc_deregister(&mymisc);
 87     return 0;
 88 }
 89 
 90 struct platform_driver  test_driver = {
 91     .driver = {
 92             .owner = THIS_MODULE,
 93             .name = "test_platform",
 94     },
 95     .probe = test_probe,
 96     .remove = test_remove,
 97 };
 98 int test_init(void)
 99 {
100     return platform_driver_register(&test_driver);
101     //驱动注册
102 }
103 
104 void test_exit(void)
105 {
106     platform_driver_unregister(&test_driver);
107     //驱动注销
108 }
109 
110 module_init(test_init);
111 module_exit(test_exit);
112 

三.platform 匹配

    platform通过device和driver的name名字来匹配,所以,device和driver的name一定要一样才可以匹配成功,当匹配成功之后,就会到驱动的probe函数里面区探测设备;

     起到的左右大概是:

      

    在这里,我们先插入driver模块,再插入device模块,可以在   

            /sys/bus/platform/devices/目录下查看到设备的插入情况:

    

        

    接下来:插入driver模块:

    

    发现,插入驱动模块的时候,自动调用了probe函数,打印出了里面的一句话;

 总结:

      platform总线是虚拟总线,通过name,起到platform_device和platform_driver的匹配工作

   ,当匹配成功之后就会调用driver里面的probe函数添加设备!          

原文地址:https://www.cnblogs.com/hongzhunzhun/p/4539306.html