文章目录
1.platform总线驱动
1.1设备模型的原理
在Linux内核中所有总线驱动都遵从设备驱动的模型,总线驱动的模型如下图:
内核在设计这些总线驱动模型的时候将一个驱动分为了三个部分device、bus、driver。
device是用来描述硬件设备的,bus是总线用来链接device和driver,driver是用来描述
驱动的对象。在内核中所有的device放在内核的klist_devices的链表中管理,而内核中
所有的driver放在klist_driver中管理。内核中的device和driver通过bus完成关联。
当device和driver匹配成功之后执行驱动的probe函数,在probe函数中就可以完成
操作硬件了。当卸载任何一方驱动的时候都会执行驱动中的remove函数。
1.2platform总线驱动的原理
platform总线驱动遵从设备模型,platform是Linux内核抽象出来的软件代码,并没
有真实的总线协议与之对应。platform总线驱动的思想就是要将设备信息和设备驱动
进行分离。platform_device和platform_driver通过总线匹配成功之后会执行驱动中
probe函数,在probe函数中驱动就能够拿到设备信息。
1.3platform驱动的API
设备端:
1.分配并初始化对象
struct platform_device {
const char *name; //用于匹配的名字
int id; //总线号 PLATFORM_DEVID_AUTO 自动分配总线号
struct device dev; //父类
u32 num_resources; //资源的个数
struct resource *resource; //资源的首地址
};
struct device {
//父类
void (*release)(struct device *dev); //释放资源
}
struct resource {
//设备信息结构体
resource_size_t start; //资源起始值 0x50006000 0xc0008000 71
resource_size_t end; //资源的结束值 0x50006000+3 0xc0008000+30 71
unsigned long flags; //资源的类型 IORESOURCE_IO IORESOURCE_MEM IORESOURCE_IRQ
};
2.注册、注销
platform_device_register(struct platform_device *); //注册
platform_device_unregister(struct platform_device *); //注销
驱动端:
1.分配并初始化对象
struct platform_driver {
int (*probe)(struct platform_device *);
//匹配成功执行的函数
int (*remove)(struct platform_device *);
//分离的时候执行的函数
struct device_driver driver;
//父类
const struct platform_device_id *id_table;
//2.idtable匹配
};
struct device_driver {
const char *name; //1.名字匹配
const struct of_device_id *of_match_table; //3.设备树匹配
}
2.注册、注销
platform_driver_register(drv); //注册
platform_driver_unregister(struct platform_driver *);//注销
3.驱动中一键注册注销的宏
module_platform_driver(__platform_driver)
module_driver(__platform_driver, platform_driver_register,platform_driver_unregister)
#define module_driver(pdrv, __register, __unregister, ...)
static int __init pdrv_init(void)
{
return platform_driver_register(&pdrv );
}
module_init(pdrv_init);
static void __exit pdrv_exit(void)
{
platform_driver_unregister(&pdrv);
}
module_exit(pdrv_exit);
1.4platform按照名字匹配的实例
pdev.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
struct resource res[] = {
[0] = {
.start = 0x12345678,
.end = 0x12345678+49,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 71,
.end = 71,
.flags = IORESOURCE_IRQ,
},
};
void pdev_release(struct device *dev)
{
printk("%s:%d\n",__func__,__LINE__);
}
struct platform_device pdev = {
.name = "hahahaha",
.id = PLATFORM_DEVID_AUTO,
.dev = {
.release = pdev_release,
},
.num_resources = ARRAY_SIZE(res),
.resource = res,
};
static int __init pdev_init(void)
{
return platform_device_register(&pdev);
}
static void __exit pdev_exit(void)
{
platform_device_unregister(&pdev);
}
module_init(pdev_init);
module_exit(pdev_exit);
MODULE_LICENSE("GPL");
pdrv.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
int pdrv_probe(struct platform_device* pdev)
{
printk("%s:%d\n", __func__, __LINE__);
return 0</