Linux内核设备驱动学习笔记整理(十六)---Linux设备驱动模型与Linux Platfrom平台设备驱动模型

Linux设备驱动模型:

1. struct bus_type 的对象来表示一个总线

   struct device  的对象来表示一个挂在总线上的设备
   struct device_driver 对象来表示一个挂在总线上的设备驱动
总线:
 一个总线可以挂多个设备和多个驱动。
 由总线的match函数来匹配设备对应的驱动, 匹配规则在总线match函数里实现
int (*match)(struct device *dev, struct device_driver *drv)
{
return 1//表示dev与drv匹配上了
return 0//表示不匹配, 总线会继续匹配直到设备与驱动一一对过
}
  
struct bus_type {
.name     //总线名
.match    //匹配函数
   //////
以下函数当总线实现时,不管device_driver里实不实现这些函数,
都会调用总线的这些函数
.probe    //设备探测函数
.remove   //设备移除
.suspend  //省电休眠
.resume   //唤醒
};

bus_register(&mybus);
bus_unregister(&mybus);

如果总线与驱动, 设备不是同一个文件里实的话
则EXPORT_SYMBOL(mybus);

在驱动与设备里
extern struct bus_type mybus;
////////////////////////

void (*release)(struct device *dev);
设备:
struct device {
.init_name  //设备在总线上的名字, 在总线上是唯一的
.bus        //属于哪个总线,指向总线的地址
.release    //设备释放函数, 必须要实现
...
.driver     //如果总线匹配成功后, 此指针指向device_driver对象的地址
};

device_register(&mydev);
device_unregister(&mydev);
//////////////////////
驱动:
struct device_driver {
.name   //驱动在总线上的名字
.bus    //属于哪个总线, 指向总线的地址
.probe  //当总线匹配上时, 驱动探测设备
/////////
.remove //设备移除时触发函数
.suspend //驱动省电的行为
.resume  //驱动恢复工作
};
driver_register(&mydrv);
driver_unregister(&mydrv);
///////////////
匹配过程:

总线的match -->> 驱动的probe

Linux platform 平台设备驱动模型
struct bus_type platform_bus_type = {
.name = "platform",
.match = platform_match,
....
};

static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev;
pdev = container_of(dev, struct platform_device, dev);
return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
}

//match根据平台设备的name与平台驱动的driver成员的name比较, 一致的话则认为匹配成功
//平台设备
<linux/platform_device.h>
struct platform_device {
const char * name; //总线match时使用
int id;     //如多个设备共用一个驱动时, id不能一样
struct device dev;    //dev.platform_data可以挂自定义的数据,
 dev里的release成员要实现
 dev.driver_data也可以挂数据 
u32 num_resources; //多少个资源
struct resource * resource;    //资源对象的始地址
};

///Platform 设备
<linux/ioport.h>
struct resource {
resource_size_t start;   //32bit/64bit数值
resource_size_t end;     //数值
const char *name;       
unsigned long flags;   
struct resource *parent, *sibling, *child;
};

flags:
#define IORESOURCE_IO 0x00000100
#define IORESOURCE_MEM 0x00000200
#define IORESOURCE_IRQ 0x00000400
#define IORESOURCE_DMA 0x00000800

struct resource *platform_get_resource(struct platform_device *dev,
  unsigned int type, unsigned int num)
//获取指定的资源 type为指定flags类型, num为同类型中的第几个资源

int platform_get_irq(struct platform_device *pdev, unsigned int num);
struct resource *platform_get_resource_byname(struct platform_device *dev,
     unsigned int type, char *name)

int platform_device_register(struct platform_device *);
void platform_device_unregister(struct platform_device *);

//Platfrom驱动
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 (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver; //driver里的name用于总线与设备匹配
const struct platform_device_id *id_table;
};

int platform_driver_register(struct platform_driver *);
void platform_driver_unregister(struct platform_driver *);

猜你喜欢

转载自blog.csdn.net/morixinguan/article/details/79783100
今日推荐