平台总线(platform_bus)
当升级平台时,对于相似的设备驱动,需要编写多次驱动代码(没有总线),会造成大量重复的代码,为了高效开发,故引入平台总线。
总线对象
//平台总线对象 不需要自己创建,在内核中已经使用
struct bus_type platform_bus_type = {
.name = "platform",
.dev_groups = platform_dev_groups,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
驱动对象
//驱动对象
struct platform_driver {
int (*probe)(struct platform_device *);//匹配成功后会调用
int (*remove)(struct platform_device *);//移除device设备,会调用
struct device_driver driver;
| const char *name;//驱动对象名字,可以用于匹配
const struct platform_device_id *id_table;//平台描述,可用于与设备之间的匹配
};
平台信息
struct platform_device_id {
char name[PLATFORM_NAME_SIZE];//平台设备名,用于进行匹配
kernel_ulong_t driver_data;
};
设备对象
//设备对象
struct platform_device {
const char *name;//设备对象名,与驱动进行匹配
int id;//一般为-1
struct device dev;//父类对象device
u32 num_resources;//资源个数
struct resource *resource;//资源(地址、中断):设备信息
};
设备资源
struct resource {
resource_size_t start;//开始地址
resource_size_t end;//结束地址
const char *name;
unsigned long flags;//标志,资源为什么类型
struct resource *parent, *sibling, *child;
};
平台总线的匹配:
1、使用platform_driver中的id_table进行匹配,id_table中就是列出支持哪些平台与平台对象名可以用于匹配
2、id_table没有匹配成功,再匹配驱动对象的名字和设备对象的名字
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;
/* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0);
外部程序、驱动、总线、设备之间的执行过程
1、将驱动与设备注册到平台总线上进行一一匹配,匹配成功platform_match函数返回匹配成功标志
2、驱动匹配成功执行probe函数,得到struct platform_device * 匹配的设备对象
3、在probe函数中进行初始化(创建设备号,设备结点,硬件地址映射…)
3、外部程序通过文件io接口const struct file_operations fops;函数通过驱动对设备进行访问、控制