mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 17:12:06 +00:00
iommu/arm-smmu: Workaround for Marvell Armada-AP806 SoC erratum #582743
Due to erratum #582743, the Marvell Armada-AP806 can't access 64bit to ARM SMMUv2 registers. Provide implementation relevant hooks: - split the writeq/readq to two accesses of writel/readl. - mask the MMU_IDR2.PTFSv8 fields to not use AArch64 format (but only AARCH32_L) since with AArch64 format 32 bits access is not supported. Note that most 64-bit registers like TTBRn can be accessed as two 32-bit halves without issue, and AArch32 format ensures that the register writes which must be atomic (for TLBI etc.) need only be 32-bit. Signed-off-by: Hanna Hawa <hannah@marvell.com> Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com> Signed-off-by: Tomasz Nowicki <tn@semihalf.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/20200715070649.18733-3-tn@semihalf.com Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
6a79a5a384
commit
f2d9848aeb
@ -125,6 +125,9 @@ stable kernels.
|
||||
| Cavium | ThunderX2 Core | #219 | CAVIUM_TX2_ERRATUM_219 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Marvell | ARM-MMU-500 | #582743 | N/A |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| Freescale/NXP | LS2080A/LS1043A | A-008585 | FSL_ERRATUM_A008585 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
|
@ -147,6 +147,48 @@ static const struct arm_smmu_impl arm_mmu500_impl = {
|
||||
.reset = arm_mmu500_reset,
|
||||
};
|
||||
|
||||
static u64 mrvl_mmu500_readq(struct arm_smmu_device *smmu, int page, int off)
|
||||
{
|
||||
/*
|
||||
* Marvell Armada-AP806 erratum #582743.
|
||||
* Split all the readq to double readl
|
||||
*/
|
||||
return hi_lo_readq_relaxed(arm_smmu_page(smmu, page) + off);
|
||||
}
|
||||
|
||||
static void mrvl_mmu500_writeq(struct arm_smmu_device *smmu, int page, int off,
|
||||
u64 val)
|
||||
{
|
||||
/*
|
||||
* Marvell Armada-AP806 erratum #582743.
|
||||
* Split all the writeq to double writel
|
||||
*/
|
||||
hi_lo_writeq_relaxed(val, arm_smmu_page(smmu, page) + off);
|
||||
}
|
||||
|
||||
static int mrvl_mmu500_cfg_probe(struct arm_smmu_device *smmu)
|
||||
{
|
||||
|
||||
/*
|
||||
* Armada-AP806 erratum #582743.
|
||||
* Hide the SMMU_IDR2.PTFSv8 fields to sidestep the AArch64
|
||||
* formats altogether and allow using 32 bits access on the
|
||||
* interconnect.
|
||||
*/
|
||||
smmu->features &= ~(ARM_SMMU_FEAT_FMT_AARCH64_4K |
|
||||
ARM_SMMU_FEAT_FMT_AARCH64_16K |
|
||||
ARM_SMMU_FEAT_FMT_AARCH64_64K);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct arm_smmu_impl mrvl_mmu500_impl = {
|
||||
.read_reg64 = mrvl_mmu500_readq,
|
||||
.write_reg64 = mrvl_mmu500_writeq,
|
||||
.cfg_probe = mrvl_mmu500_cfg_probe,
|
||||
.reset = arm_mmu500_reset,
|
||||
};
|
||||
|
||||
|
||||
struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
|
||||
{
|
||||
@ -177,5 +219,8 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
|
||||
of_device_is_compatible(np, "qcom,sm8250-smmu-500"))
|
||||
return qcom_smmu_impl_init(smmu);
|
||||
|
||||
if (of_device_is_compatible(np, "marvell,ap806-smmu-500"))
|
||||
smmu->impl = &mrvl_mmu500_impl;
|
||||
|
||||
return smmu;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user