【发布时间】:2019-08-22 02:51:55
【问题描述】:
如何将 alloc_chrdev_region 和 cdev_add 与平台驱动程序的探测功能分开,以便启动同一设备的多个实例?在哪里可以访问具有类似功能的相关平台驱动示例代码?
我有 4 个以相同方式工作的实例化设备。 通常我使用平台驱动来操作我的设备,但我的代码只能用.ko和insmod命令启动1个实例化设备,而不是同一设备的多个实例。
我试图重写我的代码。发现platform_driver的probe函数包括alloc_chrdev_region和cdev_add。我不知道如何将alloc_chrdev_region和cdev_add函数与platform_driver的probe函数分开。
以下代码是我设备的设备树:
mipi_csi2_rx_v_cap_pipeline_0: v_cap_pipeline@a0030000 {
compatible = "xlnx,v-cap-pipeline-1.0";
interrupt-names = "interrupt";
interrupt-parent = <&gic>;
interrupts = <0 104 4>;
reg = <0x0 0xa0030000 0x0 0x4000>;
xlnx,s-axi-chn-mst-num = <0x2>;
};
mipi_csi2_rx_v_cap_pipeline_1: v_cap_pipeline@a0034000 {
compatible = "xlnx,v-cap-pipeline-1.0";
interrupt-names = "interrupt";
interrupt-parent = <&gic>;
interrupts = <0 105 4>;
reg = <0x0 0xa0034000 0x0 0x4000>;
xlnx,s-axi-chn-mst-num = <0x2>;
};
mipi_csi2_rx_v_cap_pipeline_2: v_cap_pipeline@a0038000 {
compatible = "xlnx,v-cap-pipeline-1.0";
interrupt-names = "interrupt";
interrupt-parent = <&gic>;
interrupts = <0 106 4>;
reg = <0x0 0xa0038000 0x0 0x4000>;
xlnx,s-axi-chn-mst-num = <0x2>;
};
mipi_csi2_rx_v_cap_pipeline_3: v_cap_pipeline@a003c000 {
compatible = "xlnx,v-cap-pipeline-1.0";
interrupt-names = "interrupt";
interrupt-parent = <&gic>;
interrupts = <0 107 4>;
reg = <0x0 0xa003c000 0x0 0x4000>;
xlnx,s-axi-chn-mst-num = <0x2>;
};
以下示例代码是我的平台驱动程序的探测功能:
static int fstream_probe(struct platform_device *pdev) {
struct device *dev = &pdev->dev;
dev_t devno = MKDEV(fstream_major, 0);
ret = alloc_chrdev_region(&devno, 0, DEV_NUM, DRIVER_NAME);
fstream_major = MAJOR(devno);
cdevp = (struct fstream_cdev *) kzalloc(sizeof(struct fstream_cdev)*DEV_NUM, GFP_KERNEL);
fstream_setup_cdev(cdevp);
...
/* others ignored */
PDEBUG(" init success\n");;
}
static struct of_device_id fstream_of_match[] = {
{.compatible = "xlnx,v-cap-pipeline-1.0", },
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(of, fstream_of_match);
static struct platform_driver fstream_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = fstream_of_match,
},
.probe = fstream_probe,
.remove = fstream_remove,
};
static int __init fstream_init(void) {
return platform_driver_register(&fstream_driver);
}
module_init(fstream_init);
当我的代码中的探测函数被调用 4 次时,在 /proc/devices 下创建了 4 个具有不同主要 id 的主要设备,这不是我所期望的(我想要 1 个主要 id 和 4 个不同的次要 id)。
以下消息是我设备的日志,它显示探测函数被调用了 4 次:
zynqmp#dmesg |grep fstream
[ 111.769297] st_fstream: loading out-of-tree module taints kernel.
[ 111.775514] st_fstream: unknown parameter 'st_fstream' ignored
[ 111.781314] st_fstream: unknown parameter 'st_fstream' ignored
[ 111.787429] [fstream]cdev Device number reg/allocation successed. cdev->major=243, cdev->minor=0.
[ 111.787511] [fstream]@0xa0030000 mapped to 0xffffff800bbe0000, irq=46
[ 111.787512] [fstream] init success
[ 111.787572] [fstream]cdev Device number reg/allocation successed. cdev->major=242, cdev->minor=0.
[ 111.787631] [fstream]@0xa0034000 mapped to 0xffffff800bbf0000, irq=47
[ 111.787634] [fstream] init success
[ 111.787671] [fstream]cdev Device number reg/allocation successed. cdev->major=241, cdev->minor=0.
[ 111.787730] [fstream]@0xa0038000 mapped to 0xffffff800bc00000, irq=48
[ 111.787732] [fstream] init success
[ 111.787767] [fstream]cdev Device number reg/allocation successed. cdev->major=240, cdev->minor=0.
[ 111.787826] [fstream]@0xa003c000 mapped to 0xffffff800bc10000, irq=49
[ 111.787827] [fstream] init success
【问题讨论】:
-
看起来你正在为 CSI-2 设备/管道做一个不正常的方法。您是否查看过 drivers/media/ 文件夹中的示例?
-
你可以在你的模块初始化函数中调用
alloc_chrdev_region来保留一个设备号范围,然后在你的探测函数中从你保留的范围内分配一个未使用的设备号。 -
@0andriy 是的,但是我发现这个目录中的大多数示例代码都与 v4l2 驱动程序相关联,这对我来说太重了。
-
@Ian Abbott 是的,我尝试了您的建议。现在我在 static int __init fstream_init(void){..} 中获得主 ID,并在 platform_driver 的 fstream_probe 函数中添加/初始化 cdev。在 DTS 中通过 4 个相同设备的实例化,我可以成功找到 4 个具有相同主要 ID 但不同次要 ID 的设备。但是,我发现其实这些cdev都是一样的……也就是说,如果我打开/dev/st_fstream0,或者/dev/st_fstream3,驱动只是打开同一个实例化……不知道怎么回事有了这个。
-
驱动程序的“打开”文件操作处理程序(例如
int mydriver_fop_open(struct inode *inode, struct file *file))在inode->i_rdev中获取设备的主次编号组合。您应该能够使用它来检查正在打开的设备(例如,MINOR(inode->i_rdev)告诉您次要编号)。将file->private_data设置为指向您设备的私有数据,以供驱动程序的其他文件操作处理程序使用。
标签: linux-device-driver device-tree