驱动定义:
static struct platform_driver arm_smmu_driver = {
.driver = {
.name = "arm-smmu-v3",
.of_match_table = arm_smmu_of_match,
.suppress_bind_attrs = true,
},
.probe = arm_smmu_device_probe,
.remove = arm_smmu_device_remove,
.shutdown = arm_smmu_device_shutdown,
};
注册为platform_driver,对"arm,smmu-v3"设备识别并驱动其初始化,设备参数参考arm,smmu-v3.txt
smmu@2b400000 {
compatible = "arm,smmu-v3";
reg = <0x0 0x2b400000 0x0 0x20000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 77 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 79 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
dma-coherent;
#iommu-cells = <1>;
msi-parent = <&its 0xff0000>;
};
probe过程:
调用函数arm_smmu_device_probe进行probe,首先devm_kzalloc分配struct arm_smmu_device结构,调用arm_smmu_device_dt_probe对dts参数进行解析来初始化smmu结构,具体参数如上面所示,解析过程不再详细展开。
接着判断是否bypass,然后通过platform_get_resource获取到smmu的io资源信息,合法性检查之后对其进行ioremap并将虚拟地址记录在smmu->base中。通过platform_get_irq_byname_optional解析irq并记录。
至此基本的参数解析过程已经完成,紧接着根据参数进行硬件的初始化,通过函数arm_smmu_device_hw_probe完成。arm_smmu_init_structures用于完成smmu对应的结构,初始化完成后将smmu信息设置为platform device的private driver。至此开始reset设备,如设定bypass模式,清空数据等,然后将其添加到iommu系统中以供其他模块调用,同时将arm_smmu_ops赋值给iommu,通过iommu_device_register进行注册。最后是通过arm_smmu_set_bus_ops,对支持的bus设置iommu操作方法结构,均设置为arm_smmu_ops。
重点需要分析的就是arm_smmu_ops,也就是smmu提供给外界设置其功能的接口。