diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index e0d5960e7753..f58d6fc37d30 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -409,7 +409,7 @@ config ARM_SMMU_V3_SVA config TEGRA241_CMDQV bool "NVIDIA Tegra241 CMDQ-V extension support for ARM SMMUv3" - depends on ACPI + depends on ARM_SMMU_V3 help Support for NVIDIA CMDQ-Virtualization extension for ARM SMMUv3. The CMDQ-V extension is similar to v3.3 ECMDQ for multi command queues diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 185f4ef2deaf..dbf12404145e 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -3713,6 +3713,34 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) return 0; } +#ifdef CONFIG_TEGRA241_CMDQV +static void tegra_cmdqv_dt_probe(struct device_node *smmu_node, + struct arm_smmu_device *smmu) +{ + struct platform_device *pdev; + struct device_node *np; + + np = of_parse_phandle(smmu_node, "nvidia,cmdqv", 0); + if (!np) + return; + + pdev = of_find_device_by_node(np); + of_node_put(np); + if (!pdev) + return; + + smmu->impl_dev = &pdev->dev; + smmu->options |= ARM_SMMU_OPT_TEGRA241_CMDQV; + dev_info(smmu->dev, "found companion CMDQV device: %s\n", + dev_name(smmu->impl_dev)); +} +#else +static void tegra_cmdqv_dt_probe(struct device_node *smmu_node, + struct arm_smmu_device *smmu) +{ +} +#endif + #ifdef CONFIG_ACPI #ifdef CONFIG_TEGRA241_CMDQV static void acpi_smmu_dsdt_probe_tegra241_cmdqv(struct acpi_iort_node *node, @@ -3812,6 +3840,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev, if (of_dma_is_coherent(dev->of_node)) smmu->features |= ARM_SMMU_FEAT_COHERENCY; + tegra_cmdqv_dt_probe(dev->of_node, smmu); + return ret; } diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c index dd7d030d2e89..48618089d1f2 100644 --- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c +++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include @@ -748,6 +750,26 @@ free_list: return res; } +static struct resource * +tegra241_cmdqv_find_dt_resource(struct device *dev, int *irq) +{ + struct platform_device *pdev = to_platform_device(dev); + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "no memory resource found for CMDQV\n"); + return NULL; + } + + if (irq) + *irq = platform_get_irq_byname_optional(pdev, "cmdqv"); + if (!irq || *irq <= 0) + dev_warn(dev, "no interrupt. errors will not be reported\n"); + + return res; +} + static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu) { struct tegra241_cmdqv *cmdqv = @@ -875,11 +897,14 @@ struct arm_smmu_device *tegra241_cmdqv_probe(struct arm_smmu_device *smmu) if (!smmu->dev->of_node) res = tegra241_cmdqv_find_acpi_resource(smmu->impl_dev, &irq); + else + res = tegra241_cmdqv_find_dt_resource(smmu->impl_dev, &irq); if (!res) goto out_fallback; new_smmu = __tegra241_cmdqv_probe(smmu, res, irq); - kfree(res); + if (!smmu->dev->of_node) + kfree(res); if (new_smmu) return new_smmu; @@ -890,3 +915,20 @@ out_fallback: put_device(smmu->impl_dev); return ERR_PTR(-ENODEV); } + +static const struct of_device_id tegra241_cmdqv_of_match[] = { + { .compatible = "nvidia,tegra264-cmdqv" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, tegra241_cmdqv_of_match); + +static struct platform_driver tegra241_cmdqv_driver = { + .driver = { + .name = "tegra241-cmdqv", + .of_match_table = tegra241_cmdqv_of_match, + }, +}; +module_platform_driver(tegra241_cmdqv_driver); + +MODULE_DESCRIPTION("NVIDIA Tegra241 Command Queue Virtualization Driver"); +MODULE_LICENSE("GPL v2");