微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 第十篇?关于设备驱动模型platform设备驱动示例

第十篇?关于设备驱动模型platform设备驱动示例

时间:10-02 整理:3721RD 点击:
前些天,把案件驱动改成了input子系统,今天学习下platform子系统。
在linux2.6以后的设备驱动模型中,需关心总线、设备和驱动这3个实体。
1.总线:总线将设备和驱动绑定。在系统通过某一总线每注册一个设备的时候,会寻找与之匹配的驱动。同样,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。
总线中重要的结构体是:这个一般不需要我们来操作,系统会把需要的总线初始化好。

  1. struct bus_type {
  2. .
  3. .
  4. const char                *name;
  5. .
  6. .
  7. }

复制代码

2.设备:就是要操作的硬件的描述。

重要的结构体:

  1. struct device {
  2. .
  3. .
  4. struct bus_type        *bus;                /* type of bus device is on */
  5. struct device_driver *driver;        /* which driver has allocated this
  6.                                            device */
  7. void                *platform_data;        /* Platform specific data, device
  8.                                            core doesn't touch it */
  9. .
  10. .

  11. }

复制代码

对应的注册和卸载函数:

  1. device_register(struct device * dev)
  2. device_unregister(struct device * dev)

复制代码


3.设备驱动:具体操作硬件的操作函数。

  1. struct device_driver {
  2. .
  3. .
  4. const char                *name;
  5. struct bus_type                *bus;
  6. int (*probe) (struct device *dev);
  7. int (*remove) (struct device *dev);
  8. .
  9. .
  10. }

复制代码

对应的注册和卸载函数:

  1. driver_register(struct device_driver * drv)
  2. driver_unregister(struct device_driver * drv)

复制代码

-------------------------------------------------------------------------------------------------
本次设计到的platform总线,类似于继承了上述的设备和设备驱动。
设备层对应的重要的数据结构为(我直接实例化了这个数据结构的重要成员变量):

  1. struct  platform_device pt_platform_dev =
  2. {
  3.         .name = "pt2262",
  4.         .resource = pt2262_resource,
  5.         .num_resources = ARRAY_SIZE(pt2262_resource),
  6.         .dev =
  7.         {
  8.                 .platform_data = pt2262_devs,       
  9.                 .release = pt2262_release,
  10.         }
  11. };

复制代码

对应的注册和注销函数

  1. platform_driver_unregister(&pt_platform_drv);
  2. platform_device_unregister(&pt_platform_dev);

复制代码

设备驱动层对应的重要的数据结构为(我也直接实例化了这个数据结构的重要成员变量):

  1. struct platform_driver pt_platform_drv =
  2. {
  3.         .driver =
  4.         {
  5.                 .name = "pt2262",
  6.                 .owner = THIS_MODULE,
  7.         },
  8.         .probe = pt_probe,
  9.         .remove = pt_remove,
  10. };

复制代码

对应的注册和注销函数

  1. ret = platform_driver_register(&pt_platform_drv);
  2. platform_driver_unregister(&pt_platform_drv);

复制代码

以上关于platform部分,我都是从我的代码中直接复制下来的。
完整的代码如下:

  1. #include
  2. #include
  3. #include
  4. #include
  5. #include
  6. #include
  7. #include

  8. #include "pt2262.h"

  9. const int gpio_num[4]={49,60,51,50};

  10. MODULE_LICENSE("GPL");

  11. struct resource pt2262_resource[]=
  12. {
  13.         {
  14.                 .flags = IORESOURCE_IRQ,
  15.         },
  16.         {
  17.                 .flags = IORESOURCE_IRQ,
  18.         },
  19.         {
  20.                 .flags = IORESOURCE_IRQ,
  21.         },
  22.         {
  23. //                .start = gpio_to_irq(gpio_num[3]),
  24. //                .end = gpio_to_irq(gpio_num[3]),
  25.                 .flags = IORESOURCE_IRQ,
  26.         }
  27. };

  28. struct pt2262_dev pt2262_devs[] =
  29. {
  30.         {
  31.                 .desc = "A",
  32.                 .gpio = 49,
  33.                 .code = KEY_A,
  34.         },
  35.         {
  36.                 .desc = "B",
  37.                 .gpio = 60,
  38.                 .code = KEY_B,
  39.         },
  40.         {
  41.                 .desc = "C",
  42.                 .gpio = 51,
  43.                 .code = KEY_C,
  44.         },
  45.         {
  46.                 .desc = "D",
  47.                 .gpio = 50,
  48.                 .code = KEY_D,
  49.         }

  50. };

  51. void        pt2262_release(struct device *dev)
  52. {
  53.         printk(KERN_INFO "pt2262 release func.\n");       
  54. }

  55. struct  platform_device pt_platform_dev =
  56. {
  57.         .name = "pt2262",
  58.         .resource = pt2262_resource,
  59.         .num_resources = ARRAY_SIZE(pt2262_resource),
  60.         .dev =
  61.         {
  62.                 .platform_data = pt2262_devs,       
  63.                 .release = pt2262_release,
  64.         }
  65. };

  66. irqreturn_t pt_irq_handler(int irq, void *pdev)
  67. {       
  68.         struct pt2262_dev * pt2262_devp = (struct pt2262_dev*)pdev;
  69.         int i;
  70.         for(i=0; i desc ,pt2262_devs[i].desc))
  71.                 {
  72.                         printk(KERN_INFO "pt2262's code is %d\tdesc is %s\ti is %d.\n", pt2262_devp->code, pt2262_devp->desc, i);       
  73.                         break;
  74.                 }
  75.                 continue;               
  76.         }
  77.         return IRQ_HANDLED;
  78. }

  79. int pt_probe(struct platform_device *plat_pdev)
  80. {
  81.         int i,j,ret;
  82.         char buf[16];
  83.         struct pt2262_dev* pt2262_pdev_tmp = plat_pdev->dev.platform_data;
  84.         for(i=0; i num_resources; i++)
  85.         {
  86.                 //j = plat_pdev->dev.platform_data
  87.                 j = pt2262_pdev_tmp[i].gpio;
  88.                 sprintf(buf, "pt_gpio_%d", j);
  89.                 ret = gpio_request(j, buf);
  90.                 if(ret resource)+i)->start = gpio_to_irq(j);
  91.                 ((plat_pdev->resource)+i)->end = gpio_to_irq(j);
  92.                 ret = request_irq(((plat_pdev->resource)+i)->start,pt_irq_handler,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"pt_irq_handler", pt2262_pdev_tmp+i);
  93.                 if(ret num_resources);
  94.         return ret;
  95. fail:
  96.         printk(KERN_ERR "failed to request %s\n",buf);
  97.         return ret;
  98. fail2:
  99.         printk(KERN_ERR "failed to request irq %s\n",buf);
  100.         return ret;
  101. }

  102. int pt_remove(struct platform_device *plat_pdev)
  103. {
  104.         int i;
  105.         struct pt2262_dev* pt2262_pdev_tmp = plat_pdev->dev.platform_data;
  106.         printk("pt_remove goodbye.\n");
  107.         for(i=0; i num_resources; i++)
  108.         {
  109.                 free_irq(plat_pdev->resource[i].start, pt2262_pdev_tmp+i);
  110.                 gpio_free((pt2262_pdev_tmp+i)->gpio);
  111.         }
  112.         return 0;
  113. }


  114. struct platform_driver pt_platform_drv =
  115. {
  116.         .driver =
  117.         {
  118.                 .name = "pt2262",
  119.                 .owner = THIS_MODULE,
  120.         },
  121.         .probe = pt_probe,
  122.         .remove = pt_remove,
  123. };

  124. int __init pt_init(void)
  125. {
  126.         int ret;
  127.         ret = platform_device_register(&pt_platform_dev);       
  128.         ret = platform_driver_register(&pt_platform_drv);       
  129.         return ret;
  130. }
  131. module_init(pt_init);

  132. void __exit pt_exit(void)
  133. {
  134.         platform_driver_unregister(&pt_platform_drv);
  135.         platform_device_unregister(&pt_platform_dev);
  136. }
  137. module_exit(pt_exit);

复制代码

还有一个头文件pt2262.h:

  1. #ifndef __PT2262_H__
  2. #define __PT2262_H__

  3. struct pt2262_dev
  4. {
  5.         char desc[8];
  6.         int gpio;
  7.         int code;
  8. };

  9. #endif

复制代码

安装之后的效果如下图:
/sys/bus/platform/drivers目录下多出来pt2262这一项。




Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top