diff options
author | Robin Murphy <robin.murphy@arm.com> | 2016-04-13 13:12:57 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2016-05-03 13:23:01 -0400 |
commit | 67b65a3fb8e658d00ad1bb06e341f09b1f93a25c (patch) | |
tree | e585e1fd41b7c4b9c3bde03b85ec90da61d4c4af /drivers/iommu/arm-smmu.c | |
parent | 1bd37a6835bef0ecd2138cb42f9088fd890f9939 (diff) |
iommu/arm-smmu: Differentiate specific implementations
As the inevitable reality of implementation-specific errata workarounds
begin to accrue alongside our integration quirk handling, it's about
time the driver had a decent way of keeping track. Extend the per-SMMU
data so we can identify specific implementations in an efficient and
firmware-agnostic manner.
Acked-by: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com>
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.c | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e933679a3266..2d5f357de69c 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -278,6 +278,10 @@ enum arm_smmu_arch_version { | |||
278 | ARM_SMMU_V2, | 278 | ARM_SMMU_V2, |
279 | }; | 279 | }; |
280 | 280 | ||
281 | enum arm_smmu_implementation { | ||
282 | GENERIC_SMMU, | ||
283 | }; | ||
284 | |||
281 | struct arm_smmu_smr { | 285 | struct arm_smmu_smr { |
282 | u8 idx; | 286 | u8 idx; |
283 | u16 mask; | 287 | u16 mask; |
@@ -315,6 +319,7 @@ struct arm_smmu_device { | |||
315 | #define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0) | 319 | #define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0) |
316 | u32 options; | 320 | u32 options; |
317 | enum arm_smmu_arch_version version; | 321 | enum arm_smmu_arch_version version; |
322 | enum arm_smmu_implementation model; | ||
318 | 323 | ||
319 | u32 num_context_banks; | 324 | u32 num_context_banks; |
320 | u32 num_s2_context_banks; | 325 | u32 num_s2_context_banks; |
@@ -1735,13 +1740,24 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) | |||
1735 | return 0; | 1740 | return 0; |
1736 | } | 1741 | } |
1737 | 1742 | ||
1743 | struct arm_smmu_match_data { | ||
1744 | enum arm_smmu_arch_version version; | ||
1745 | enum arm_smmu_implementation model; | ||
1746 | }; | ||
1747 | |||
1748 | #define ARM_SMMU_MATCH_DATA(name, ver, imp) \ | ||
1749 | static struct arm_smmu_match_data name = { .version = ver, .model = imp } | ||
1750 | |||
1751 | ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU); | ||
1752 | ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU); | ||
1753 | |||
1738 | static const struct of_device_id arm_smmu_of_match[] = { | 1754 | static const struct of_device_id arm_smmu_of_match[] = { |
1739 | { .compatible = "arm,smmu-v1", .data = (void *)ARM_SMMU_V1 }, | 1755 | { .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 }, |
1740 | { .compatible = "arm,smmu-v2", .data = (void *)ARM_SMMU_V2 }, | 1756 | { .compatible = "arm,smmu-v2", .data = &smmu_generic_v2 }, |
1741 | { .compatible = "arm,mmu-400", .data = (void *)ARM_SMMU_V1 }, | 1757 | { .compatible = "arm,mmu-400", .data = &smmu_generic_v1 }, |
1742 | { .compatible = "arm,mmu-401", .data = (void *)ARM_SMMU_V1 }, | 1758 | { .compatible = "arm,mmu-401", .data = &smmu_generic_v1 }, |
1743 | { .compatible = "arm,mmu-500", .data = (void *)ARM_SMMU_V2 }, | 1759 | { .compatible = "arm,mmu-500", .data = &smmu_generic_v2 }, |
1744 | { .compatible = "cavium,smmu-v2", .data = (void *)ARM_SMMU_V2 }, | 1760 | { .compatible = "cavium,smmu-v2", .data = &smmu_generic_v2 }, |
1745 | { }, | 1761 | { }, |
1746 | }; | 1762 | }; |
1747 | MODULE_DEVICE_TABLE(of, arm_smmu_of_match); | 1763 | MODULE_DEVICE_TABLE(of, arm_smmu_of_match); |
@@ -1749,6 +1765,7 @@ MODULE_DEVICE_TABLE(of, arm_smmu_of_match); | |||
1749 | static int arm_smmu_device_dt_probe(struct platform_device *pdev) | 1765 | static int arm_smmu_device_dt_probe(struct platform_device *pdev) |
1750 | { | 1766 | { |
1751 | const struct of_device_id *of_id; | 1767 | const struct of_device_id *of_id; |
1768 | const struct arm_smmu_match_data *data; | ||
1752 | struct resource *res; | 1769 | struct resource *res; |
1753 | struct arm_smmu_device *smmu; | 1770 | struct arm_smmu_device *smmu; |
1754 | struct device *dev = &pdev->dev; | 1771 | struct device *dev = &pdev->dev; |
@@ -1764,7 +1781,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) | |||
1764 | smmu->dev = dev; | 1781 | smmu->dev = dev; |
1765 | 1782 | ||
1766 | of_id = of_match_node(arm_smmu_of_match, dev->of_node); | 1783 | of_id = of_match_node(arm_smmu_of_match, dev->of_node); |
1767 | smmu->version = (enum arm_smmu_arch_version)of_id->data; | 1784 | data = of_id->data; |
1785 | smmu->version = data->version; | ||
1786 | smmu->model = data->model; | ||
1768 | 1787 | ||
1769 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1788 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1770 | smmu->base = devm_ioremap_resource(dev, res); | 1789 | smmu->base = devm_ioremap_resource(dev, res); |