linux平台总线模型
什么是平台总线模型: 是linux系统虚拟出来的总线, 没有对应的硬件接口
平台总线模型将一个驱动分成了两个部分
device.c
: 描述硬件资源代码, 描述寄存器的地址, 中断号
driver.c
: 控制硬件的驱动代码, 操作寄存器, 处理中断
这两个部分通过相同的name
进行匹配
为什么要使用平台总线, 平台总线的优点
不同的处理器的相同功能的寄存器不在一个位置, 但是使用驱动可以是同一套
- 减少编写的重复代码, 提高效率
- 提高代码的利用率
注册平台设备
device.c描述的硬件资源是
硬件的寄存器的地址, 中断号, 和其他硬件资源
使用下面的结构体描述
struct platform_device {
// 名字, 和driver匹配, 可以在sys目录下看到
const char *name;
// 区分不同的设备, sys目录下的设备文件的后缀(-1无后缀)
int id;
bool id_auto; // 自动设置id, 一般不用
// 设备的通用属性部分, 必须实现里面的release函数
struct device dev;
u64 platform_dma_mask;
struct device_dma_parameters dma_parms;
// 存储资源的个数
u32 num_resources;
// 存放硬件资源的结构体
struct resource *resource;
const struct platform_device_id *id_entry;
const char *driver_override;
/* MFD cell pointer */
struct mfd_cell *mfd_cell;
/* arch specific additions */
struct pdev_archdata archdata;
};
描述硬件资源的结构体
// linux-master/include/linux/ioport.h
struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
unsigned long desc;
struct resource *parent, *sibling, *child;
};
- start/end: 资源的起始信息和终止信息, 比如寄存器的起始地址和终止地址
- flags: 硬件资源信息的类型, 在
include/linux/ioport.h
路径下列举
硬件资源举例
static struct resource my_device_resources[] = {
[0] = {
.start = 0xFDD60000,
.end = 0xFDD60004,
.flags = IORESOURCE_MEM, // 内存类型或寄存器
},
[1] = {
.start = 13,
.end = 13,
.flags= IORESOURCE_IRQ, // 中断类型
},
};
platform设备加卸载函数: 把设备加载到总线上
int platform_device_register(struct platform_device *pdev)
void platform_device_unregister(struct platform_device *pdev)
注册平台驱动
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;
bool prevent_deferred_probe;
bool driver_managed_dma;
};
- probe: 必须实现, 当设备和驱动匹配成功之后, 自动执行
- remove: 移出一个设备的时候执行
- shutdown: 电源管理, 关掉设备时执行
- suspend: 电源管理, 挂起时执行
- resume: 电源管理, 恢复时执行
- driver: 设备共用的一些属性
- id_table: 设备的ID表
platform驱动加卸载函数
const struct platform_device_id mydriver_id_table = {
.name = "mydevice",
};
struct platform driver platform driver test ={
.probe = mydriver_probe,
.remove =mydriver_remove,
.driver = {
.name ="mydevice",
.owner = THIS_MODULE,
}
// id_table的优先级大于drive中的name
.id_table = &mydriver_id_table,
}
int platform_driver_register(struct platform_driver *drv, struct module *owner)
void platform_driver_unregister(struct platform_driver *drv);
设备和驱动的匹配方法
平台设备和驱动的匹配方法
- 先通过platform_driver中的id_table
- 如果id_table不存在,则只是简单的比较设备中的name字段和驱动中的name字段是否相同
static int platform_match(struct device *dev, struct device_driver *drv)
{
...
/* Then try to match against the id table */
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);
}
获取设备资源
获取设备资源的函数
platform_get_resource: 返回设备指定类型的第num个资源
struct resource *platform_get_resource(struct platform_device *dev,
unsigned int type, unsigned int num)
{
u32 i;
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
if (type == resource_type(r) && num-- == 0)
return r;
}
return NULL;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 本地部署 DeepSeek:小白也能轻松搞定!
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
· 我们是如何解决abp身上的几个痛点
· 如何基于DeepSeek开展AI项目