// SPDX-License-Identifier: GPL-2.0-only // Miscellaneous Arm SMMU implementation and integration quirks // Copyright (C) 2019 Arm Limited
#define pr_fmt(fmt) "arm-smmu: " fmt
#include <linux/bitfield.h> #include <linux/of.h>
#include"arm-smmu.h"
staticint arm_smmu_gr0_ns(int offset)
{ switch (offset) { case ARM_SMMU_GR0_sCR0: case ARM_SMMU_GR0_sACR: case ARM_SMMU_GR0_sGFSR: case ARM_SMMU_GR0_sGFSYNR0: case ARM_SMMU_GR0_sGFSYNR1: case ARM_SMMU_GR0_sGFSYNR2: return offset + 0x400; default: return offset;
}
}
static u32 arm_smmu_read_ns(struct arm_smmu_device *smmu, int page, int offset)
{ if (page == ARM_SMMU_GR0)
offset = arm_smmu_gr0_ns(offset); return readl_relaxed(arm_smmu_page(smmu, page) + offset);
}
staticvoid arm_smmu_write_ns(struct arm_smmu_device *smmu, int page, int offset, u32 val)
{ if (page == ARM_SMMU_GR0)
offset = arm_smmu_gr0_ns(offset);
writel_relaxed(val, arm_smmu_page(smmu, page) + offset);
}
/* Since we don't care for sGFAR, we can do without 64-bit accessors */ staticconststruct arm_smmu_impl calxeda_impl = {
.read_reg = arm_smmu_read_ns,
.write_reg = arm_smmu_write_ns,
};
int arm_mmu500_reset(struct arm_smmu_device *smmu)
{
u32 reg, major; /* * On MMU-500 r2p0 onwards we need to clear ACR.CACHE_LOCK before * writes to the context bank ACTLRs will stick. And we just hope that * Secure has also cleared SACR.CACHE_LOCK for this to take effect...
*/
reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_ID7);
major = FIELD_GET(ARM_SMMU_ID7_MAJOR, reg);
reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sACR); if (major >= 2)
reg &= ~ARM_MMU500_ACR_CACHE_LOCK; /* * Allow unmatched Stream IDs to allocate bypass * TLB entries for reduced latency.
*/
reg |= ARM_MMU500_ACR_SMTNMB_TLBEN | ARM_MMU500_ACR_S2CRB_TLBEN;
arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sACR, reg);
#ifdef CONFIG_ARM_SMMU_MMU_500_CPRE_ERRATA /* * Disable MMU-500's not-particularly-beneficial next-page * prefetcher for the sake of at least 5 known errata.
*/ for (int i = 0; i < smmu->num_context_banks; ++i) {
reg = arm_smmu_cb_read(smmu, i, ARM_SMMU_CB_ACTLR);
reg &= ~ARM_MMU500_ACTLR_CPRE;
arm_smmu_cb_write(smmu, i, ARM_SMMU_CB_ACTLR, reg);
reg = arm_smmu_cb_read(smmu, i, ARM_SMMU_CB_ACTLR); if (reg & ARM_MMU500_ACTLR_CPRE)
dev_warn_once(smmu->dev, "Failed to disable prefetcher for errata workarounds, check SACR.CACHE_LOCK\n");
} #endif
/* * 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);
/* * Set the impl for model-specific implementation quirks first, * such that platform integration quirks can pick it up and * inherit from it if necessary.
*/ switch (smmu->model) { case ARM_MMU500:
smmu->impl = &arm_mmu500_impl; break; case CAVIUM_SMMUV2: return cavium_smmu_impl_init(smmu); default: break;
}
/* This is implicitly MMU-400 */ if (of_property_read_bool(np, "calxeda,smmu-secure-config-access"))
smmu->impl = &calxeda_impl;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.