米尔电子
直播中

杨永胜

11年用户 2379经验值
擅长:嵌入式技术
私信 关注

【Rico Board试用体验】第十篇☞关于设备驱动模型platform设备驱动示例

前些天,把案件驱动改成了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
  71.         {
  72.                 if(0 == strcmp(pt2262_devp->desc ,pt2262_devs[i].desc))
  73.                 {
  74.                         printk(KERN_INFO "pt2262's code is %dtdesc is %sti is %d.n", pt2262_devp->code, pt2262_devp->desc, i);       
  75.                         break;
  76.                 }
  77.                 continue;               
  78.         }
  79.         return IRQ_HANDLED;
  80. }

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

  110. int pt_remove(struct platform_device *plat_pdev)
  111. {
  112.         int i;
  113.         struct pt2262_dev* pt2262_pdev_tmp = plat_pdev->dev.platform_data;
  114.         printk("pt_remove goodbye.n");
  115.         for(i=0; inum_resources; i++)
  116.         {
  117.                 free_irq(plat_pdev->resource[i].start, pt2262_pdev_tmp+i);
  118.                 gpio_free((pt2262_pdev_tmp+i)->gpio);
  119.         }
  120.         return 0;
  121. }


  122. struct platform_driver pt_platform_drv =
  123. {
  124.         .driver =
  125.         {
  126.                 .name = "pt2262",
  127.                 .owner = THIS_MODULE,
  128.         },
  129.         .probe = pt_probe,
  130.         .remove = pt_remove,
  131. };

  132. int __init pt_init(void)
  133. {
  134.         int ret;
  135.         ret = platform_device_register(&pt_platform_dev);       
  136.         ret = platform_driver_register(&pt_platform_drv);       
  137.         return ret;
  138. }
  139. module_init(pt_init);

  140. void __exit pt_exit(void)
  141. {
  142.         platform_driver_unregister(&pt_platform_drv);
  143.         platform_device_unregister(&pt_platform_dev);
  144. }
  145. 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这一项。
0000.PNG



  • 0001.PNG

更多回帖

发帖
×
20
完善资料,
赚取积分