diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/iommu/arm-smmu.c | 47 |
1 files changed, 25 insertions, 22 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 27fd3d7ba886..c00f483e106f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -331,6 +331,11 @@ module_param_named(force_stage, force_stage, int, S_IRUGO | S_IWUSR); | |||
331 | MODULE_PARM_DESC(force_stage, | 331 | MODULE_PARM_DESC(force_stage, |
332 | "Force SMMU mappings to be installed at a particular stage of translation. A value of '1' or '2' forces the corresponding stage. All other values are ignored (i.e. no stage is forced). Note that selecting a specific stage will disable support for nested translation."); | 332 | "Force SMMU mappings to be installed at a particular stage of translation. A value of '1' or '2' forces the corresponding stage. All other values are ignored (i.e. no stage is forced). Note that selecting a specific stage will disable support for nested translation."); |
333 | 333 | ||
334 | enum arm_smmu_arch_version { | ||
335 | ARM_SMMU_V1 = 1, | ||
336 | ARM_SMMU_V2, | ||
337 | }; | ||
338 | |||
334 | struct arm_smmu_smr { | 339 | struct arm_smmu_smr { |
335 | u8 idx; | 340 | u8 idx; |
336 | u16 mask; | 341 | u16 mask; |
@@ -365,7 +370,7 @@ struct arm_smmu_device { | |||
365 | 370 | ||
366 | #define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0) | 371 | #define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0) |
367 | u32 options; | 372 | u32 options; |
368 | int version; | 373 | enum arm_smmu_arch_version version; |
369 | 374 | ||
370 | u32 num_context_banks; | 375 | u32 num_context_banks; |
371 | u32 num_s2_context_banks; | 376 | u32 num_s2_context_banks; |
@@ -737,7 +742,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) | |||
737 | 742 | ||
738 | /* CBAR */ | 743 | /* CBAR */ |
739 | reg = cfg->cbar; | 744 | reg = cfg->cbar; |
740 | if (smmu->version == 1) | 745 | if (smmu->version == ARM_SMMU_V1) |
741 | reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT; | 746 | reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT; |
742 | 747 | ||
743 | /* | 748 | /* |
@@ -752,7 +757,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) | |||
752 | } | 757 | } |
753 | writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx)); | 758 | writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx)); |
754 | 759 | ||
755 | if (smmu->version > 1) { | 760 | if (smmu->version > ARM_SMMU_V1) { |
756 | /* CBA2R */ | 761 | /* CBA2R */ |
757 | #ifdef CONFIG_64BIT | 762 | #ifdef CONFIG_64BIT |
758 | reg = CBA2R_RW64_64BIT; | 763 | reg = CBA2R_RW64_64BIT; |
@@ -825,7 +830,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) | |||
825 | * TTBCR | 830 | * TTBCR |
826 | * We use long descriptor, with inner-shareable WBWA tables in TTBR0. | 831 | * We use long descriptor, with inner-shareable WBWA tables in TTBR0. |
827 | */ | 832 | */ |
828 | if (smmu->version > 1) { | 833 | if (smmu->version > ARM_SMMU_V1) { |
829 | if (PAGE_SIZE == SZ_4K) | 834 | if (PAGE_SIZE == SZ_4K) |
830 | reg = TTBCR_TG0_4K; | 835 | reg = TTBCR_TG0_4K; |
831 | else | 836 | else |
@@ -922,7 +927,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, | |||
922 | goto out_unlock; | 927 | goto out_unlock; |
923 | 928 | ||
924 | cfg->cbndx = ret; | 929 | cfg->cbndx = ret; |
925 | if (smmu->version == 1) { | 930 | if (smmu->version == ARM_SMMU_V1) { |
926 | cfg->irptndx = atomic_inc_return(&smmu->irptndx); | 931 | cfg->irptndx = atomic_inc_return(&smmu->irptndx); |
927 | cfg->irptndx %= smmu->num_context_irqs; | 932 | cfg->irptndx %= smmu->num_context_irqs; |
928 | } else { | 933 | } else { |
@@ -1733,10 +1738,6 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) | |||
1733 | u32 id; | 1738 | u32 id; |
1734 | 1739 | ||
1735 | dev_notice(smmu->dev, "probing hardware configuration...\n"); | 1740 | dev_notice(smmu->dev, "probing hardware configuration...\n"); |
1736 | |||
1737 | /* Primecell ID */ | ||
1738 | id = readl_relaxed(gr0_base + ARM_SMMU_GR0_PIDR2); | ||
1739 | smmu->version = ((id >> PIDR2_ARCH_SHIFT) & PIDR2_ARCH_MASK) + 1; | ||
1740 | dev_notice(smmu->dev, "SMMUv%d with:\n", smmu->version); | 1741 | dev_notice(smmu->dev, "SMMUv%d with:\n", smmu->version); |
1741 | 1742 | ||
1742 | /* ID0 */ | 1743 | /* ID0 */ |
@@ -1853,7 +1854,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) | |||
1853 | size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); | 1854 | size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); |
1854 | smmu->s2_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, size); | 1855 | smmu->s2_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, size); |
1855 | 1856 | ||
1856 | if (smmu->version == 1) { | 1857 | if (smmu->version == ARM_SMMU_V1) { |
1857 | smmu->s1_input_size = 32; | 1858 | smmu->s1_input_size = 32; |
1858 | } else { | 1859 | } else { |
1859 | #ifdef CONFIG_64BIT | 1860 | #ifdef CONFIG_64BIT |
@@ -1884,8 +1885,18 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) | |||
1884 | return 0; | 1885 | return 0; |
1885 | } | 1886 | } |
1886 | 1887 | ||
1888 | static struct of_device_id arm_smmu_of_match[] = { | ||
1889 | { .compatible = "arm,smmu-v1", .data = (void *)ARM_SMMU_V1 }, | ||
1890 | { .compatible = "arm,smmu-v2", .data = (void *)ARM_SMMU_V2 }, | ||
1891 | { .compatible = "arm,mmu-400", .data = (void *)ARM_SMMU_V1 }, | ||
1892 | { .compatible = "arm,mmu-500", .data = (void *)ARM_SMMU_V2 }, | ||
1893 | { }, | ||
1894 | }; | ||
1895 | MODULE_DEVICE_TABLE(of, arm_smmu_of_match); | ||
1896 | |||
1887 | static int arm_smmu_device_dt_probe(struct platform_device *pdev) | 1897 | static int arm_smmu_device_dt_probe(struct platform_device *pdev) |
1888 | { | 1898 | { |
1899 | const struct of_device_id *of_id; | ||
1889 | struct resource *res; | 1900 | struct resource *res; |
1890 | struct arm_smmu_device *smmu; | 1901 | struct arm_smmu_device *smmu; |
1891 | struct device *dev = &pdev->dev; | 1902 | struct device *dev = &pdev->dev; |
@@ -1900,6 +1911,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) | |||
1900 | } | 1911 | } |
1901 | smmu->dev = dev; | 1912 | smmu->dev = dev; |
1902 | 1913 | ||
1914 | of_id = of_match_node(arm_smmu_of_match, dev->of_node); | ||
1915 | smmu->version = (enum arm_smmu_arch_version)of_id->data; | ||
1916 | |||
1903 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1917 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1904 | smmu->base = devm_ioremap_resource(dev, res); | 1918 | smmu->base = devm_ioremap_resource(dev, res); |
1905 | if (IS_ERR(smmu->base)) | 1919 | if (IS_ERR(smmu->base)) |
@@ -1964,7 +1978,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) | |||
1964 | 1978 | ||
1965 | parse_driver_options(smmu); | 1979 | parse_driver_options(smmu); |
1966 | 1980 | ||
1967 | if (smmu->version > 1 && | 1981 | if (smmu->version > ARM_SMMU_V1 && |
1968 | smmu->num_context_banks != smmu->num_context_irqs) { | 1982 | smmu->num_context_banks != smmu->num_context_irqs) { |
1969 | dev_err(dev, | 1983 | dev_err(dev, |
1970 | "found only %d context interrupt(s) but %d required\n", | 1984 | "found only %d context interrupt(s) but %d required\n", |
@@ -2045,17 +2059,6 @@ static int arm_smmu_device_remove(struct platform_device *pdev) | |||
2045 | return 0; | 2059 | return 0; |
2046 | } | 2060 | } |
2047 | 2061 | ||
2048 | #ifdef CONFIG_OF | ||
2049 | static struct of_device_id arm_smmu_of_match[] = { | ||
2050 | { .compatible = "arm,smmu-v1", }, | ||
2051 | { .compatible = "arm,smmu-v2", }, | ||
2052 | { .compatible = "arm,mmu-400", }, | ||
2053 | { .compatible = "arm,mmu-500", }, | ||
2054 | { }, | ||
2055 | }; | ||
2056 | MODULE_DEVICE_TABLE(of, arm_smmu_of_match); | ||
2057 | #endif | ||
2058 | |||
2059 | static struct platform_driver arm_smmu_driver = { | 2062 | static struct platform_driver arm_smmu_driver = { |
2060 | .driver = { | 2063 | .driver = { |
2061 | .owner = THIS_MODULE, | 2064 | .owner = THIS_MODULE, |