Linux 驱动platform (驱动架构理解)

前言:对于博客,由于能力有限,很多问题都是自己的学习过程和笔记,现在还没有能力说下自己的独特见解;

前面的几个博客都记录了自己对Linux设备驱动的基础知识,但是现实中的Linux驱动不是那个样子的,要复杂的多些。简单的驱动是device 和driver 一对一的结合,但是现实中一种驱动driver可能够被多个device使用,总不能给一个设备单独写一个独特的driver吧,Linux驱动架构出现了platform平台,一般称为虚拟总线。platform就是把device和driver联系起来,实现驱动的重复使用。platform不是一个具体的实物总线,它是虚拟的用来管理设备和多功能的匹配关系的,这点理解很重要。

一、 了解两个结构体:

(1)struct platform_device ,更好的来管理(RTC,LCD等设备);包含struct devicedev;

(2)struct platform_drivver, 更好的管理设备驱动,包含设备驱动结构体struct device_driver driver;

上面的两个结构体是对简单的驱动 device 和driver的更好的封装,增加了更多的属性信息。

注意:platform_driver地位对等的i2c_driver、spi_driver、usb_driver、pci_driver中都包含了device_driver结构体实例成员。它其实描述了各种xxx_driver(xxx是总线名)在驱动意义上的一些共性;

二、Linux的platform把不同的设备和驱动附在了一起,但是要实现特性设备的驱动,是通过1struct bus_type platform_bus_type 的成员match()函数实现的,match函数的功能是实现通过设备树、ACPI、匹配ID表、设备名和驱动的名字四种匹配方法;

三、具体的使用platform_device是在板级支持包BSP文件中注册,int platform_add_devices(struct platform_device **devs, int num);实际上是调用了platform_device_register()函数来注册平台设备。linux3.x之后可以使用设备树注册设备。

四、使用虚拟总线实现设备驱动程序:

我们以globalfifo为例:

(1)probe函数:

static int globalfifo_probe(struct platform_device *pdev)
{
int ret;
dev_t devno = MKDEV(globalfifo_major, 0);

 if (globalfifo_major)
 ret = register_chrdev_region(devno, 1, "globalfifo");
 else {
 ret = alloc_chrdev_region(&devno, 0, 1, "globalfifo");
 globalfifo_major = MAJOR(devno);
 }
 if (ret < 0)
 return ret;

 globalfifo_devp = devm_kzalloc(&pdev->dev, sizeof(*globalfifo_devp),GFP_KERNEL);
 if (!globalfifo_devp) {
 ret = -ENOMEM;
 goto fail_malloc;
 }

 globalfifo_setup_cdev(globalfifo_devp, 0);

 mutex_init(&globalfifo_devp->mutex);
 init_waitqueue_head(&globalfifo_devp->r_wait);
 init_waitqueue_head(&globalfifo_devp->w_wait);
 return 0;

fail_malloc:
     unregister_chrdev_region(devno, 1);
    return ret;
}

(2)remove函数

static int globalfifo_remove(struct platform_device *pdev)
{
     cdev_del(&globalfifo_devp->cdev);
     unregister_chrdev_region(MKDEV(globalfifo_major, 0), 1);

     return 0;
}

(3)platform_driver实现:

static struct platform_driver globalfifo_driver = {
 .driver = {
 .name = "globalfifo",
 .owner = THIS_MODULE,
},
 .probe = globalfifo_probe,
 .remove = globalfifo_remove,
};

module_platform_driver(globalfifo_driver);

(4)platform_device的实现(注意,这个在BSP的平台文件中实现)

static struct platform_device globalfifo_device = {
    .name = "globalfifo",
    3 .id = -1,
};

(5)module_platform_driver()宏所定义的模块加载和卸载函数仅仅通过platform_driver_register()、platform_driver_unregister()函数进行platform_driver的注册与注销。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章