原创kylin_zeng:http://blog.csdn.net/kylin_fire_zeng
平台(platform)总线:
一、Platform总线是linux2.6内核加入的一种虚拟总线。platform机制的本身使用并不
复杂,且Platform 驱动与传统的设备驱动模型相比,优势在于platform机制将设备本身
的资源注册进内核,由内核统一管理,在驱动程序使用这些资源时使用统一的
接口,这样提高了程序的可移植性。由两部分组成:
platform_device和platform_driver
二通过platform机制开发底层设备驱动的流程如图:
platform_device定义 ->platform_device注册 ->platform driver定义 -> platform_driver注册
1)platform_device平台设备 描述:
平台设备使用Struct Platform_device来描述:
struct platform_device
{
const char *name; /*设备名*/
int id; /*设备编号,配合设备名使用*/
struct device dev;
u32 num_resources;
struct resource *resource; /*设备资源*/
}
struct resource
{
resource_size_t start; //资源的起始物理地址
resource_size_t end; //资源的结束物理地址
const char *name; //资源的名称
unsigned long flags; //资源的类型,比如MEM,IO,IRQ类型
struct resource *parent, *sibling, *child;//资源链表指针
}
获取资源:
struct resource *platform_get_resource(struct platform_device
*dev, unsigned int type, unsigned int num)
参数:
dev: 资源所属的设备
type: 获取的资源类型
num: 获取的资源数
例:
platform_get_resource(pdev, IORESOURCE_IRQ, 0)
获取中断号
2)平台设备申请:
Struct Platform_device的分配使用:
struct platform_device *platform_device_alloc(const char *name, int id)
参数:name: 设备名 id: 设备id,一般为-1
3)注册平台设备:
int platform_device_add(struct platform_device *pdev)
二、平台驱动
1)平台驱动使用struct platform_driver 描述:
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; //平台驱动中包含着设备驱动
}
2)平台驱动注册:(及如何去匹配设备和驱动是否对应,对应后怎么执行prope)
平台驱动注册使用函数:
int platform_driver_register(struct platform_driver *)
{
drv->driver.bus=&platform_bus_type //可以知道是哪个总线类型
if(drv->probe)
{
drv->driver.probe=platform_drv_probe;
}
.....
return driver_register(&drv->driver);
}
int driver_register(struct device_driver *drv)
{
....
ret=bus_add_driver(drv); //总线上添加驱动
....
}
int bus_add_driver(struct device_driver *drv)
{
...
if(drv->bus->p->drivers_autoprobe)
{
error=driver_attach(drv);
}
...
}
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus,null,drv,__driver_attach); //总线上的每一个设备都会执行这个
}
static __driver_attach(struct device *dev ,void *data)
{
...
if(drv->bus->match && !drv->bus->match(dev,drv))
return 0; //查找设备和驱动是否对应,不对应则直接返回
...
if(!dev->driver)
{
driver_probe_device(drv,dev); //如果对应则执行probe
}
...
}
int driver_probe_device(struct device_driver *drv ,struct device *dev)
{
...
ret=really_probe(dev,drv);
...
}
static int really_probe(struct device *dev ,struct device_driver *drv)
{
...
ret=drv_probe(dev);//真正驱动中的probe
}
因此当注册一个驱动时,系统会遍历总线上的所有设备,看是否匹配。匹配了才执行prope,
平台总线还有一个match
struct bus_type platform_bus_type=
{
.name="",
.match=platform_match,
....
}
static int platform_match(struct device *dev ,struct device_driver *drv)
{
...
return(Strcmp(pdev->name,drv->name)==0);//驱动和设备示匹配的,能过处理。
}