diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 4f4132d0fca40de669e30147b8e4627ff34bcbb6..a608ac136a973b4081b7d4fe063a275531e0b42f 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -444,9 +444,17 @@ config QCOM_IOMMU Support for IOMMU on certain Qualcomm SoCs. config SMMU_BYPASS_DEV - bool "SMMU bypass streams for some specific devices" + bool "SMMU bypass streams for some specific devices or CPU SoCs" help - according smmu.bypassdev cmdline, SMMU performs attribute - transformation only,with no address translation. + Using the smmu.bypassdev cmdline, to collect the devices that SMMU + performs attribute transformation only, with no address translation. + This function will be replaced by IORT RMR node, which will be + upstreamed in mainline. + Also extended this function to support SMMU bypass for some CPU SoCs + which the SMMU for some platform is not functional well. Since mainline + kernel already has the .def_domain_type hook for iommu_ops, so if we + update the kernel in the future, we can add the SMMU bypass code for + some CPU SoCs in the .def_domain_type hook, for now we just reuse the + dev bypass. endif # IOMMU_SUPPORT diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e2a72c71e20d01b4862bc9f38cc659ccfd5171fc..451075bb1b3c66ed13c619f1767cf1cf8339d1be 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1608,6 +1608,31 @@ static void arm_smmu_put_resv_regions(struct device *dev, kfree(entry); } +#ifdef CONFIG_SMMU_BYPASS_DEV + +#ifdef CONFIG_ARM64 +#include +static int phytium_smmu_def_domain_type(struct device *dev, unsigned int *type) +{ + u32 midr = read_cpuid_id(); + + if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_PHYTIUM_FT2000PLUS) + || ((midr & MIDR_CPU_MODEL_MASK) == MIDR_PHYTIUM_FT2500)) { + *type = IOMMU_DOMAIN_IDENTITY; + return 0; + } + + return -EINVAL; +} +#else +static inline int phytium_smmu_def_domain_type(struct device *dev, unsigned int *type) +{ + return -EINVAL; +} +#endif + +#endif + static struct iommu_ops arm_smmu_ops = { .capable = arm_smmu_capable, .domain_alloc = arm_smmu_domain_alloc, @@ -1627,6 +1652,9 @@ static struct iommu_ops arm_smmu_ops = { .get_resv_regions = arm_smmu_get_resv_regions, .put_resv_regions = arm_smmu_put_resv_regions, .pgsize_bitmap = -1UL, /* Restricted during device attach */ +#ifdef CONFIG_SMMU_BYPASS_DEV + .device_domain_type = phytium_smmu_def_domain_type, +#endif }; static void arm_smmu_device_reset(struct arm_smmu_device *smmu)