设备模型:
1、平台设备结构体:platform_device,通过platform_device_register注册,通过platform_device_unregister卸载;
2、平台驱动结构体:platform_driver,通过platform_driver_register注册,通过platform_driver_unregister卸载;
3、平台总线结构体:platform_bus_type。
总线的重要性:总线存在两条链表,一条是驱动链表bus_type->p->klist_drivers,一条设备链表bus_type->p->klist_devices,还有一个设备驱动匹配函数指针match。
所以很容易理解(一般情况下):
注册平台驱动做什么事情?platform_driver_register
1、把驱动放到平台总线的驱动链表;
2、从平台总线的设备链表逐个取出设备,和驱动进行匹配,如果匹配成功,就调用驱动的probe函数;
注册平台设备做什么事情?platform_device_register
1、把设备放到平台总线的设备链表;
2、从平台总线的设备链表逐个取出驱动,和设备进行匹配,如果匹配成功,就调用驱动的probe函数;
代码具体如下:
platform_driver_register
drv->driver.bus = &platform_bus_type;
drv->driver.probe = platform_drv_probe;//实际就是驱动的probe函数,参数是对应设备
driver_register(&drv->driver);
ret = bus_add_driver(drv); //把驱动放到总线的驱动链表
if (drv->bus->p->drivers_autoprobe){ //bus->p->drivers_autoprobe在平台总线初始化时候已经设为1
error = driver_attach(drv);
while ((dev = next_device(&i)) && !error) //遍历总线的设备链表
__driver_attach
driver_match_device(drv, dev) //匹配设备和驱动,调用总线的匹配函数
driver_probe_device(drv, dev); //匹配成功调用驱动的probe函数
同理:
platform_device_register
platform_device_add;
pdev->dev.bus = &platform_bus_type;
device_add(&pdev->dev)
bus_probe_device
error = bus_add_device(dev); //设备放到总线的设备链表
device_attach(dev); //这个和前面的一样
平台总线的匹配函数实现原理:
platform_match
of_driver_match_device
platform_match_id //第一种匹配:根据名字
strcmp(pdev->name, id->name) //通过驱动的id_table的name和设备的name比较
of_driver_match_device(dev, drv) //另外一种匹配
平台设备如何编写:
1、设置资源:
static struct resource dm9000_resources[] = {
[0] = {
.start = S3C64XX_PA_DM9000,
.end = S3C64XX_PA_DM9000 + 3,
.flags = IORESOURCE_MEM, //寄存器范围
},
。。。。。。
[2] = {
.start = IRQ_EINT(7),
.end = IRQ_EINT(7),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, //中断号
},
};
2、设置平台设备
static struct platform_device s3c_device_dm9000 = {
.name = "dm9000",
.id = 0,
.num_resources = ARRAY_SIZE(dm9000_resources),
.resource = dm9000_resources,
.dev = {
.platform_data = &dm9000_setup,
} s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
};
3、注册平台设备:
platform_add_devices函数
平台驱动:
1、设置平台驱动结构体
static struct platform_driver dm9000_driver = {
.driver = {
.name = "dm9000",
.owner = THIS_MODULE,
},
.probe = dm9000_probe,
};
2、注册平台驱动
platform_driver_register(&dm9000_driver);
3、已注册就会匹配平台设备,匹配成功就调用probe函数 dm9000_probe,在该函数重要功能:
获取平台设备的寄存器资源;
获取平台设备的中断号,并且注册中断
获取平台设备的私有数据。