Platform总线、设备与驱动浅析

来源:互联网 发布:昂飞基因芯片数据分析 编辑:程序博客网 时间:2024/06/15 18:18

什么是platform总线

在linux2.6以后的内核驱动模型中,关心总线、设备、驱动这三块。
总线是连接设备和驱动的,一个设备注册后会通过总线去找驱动,而驱动注册后也会通过总线去找对应的设备。
这种设备模型就需要设备和驱动挂接在一个总线上面,对有实际总线的设备和驱动那是没问题的,但有一些挂接在soc内存空间的外设,则没有对应的总线来挂接,由此引入了platform总线的概念, 即虚拟总线。

platform总线上面的设备和驱动分别是platform_device 和platform_dirver。设备和驱动通过一些特殊的方式进行匹配,下面进行具体代码分析。

platform总线的设备信息

描述设备信息的通常有三种方法:平台文件、模块和设备树,这里以模块方式加载设备信息。
关于设备信息结构体描述在platform_device.h文件中

struct platform_device {    /*一般都是通过名字来匹配的*/    const char  *name;      /*ID是-1的话,则通过过名字来匹配*/    int     id;    bool        id_auto;    /*设备信息*/    struct device   dev;    /*资源信息的大小*/    u32     num_resources;    /*这个结构体里面填充相应的设备资源信息,是一个结构体数组*/    struct resource *resource;    const struct platform_device_id *id_entry;    char *driver_override; /* Driver name to force a match */    /* MFD cell pointer */    struct mfd_cell *mfd_cell;    /* arch specific additions */    struct pdev_archdata    archdata;};

resource结构体填充—>下面只是举的一个例子

struct resource res[]={    [0]={    .start = 0x11,    .end   = 0x22,    .flags = IORESOURCE_MEM,        /*寄存器信息*/    },    [1]={    .start = 0x33,    .end   = 0x44,    .flags = IORESOURCE_MEM,    },    [2]={    .start = 25,    .end   = 25,    .flags = IORESOURCE_IRQ,       /*中断信息*/    },};

一般驱动几个步骤,定义,初始化,注册和释放。上面将设备信息模块的定义与初始化讲完了。
下面说说设备信息模块的注册与释放,同样他们也在platform_device.h文件中。
注册

extern int platform_device_register(struct platform_device *);

释放

extern void platform_device_unregister(struct platform_device *);

platform总线的驱动方法

无论设备信息用何种方式描述,驱动方法都是使用同样的一种套路。驱动方法一般都是以模块的方式加载进内核当中的。
同样驱动方法的编写离不开四大步:定义,初始化,注册和释放。
驱动方法所使用的函数和结构体都在platform_device.h当中。

定义结构体

struct platform_driver {    /*设备的注册和相应的操作在probe中完成*/    int (*probe)(struct platform_device *);    /*设备的注销在remove中完成*/    int (*remove)(struct platform_device *);    void (*shutdown)(struct platform_device *);    int (*suspend)(struct platform_device *, pm_message_t state);    int (*resume)(struct platform_device *);    /*这个结构体重描述设备信息,如名字什么的,总线通过driver结构体的内容进行匹配*/    struct device_driver driver;    const struct platform_device_id *id_table;    bool prevent_deferred_probe;};

当驱动信息对应字符设备时,字符设备的获取设备号及注册的工作在probe里面完成,字符设备的注销在remove里面完成。而相应的模块的注册和模块的注销则还是在init和exit函数中完成。

获取资源
一旦匹配成功,程序就会进入probe当中,在probe中通过获取资源的一些函数操作可以得到相应的设备信息中的内容。

extern struct resource *platform_get_resource(struct platform_device *,                          unsigned int, unsigned int);

举一个实例,对应上面的device中的设备信息

    struct resource * res =NULL;    res = platform_get_resource(dev,IORESOURCE_MEM, 0);    printk("res->start = %#x\n",res->start);    printk("res->end = %#x\n",res->end);    printk("res->flags = %#x\n",res->flags);    /*这里是得到reg信息,然后打印出来*/

注册及注销模块

platform_driver_register(drv)
extern void platform_driver_unregister(struct platform_driver *);

以上也只是platform总线的最基础模块的编写,如果在实际工作中还需要编写对下硬件的操作,对上层提供函数接口的工作。

0 0
原创粉丝点击