为什么platform device匹配驱动后还需要额外注册为misc device?
核心解答
1. 为什么platform匹配完成后仍需注册misc device
首先明确两类设备模型的定位差异:
- platform总线的核心作用是适配SOC上无法自动枚举的内置外设:platform_device负责承载硬件的固定资源(寄存器地址、中断号、时钟、GPIO等),platform_driver负责实现硬件的内核态控制逻辑,二者匹配成功仅代表内核完成了硬件资源和驱动逻辑的绑定,硬件已经在内核态就绪,但此时用户态完全没有途径操作这个设备。
- misc device是字符设备的轻量子类,作用就是为用户态提供标准的操作入口:注册misc设备后,内核会自动生成对应的
/dev/xxx设备节点,用户态可以通过open、read、write、ioctl等通用文件接口和硬件交互,这是用户态访问硬件的必要环节。
二者的作用域完全分离,不存在重复适配的问题。
2. misc device与platform device的绑定逻辑
绑定完全通过驱动自定义的私有数据结构实现,步骤非常固定:
- 驱动预先定义自定义私有结构体,内部同时包含platform设备的资源指针、miscdevice实例、以及硬件运行所需的其他上下文变量。
- 在probe函数中分配该私有结构体的内存,完成platform侧的硬件资源初始化(寄存器映射、中断申请、时钟使能等)后,通过
platform_set_drvdata(pdev, 私有结构体指针)将私有数据和platform设备绑定。 - 初始化miscdevice结构体时,将
.parent字段设置为&pdev->dev,在设备模型中建立父子关联,同时将misc的fops和名称等参数配置完成后调用misc_register完成注册。 - 在misc设备的fops回调中,通过
container_of宏从file的私有数据拿到miscdevice实例,再进一步拿到自定义私有结构体,即可获取到platform侧的所有硬件资源,完成对硬件的操作。
简化代码示例
// 自定义私有结构体,关联两类设备的所有信息 struct my_dev_ctx { struct platform_device *pdev; struct miscdevice mdev; void __iomem *reg_base; int irq; }; static const struct file_operations my_dev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = my_dev_ioctl, // 其他fops回调按需实现 }; static int my_dev_probe(struct platform_device *pdev) { struct my_dev_ctx *ctx; int ret; ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; // 保存platform设备指针,获取硬件资源 ctx->pdev = pdev; ctx->reg_base = devm_platform_ioremap_resource(pdev, 0); ctx->irq = platform_get_irq(pdev, 0); // 此处省略硬件初始化、中断申请等操作 // 初始化misc设备 ctx->mdev.name = "my_hw_dev"; ctx->mdev.minor = MISC_DYNAMIC_MINOR; ctx->mdev.fops = &my_dev_fops; ctx->mdev.parent = &pdev->dev; // 建立父子设备关联 ret = misc_register(&ctx->mdev); if (ret) return ret; platform_set_drvdata(pdev, ctx); return 0; } static long my_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct miscdevice *mdev = filp->private_data; struct my_dev_ctx *ctx = container_of(mdev, struct my_dev_ctx, mdev); // 此处即可通过ctx->reg_base、ctx->irq等资源直接操作硬件 return 0; }
内容的提问来源于stack exchange,提问作者Xingx1
相关产品推荐
相关产品推荐

