aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/arm-smmu.c
diff options
context:
space:
mode:
authorRobin Murphy <robin.murphy@arm.com>2016-04-13 13:13:03 -0400
committerWill Deacon <will.deacon@arm.com>2016-05-03 13:23:03 -0400
commitb7862e3559f9ab4aaa258dcb846986601a7ca0b8 (patch)
tree651a030a209b4e69649c35df886ec5bd80e62452 /drivers/iommu/arm-smmu.c
parent7602b8710645da48b2937f05fa41d627a0e73dad (diff)
iommu/arm-smmu: Support SMMUv1 64KB supplement
The 64KB Translation Granule Supplement to the SMMUv1 architecture allows an SMMUv1 implementation to support 64KB pages for stage 2 translations, using a constrained VMSAv8 descriptor format limited to 40-bit addresses. Now that we can freely mix and match context formats, we can actually handle having 4KB pages via an AArch32 context but 64KB pages via an AArch64 context, so plumb it in. It is assumed that any implementations will have hardware capabilities matching the format constraints, thus obviating the need for excessive sanity-checking; this is the case for MMU-401, the only ARM Ltd. implementation. CC: Eric Auger <eric.auger@linaro.org> Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r--drivers/iommu/arm-smmu.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index f2ded69feba7..72dea314f9a1 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -277,7 +277,8 @@ MODULE_PARM_DESC(disable_bypass,
277 "Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU."); 277 "Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU.");
278 278
279enum arm_smmu_arch_version { 279enum arm_smmu_arch_version {
280 ARM_SMMU_V1 = 1, 280 ARM_SMMU_V1,
281 ARM_SMMU_V1_64K,
281 ARM_SMMU_V2, 282 ARM_SMMU_V2,
282}; 283};
283 284
@@ -769,7 +770,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
769 770
770 /* CBAR */ 771 /* CBAR */
771 reg = cfg->cbar; 772 reg = cfg->cbar;
772 if (smmu->version == ARM_SMMU_V1) 773 if (smmu->version < ARM_SMMU_V2)
773 reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT; 774 reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT;
774 775
775 /* 776 /*
@@ -934,7 +935,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
934 goto out_unlock; 935 goto out_unlock;
935 936
936 cfg->cbndx = ret; 937 cfg->cbndx = ret;
937 if (smmu->version == ARM_SMMU_V1) { 938 if (smmu->version < ARM_SMMU_V2) {
938 cfg->irptndx = atomic_inc_return(&smmu->irptndx); 939 cfg->irptndx = atomic_inc_return(&smmu->irptndx);
939 cfg->irptndx %= smmu->num_context_irqs; 940 cfg->irptndx %= smmu->num_context_irqs;
940 } else { 941 } else {
@@ -1619,7 +1620,8 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
1619 bool cttw_dt, cttw_reg; 1620 bool cttw_dt, cttw_reg;
1620 1621
1621 dev_notice(smmu->dev, "probing hardware configuration...\n"); 1622 dev_notice(smmu->dev, "probing hardware configuration...\n");
1622 dev_notice(smmu->dev, "SMMUv%d with:\n", smmu->version); 1623 dev_notice(smmu->dev, "SMMUv%d with:\n",
1624 smmu->version == ARM_SMMU_V2 ? 2 : 1);
1623 1625
1624 /* ID0 */ 1626 /* ID0 */
1625 id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID0); 1627 id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID0);
@@ -1651,7 +1653,8 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
1651 return -ENODEV; 1653 return -ENODEV;
1652 } 1654 }
1653 1655
1654 if ((id & ID0_S1TS) && ((smmu->version == 1) || !(id & ID0_ATOSNS))) { 1656 if ((id & ID0_S1TS) &&
1657 ((smmu->version < ARM_SMMU_V2) || !(id & ID0_ATOSNS))) {
1655 smmu->features |= ARM_SMMU_FEAT_TRANS_OPS; 1658 smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;
1656 dev_notice(smmu->dev, "\taddress translation ops\n"); 1659 dev_notice(smmu->dev, "\taddress translation ops\n");
1657 } 1660 }
@@ -1766,8 +1769,10 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
1766 dev_warn(smmu->dev, 1769 dev_warn(smmu->dev,
1767 "failed to set DMA mask for table walker\n"); 1770 "failed to set DMA mask for table walker\n");
1768 1771
1769 if (smmu->version == ARM_SMMU_V1) { 1772 if (smmu->version < ARM_SMMU_V2) {
1770 smmu->va_size = smmu->ipa_size; 1773 smmu->va_size = smmu->ipa_size;
1774 if (smmu->version == ARM_SMMU_V1_64K)
1775 smmu->features |= ARM_SMMU_FEAT_FMT_AARCH64_64K;
1771 } else { 1776 } else {
1772 size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK; 1777 size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK;
1773 smmu->va_size = arm_smmu_id_size_to_bits(size); 1778 smmu->va_size = arm_smmu_id_size_to_bits(size);
@@ -1815,6 +1820,7 @@ static struct arm_smmu_match_data name = { .version = ver, .model = imp }
1815 1820
1816ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); 1821ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU);
1817ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); 1822ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU);
1823ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU);
1818ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500); 1824ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500);
1819ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2); 1825ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2);
1820 1826
@@ -1822,7 +1828,7 @@ static const struct of_device_id arm_smmu_of_match[] = {
1822 { .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 }, 1828 { .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 },
1823 { .compatible = "arm,smmu-v2", .data = &smmu_generic_v2 }, 1829 { .compatible = "arm,smmu-v2", .data = &smmu_generic_v2 },
1824 { .compatible = "arm,mmu-400", .data = &smmu_generic_v1 }, 1830 { .compatible = "arm,mmu-400", .data = &smmu_generic_v1 },
1825 { .compatible = "arm,mmu-401", .data = &smmu_generic_v1 }, 1831 { .compatible = "arm,mmu-401", .data = &arm_mmu401 },
1826 { .compatible = "arm,mmu-500", .data = &arm_mmu500 }, 1832 { .compatible = "arm,mmu-500", .data = &arm_mmu500 },
1827 { .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 }, 1833 { .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 },
1828 { }, 1834 { },
@@ -1916,7 +1922,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
1916 1922
1917 parse_driver_options(smmu); 1923 parse_driver_options(smmu);
1918 1924
1919 if (smmu->version > ARM_SMMU_V1 && 1925 if (smmu->version == ARM_SMMU_V2 &&
1920 smmu->num_context_banks != smmu->num_context_irqs) { 1926 smmu->num_context_banks != smmu->num_context_irqs) {
1921 dev_err(dev, 1927 dev_err(dev,
1922 "found only %d context interrupt(s) but %d required\n", 1928 "found only %d context interrupt(s) but %d required\n",