Linux platform总线
文章目录
一、总线概念
在Linux驱动模型中总要关心三个对象:总线
、设备
、驱动
总线指i2c总线、spi总线、usb总线等总线,它们管理着设备和驱动
设备描述了硬件信息
驱动是具体的驱动的实现
当向总线注册设备时,会寻找与之匹配的驱动。反之,当注册驱动时,会寻找与之匹配的设备
使用这种机制可以使得一个驱动程序给多个硬件设备使用,实现了硬件与软件的分离
对于一个设备总要附于某一条总线上,如i2c总线、spi总线、usb总线等,当有的设备如led,并不是接在某一具体的总线上,而内核为了实现总线
、设备
、驱动
这种模型,所以就产生了虚拟总线(platform总线)
二、platform驱动框架详解
2.1 platform驱动框架
platform总线相应的设备和驱动分别为platform_device
和platform_driver
所谓platform_device
并不是和字符设备、块设备、网络设备并列的概念,而是内核提供的一种机制
platform_device结构体定义如下
struct platform_device {
const char *name;
struct device dev;
u32 num_resources;
struct resource *resource;
...
};
name
是platform_device的名称,此名称将会被用于和platform_driver的匹配规则中
dev
表明这是一个设备
resource
描述硬件资源
num_resources
表明resource
所指的数组有几项
注册设备的接口为
int platform_device_register(struct platform_device *);
void platform_device_unregister(struct platform_device *);
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 (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};
platform_driver
中定义了probe、remove等一系列函数,其中的probe函数将在驱动和设备匹配时被调用
driver
表明这是一个驱动,id_table
将用于与platform_device
的匹配规则中
注册驱动的接口为
int platform_driver_register(struct platform_driver *);
void platform_driver_unregister(struct platform_driver *);
platform总线结构体如下
struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
platform总线并不是直接暴露给驱动开发者,它是一个幕后工作者,管理者platform_device
和platform_driver
其中platform_match
定义了设备和驱动的匹配规则
总线维护一个设备链表和一个驱动链表,当注册设备时,会遍历驱动链表,调用总线的匹配规则,如果匹配就调用驱动的probe函数,注册驱动时同理
以上就是platform的驱动框架
2.2 platform_device和platform_driver的匹配规则
对于platform_device和platform_driver的匹配规则,要分析platform_match
函数,这里先给出结论,后头再分析源码
第一种情况
匹配platform_driver
中的id_table数组
元素的name
和platform_device
的name
(字符串匹配)
struct platform_device_id {
char name[PLATFORM_NAME_SIZE];
kernel_ulong_t driver_data
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
struct platform_driver {
...
const struct platform_device_id *id_table;
};
struct platform_device {
const char *