···1616 "arm,mmu-400"1717 "arm,mmu-401"1818 "arm,mmu-500"1919+ "cavium,smmu-v2"19202021 depending on the particular implementation and/or the2122 version of the architecture implemented.
+210-81
drivers/iommu/arm-smmu.c
···3434#include <linux/err.h>3535#include <linux/interrupt.h>3636#include <linux/io.h>3737+#include <linux/io-64-nonatomic-hi-lo.h>3738#include <linux/iommu.h>3839#include <linux/iopoll.h>3940#include <linux/module.h>···7271 ((smmu->options & ARM_SMMU_OPT_SECURE_CFG_ACCESS) \7372 ? 0x400 : 0))74737474+/*7575+ * Some 64-bit registers only make sense to write atomically, but in such7676+ * cases all the data relevant to AArch32 formats lies within the lower word,7777+ * therefore this actually makes more sense than it might first appear.7878+ */7579#ifdef CONFIG_64BIT7676-#define smmu_writeq writeq_relaxed8080+#define smmu_write_atomic_lq writeq_relaxed7781#else7878-#define smmu_writeq(reg64, addr) \7979- do { \8080- u64 __val = (reg64); \8181- void __iomem *__addr = (addr); \8282- writel_relaxed(__val >> 32, __addr + 4); \8383- writel_relaxed(__val, __addr); \8484- } while (0)8282+#define smmu_write_atomic_lq writel_relaxed8583#endif86848785/* Configuration registers */···9494#define sCR0_VMIDPNE (1 << 11)9595#define sCR0_PTM (1 << 12)9696#define sCR0_FB (1 << 13)9797+#define sCR0_VMID16EN (1 << 31)9798#define sCR0_BSU_SHIFT 149899#define sCR0_BSU_MASK 0x3100100+101101+/* Auxiliary Configuration register */102102+#define ARM_SMMU_GR0_sACR 0x1099103100104/* Identification registers */101105#define ARM_SMMU_GR0_ID0 0x20···120116#define ID0_NTS (1 << 28)121117#define ID0_SMS (1 << 27)122118#define ID0_ATOSNS (1 << 26)119119+#define ID0_PTFS_NO_AARCH32 (1 << 25)120120+#define ID0_PTFS_NO_AARCH32S (1 << 24)123121#define ID0_CTTW (1 << 14)124122#define ID0_NUMIRPT_SHIFT 16125123#define ID0_NUMIRPT_MASK 0xff···147141#define ID2_PTFS_4K (1 << 12)148142#define ID2_PTFS_16K (1 << 13)149143#define ID2_PTFS_64K (1 << 14)144144+#define ID2_VMID16 (1 << 15)145145+146146+#define ID7_MAJOR_SHIFT 4147147+#define ID7_MAJOR_MASK 0xf150148151149/* Global TLB invalidation */152150#define ARM_SMMU_GR0_TLBIVMID 0x64···203193#define ARM_SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2))204194#define CBA2R_RW64_32BIT (0 << 0)205195#define CBA2R_RW64_64BIT (1 << 0)196196+#define CBA2R_VMID_SHIFT 16197197+#define CBA2R_VMID_MASK 0xffff206198207199/* Translation context bank */208200#define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size >> 1))209201#define ARM_SMMU_CB(smmu, n) ((n) * (1 << (smmu)->pgshift))210202211203#define ARM_SMMU_CB_SCTLR 0x0204204+#define ARM_SMMU_CB_ACTLR 0x4212205#define ARM_SMMU_CB_RESUME 0x8213206#define ARM_SMMU_CB_TTBCR2 0x10214207#define ARM_SMMU_CB_TTBR0 0x20···219206#define ARM_SMMU_CB_TTBCR 0x30220207#define ARM_SMMU_CB_S1_MAIR0 0x38221208#define ARM_SMMU_CB_S1_MAIR1 0x3c222222-#define ARM_SMMU_CB_PAR_LO 0x50223223-#define ARM_SMMU_CB_PAR_HI 0x54209209+#define ARM_SMMU_CB_PAR 0x50224210#define ARM_SMMU_CB_FSR 0x58225225-#define ARM_SMMU_CB_FAR_LO 0x60226226-#define ARM_SMMU_CB_FAR_HI 0x64211211+#define ARM_SMMU_CB_FAR 0x60227212#define ARM_SMMU_CB_FSYNR0 0x68228213#define ARM_SMMU_CB_S1_TLBIVA 0x600229214#define ARM_SMMU_CB_S1_TLBIASID 0x610···240229#define SCTLR_TRE (1 << 1)241230#define SCTLR_M (1 << 0)242231#define SCTLR_EAE_SBOP (SCTLR_AFE | SCTLR_TRE)232232+233233+#define ARM_MMU500_ACTLR_CPRE (1 << 1)234234+235235+#define ARM_MMU500_ACR_CACHE_LOCK (1 << 26)243236244237#define CB_PAR_F (1 << 0)245238···285270 "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.");286271287272enum arm_smmu_arch_version {288288- ARM_SMMU_V1 = 1,273273+ ARM_SMMU_V1,274274+ ARM_SMMU_V1_64K,289275 ARM_SMMU_V2,276276+};277277+278278+enum arm_smmu_implementation {279279+ GENERIC_SMMU,280280+ ARM_MMU500,281281+ CAVIUM_SMMUV2,290282};291283292284struct arm_smmu_smr {···327305#define ARM_SMMU_FEAT_TRANS_S2 (1 << 3)328306#define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4)329307#define ARM_SMMU_FEAT_TRANS_OPS (1 << 5)308308+#define ARM_SMMU_FEAT_VMID16 (1 << 6)309309+#define ARM_SMMU_FEAT_FMT_AARCH64_4K (1 << 7)310310+#define ARM_SMMU_FEAT_FMT_AARCH64_16K (1 << 8)311311+#define ARM_SMMU_FEAT_FMT_AARCH64_64K (1 << 9)312312+#define ARM_SMMU_FEAT_FMT_AARCH32_L (1 << 10)313313+#define ARM_SMMU_FEAT_FMT_AARCH32_S (1 << 11)330314 u32 features;331315332316#define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)333317 u32 options;334318 enum arm_smmu_arch_version version;319319+ enum arm_smmu_implementation model;335320336321 u32 num_context_banks;337322 u32 num_s2_context_banks;···358329359330 struct list_head list;360331 struct rb_root masters;332332+333333+ u32 cavium_id_base; /* Specific to Cavium */334334+};335335+336336+enum arm_smmu_context_fmt {337337+ ARM_SMMU_CTX_FMT_NONE,338338+ ARM_SMMU_CTX_FMT_AARCH64,339339+ ARM_SMMU_CTX_FMT_AARCH32_L,340340+ ARM_SMMU_CTX_FMT_AARCH32_S,361341};362342363343struct arm_smmu_cfg {364344 u8 cbndx;365345 u8 irptndx;366346 u32 cbar;347347+ enum arm_smmu_context_fmt fmt;367348};368349#define INVALID_IRPTNDX 0xff369350370370-#define ARM_SMMU_CB_ASID(cfg) ((cfg)->cbndx)371371-#define ARM_SMMU_CB_VMID(cfg) ((cfg)->cbndx + 1)351351+#define ARM_SMMU_CB_ASID(smmu, cfg) ((u16)(smmu)->cavium_id_base + (cfg)->cbndx)352352+#define ARM_SMMU_CB_VMID(smmu, cfg) ((u16)(smmu)->cavium_id_base + (cfg)->cbndx + 1)372353373354enum arm_smmu_domain_stage {374355 ARM_SMMU_DOMAIN_S1 = 0,···405366 u32 opt;406367 const char *prop;407368};369369+370370+static atomic_t cavium_smmu_context_count = ATOMIC_INIT(0);408371409372static struct arm_smmu_option_prop arm_smmu_options[] = {410373 { ARM_SMMU_OPT_SECURE_CFG_ACCESS, "calxeda,smmu-secure-config-access" },···619578620579 if (stage1) {621580 base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);622622- writel_relaxed(ARM_SMMU_CB_ASID(cfg),581581+ writel_relaxed(ARM_SMMU_CB_ASID(smmu, cfg),623582 base + ARM_SMMU_CB_S1_TLBIASID);624583 } else {625584 base = ARM_SMMU_GR0(smmu);626626- writel_relaxed(ARM_SMMU_CB_VMID(cfg),585585+ writel_relaxed(ARM_SMMU_CB_VMID(smmu, cfg),627586 base + ARM_SMMU_GR0_TLBIVMID);628587 }629588···643602 reg = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);644603 reg += leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA;645604646646- if (!IS_ENABLED(CONFIG_64BIT) || smmu->version == ARM_SMMU_V1) {605605+ if (cfg->fmt != ARM_SMMU_CTX_FMT_AARCH64) {647606 iova &= ~12UL;648648- iova |= ARM_SMMU_CB_ASID(cfg);607607+ iova |= ARM_SMMU_CB_ASID(smmu, cfg);649608 do {650609 writel_relaxed(iova, reg);651610 iova += granule;652611 } while (size -= granule);653653-#ifdef CONFIG_64BIT654612 } else {655613 iova >>= 12;656656- iova |= (u64)ARM_SMMU_CB_ASID(cfg) << 48;614614+ iova |= (u64)ARM_SMMU_CB_ASID(smmu, cfg) << 48;657615 do {658616 writeq_relaxed(iova, reg);659617 iova += granule >> 12;660618 } while (size -= granule);661661-#endif662619 }663663-#ifdef CONFIG_64BIT664620 } else if (smmu->version == ARM_SMMU_V2) {665621 reg = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);666622 reg += leaf ? ARM_SMMU_CB_S2_TLBIIPAS2L :667623 ARM_SMMU_CB_S2_TLBIIPAS2;668624 iova >>= 12;669625 do {670670- writeq_relaxed(iova, reg);626626+ smmu_write_atomic_lq(iova, reg);671627 iova += granule >> 12;672628 } while (size -= granule);673673-#endif674629 } else {675630 reg = ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_TLBIVMID;676676- writel_relaxed(ARM_SMMU_CB_VMID(cfg), reg);631631+ writel_relaxed(ARM_SMMU_CB_VMID(smmu, cfg), reg);677632 }678633}679634···682645static irqreturn_t arm_smmu_context_fault(int irq, void *dev)683646{684647 int flags, ret;685685- u32 fsr, far, fsynr, resume;648648+ u32 fsr, fsynr, resume;686649 unsigned long iova;687650 struct iommu_domain *domain = dev;688651 struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);···704667 fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0);705668 flags = fsynr & FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ;706669707707- far = readl_relaxed(cb_base + ARM_SMMU_CB_FAR_LO);708708- iova = far;709709-#ifdef CONFIG_64BIT710710- far = readl_relaxed(cb_base + ARM_SMMU_CB_FAR_HI);711711- iova |= ((unsigned long)far << 32);712712-#endif713713-670670+ iova = readq_relaxed(cb_base + ARM_SMMU_CB_FAR);714671 if (!report_iommu_fault(domain, smmu->dev, iova, flags)) {715672 ret = IRQ_HANDLED;716673 resume = RESUME_RETRY;···765734 cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);766735767736 if (smmu->version > ARM_SMMU_V1) {768768- /*769769- * CBA2R.770770- * *Must* be initialised before CBAR thanks to VMID16771771- * architectural oversight affected some implementations.772772- */773773-#ifdef CONFIG_64BIT774774- reg = CBA2R_RW64_64BIT;775775-#else776776- reg = CBA2R_RW64_32BIT;777777-#endif737737+ if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)738738+ reg = CBA2R_RW64_64BIT;739739+ else740740+ reg = CBA2R_RW64_32BIT;741741+ /* 16-bit VMIDs live in CBA2R */742742+ if (smmu->features & ARM_SMMU_FEAT_VMID16)743743+ reg |= ARM_SMMU_CB_VMID(smmu, cfg) << CBA2R_VMID_SHIFT;744744+778745 writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBA2R(cfg->cbndx));779746 }780747781748 /* CBAR */782749 reg = cfg->cbar;783783- if (smmu->version == ARM_SMMU_V1)750750+ if (smmu->version < ARM_SMMU_V2)784751 reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT;785752786753 /*···788759 if (stage1) {789760 reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |790761 (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);791791- } else {792792- reg |= ARM_SMMU_CB_VMID(cfg) << CBAR_VMID_SHIFT;762762+ } else if (!(smmu->features & ARM_SMMU_FEAT_VMID16)) {763763+ /* 8-bit VMIDs live in CBAR */764764+ reg |= ARM_SMMU_CB_VMID(smmu, cfg) << CBAR_VMID_SHIFT;793765 }794766 writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));795767···798768 if (stage1) {799769 reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];800770801801- reg64 |= ((u64)ARM_SMMU_CB_ASID(cfg)) << TTBRn_ASID_SHIFT;802802- smmu_writeq(reg64, cb_base + ARM_SMMU_CB_TTBR0);771771+ reg64 |= ((u64)ARM_SMMU_CB_ASID(smmu, cfg)) << TTBRn_ASID_SHIFT;772772+ writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR0);803773804774 reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1];805805- reg64 |= ((u64)ARM_SMMU_CB_ASID(cfg)) << TTBRn_ASID_SHIFT;806806- smmu_writeq(reg64, cb_base + ARM_SMMU_CB_TTBR1);775775+ reg64 |= ((u64)ARM_SMMU_CB_ASID(smmu, cfg)) << TTBRn_ASID_SHIFT;776776+ writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR1);807777 } else {808778 reg64 = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;809809- smmu_writeq(reg64, cb_base + ARM_SMMU_CB_TTBR0);779779+ writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR0);810780 }811781812782 /* TTBCR */···885855 if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S2))886856 smmu_domain->stage = ARM_SMMU_DOMAIN_S1;887857858858+ /*859859+ * Choosing a suitable context format is even more fiddly. Until we860860+ * grow some way for the caller to express a preference, and/or move861861+ * the decision into the io-pgtable code where it arguably belongs,862862+ * just aim for the closest thing to the rest of the system, and hope863863+ * that the hardware isn't esoteric enough that we can't assume AArch64864864+ * support to be a superset of AArch32 support...865865+ */866866+ if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH32_L)867867+ cfg->fmt = ARM_SMMU_CTX_FMT_AARCH32_L;868868+ if ((IS_ENABLED(CONFIG_64BIT) || cfg->fmt == ARM_SMMU_CTX_FMT_NONE) &&869869+ (smmu->features & (ARM_SMMU_FEAT_FMT_AARCH64_64K |870870+ ARM_SMMU_FEAT_FMT_AARCH64_16K |871871+ ARM_SMMU_FEAT_FMT_AARCH64_4K)))872872+ cfg->fmt = ARM_SMMU_CTX_FMT_AARCH64;873873+874874+ if (cfg->fmt == ARM_SMMU_CTX_FMT_NONE) {875875+ ret = -EINVAL;876876+ goto out_unlock;877877+ }878878+888879 switch (smmu_domain->stage) {889880 case ARM_SMMU_DOMAIN_S1:890881 cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;891882 start = smmu->num_s2_context_banks;892883 ias = smmu->va_size;893884 oas = smmu->ipa_size;894894- if (IS_ENABLED(CONFIG_64BIT))885885+ if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64) {895886 fmt = ARM_64_LPAE_S1;896896- else887887+ } else {897888 fmt = ARM_32_LPAE_S1;889889+ ias = min(ias, 32UL);890890+ oas = min(oas, 40UL);891891+ }898892 break;899893 case ARM_SMMU_DOMAIN_NESTED:900894 /*···930876 start = 0;931877 ias = smmu->ipa_size;932878 oas = smmu->pa_size;933933- if (IS_ENABLED(CONFIG_64BIT))879879+ if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64) {934880 fmt = ARM_64_LPAE_S2;935935- else881881+ } else {936882 fmt = ARM_32_LPAE_S2;883883+ ias = min(ias, 40UL);884884+ oas = min(oas, 40UL);885885+ }937886 break;938887 default:939888 ret = -EINVAL;···949892 goto out_unlock;950893951894 cfg->cbndx = ret;952952- if (smmu->version == ARM_SMMU_V1) {895895+ if (smmu->version < ARM_SMMU_V2) {953896 cfg->irptndx = atomic_inc_return(&smmu->irptndx);954897 cfg->irptndx %= smmu->num_context_irqs;955898 } else {···13091252 /* ATS1 registers can only be written atomically */13101253 va = iova & ~0xfffUL;13111254 if (smmu->version == ARM_SMMU_V2)13121312- smmu_writeq(va, cb_base + ARM_SMMU_CB_ATS1PR);13131313- else12551255+ smmu_write_atomic_lq(va, cb_base + ARM_SMMU_CB_ATS1PR);12561256+ else /* Register is only 32-bit in v1 */13141257 writel_relaxed(va, cb_base + ARM_SMMU_CB_ATS1PR);1315125813161259 if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp,···13211264 return ops->iova_to_phys(ops, iova);13221265 }1323126613241324- phys = readl_relaxed(cb_base + ARM_SMMU_CB_PAR_LO);13251325- phys |= ((u64)readl_relaxed(cb_base + ARM_SMMU_CB_PAR_HI)) << 32;13261326-12671267+ phys = readq_relaxed(cb_base + ARM_SMMU_CB_PAR);13271268 if (phys & CB_PAR_F) {13281269 dev_err(dev, "translation fault!\n");13291270 dev_err(dev, "PAR = 0x%llx\n", phys);···15471492 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);15481493 void __iomem *cb_base;15491494 int i = 0;15501550- u32 reg;14951495+ u32 reg, major;1551149615521497 /* clear global FSR */15531498 reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);···15601505 writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i));15611506 }1562150715081508+ /*15091509+ * Before clearing ARM_MMU500_ACTLR_CPRE, need to15101510+ * clear CACHE_LOCK bit of ACR first. And, CACHE_LOCK15111511+ * bit is only present in MMU-500r2 onwards.15121512+ */15131513+ reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);15141514+ major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;15151515+ if ((smmu->model == ARM_MMU500) && (major >= 2)) {15161516+ reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);15171517+ reg &= ~ARM_MMU500_ACR_CACHE_LOCK;15181518+ writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);15191519+ }15201520+15631521 /* Make sure all context banks are disabled and clear CB_FSR */15641522 for (i = 0; i < smmu->num_context_banks; ++i) {15651523 cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);15661524 writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);15671525 writel_relaxed(FSR_FAULT, cb_base + ARM_SMMU_CB_FSR);15261526+ /*15271527+ * Disable MMU-500's not-particularly-beneficial next-page15281528+ * prefetcher for the sake of errata #841119 and #826419.15291529+ */15301530+ if (smmu->model == ARM_MMU500) {15311531+ reg = readl_relaxed(cb_base + ARM_SMMU_CB_ACTLR);15321532+ reg &= ~ARM_MMU500_ACTLR_CPRE;15331533+ writel_relaxed(reg, cb_base + ARM_SMMU_CB_ACTLR);15341534+ }15681535 }1569153615701537 /* Invalidate the TLB, just in case */···1613153616141537 /* Don't upgrade barriers */16151538 reg &= ~(sCR0_BSU_MASK << sCR0_BSU_SHIFT);15391539+15401540+ if (smmu->features & ARM_SMMU_FEAT_VMID16)15411541+ reg |= sCR0_VMID16EN;1616154216171543 /* Push the button */16181544 __arm_smmu_tlb_sync(smmu);···16491569 bool cttw_dt, cttw_reg;1650157016511571 dev_notice(smmu->dev, "probing hardware configuration...\n");16521652- dev_notice(smmu->dev, "SMMUv%d with:\n", smmu->version);15721572+ dev_notice(smmu->dev, "SMMUv%d with:\n",15731573+ smmu->version == ARM_SMMU_V2 ? 2 : 1);1653157416541575 /* ID0 */16551576 id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID0);···16821601 return -ENODEV;16831602 }1684160316851685- if ((id & ID0_S1TS) && ((smmu->version == 1) || !(id & ID0_ATOSNS))) {16041604+ if ((id & ID0_S1TS) &&16051605+ ((smmu->version < ARM_SMMU_V2) || !(id & ID0_ATOSNS))) {16861606 smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;16871607 dev_notice(smmu->dev, "\taddress translation ops\n");16881608 }···17391657 ID0_NUMSIDB_MASK;17401658 }1741165916601660+ if (smmu->version < ARM_SMMU_V2 || !(id & ID0_PTFS_NO_AARCH32)) {16611661+ smmu->features |= ARM_SMMU_FEAT_FMT_AARCH32_L;16621662+ if (!(id & ID0_PTFS_NO_AARCH32S))16631663+ smmu->features |= ARM_SMMU_FEAT_FMT_AARCH32_S;16641664+ }16651665+17421666 /* ID1 */17431667 id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID1);17441668 smmu->pgshift = (id & ID1_PAGESIZE) ? 16 : 12;···17651677 }17661678 dev_notice(smmu->dev, "\t%u context banks (%u stage-2 only)\n",17671679 smmu->num_context_banks, smmu->num_s2_context_banks);16801680+ /*16811681+ * Cavium CN88xx erratum #27704.16821682+ * Ensure ASID and VMID allocation is unique across all SMMUs in16831683+ * the system.16841684+ */16851685+ if (smmu->model == CAVIUM_SMMUV2) {16861686+ smmu->cavium_id_base =16871687+ atomic_add_return(smmu->num_context_banks,16881688+ &cavium_smmu_context_count);16891689+ smmu->cavium_id_base -= smmu->num_context_banks;16901690+ }1768169117691692 /* ID2 */17701693 id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID2);···17861687 size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);17871688 smmu->pa_size = size;1788168916901690+ if (id & ID2_VMID16)16911691+ smmu->features |= ARM_SMMU_FEAT_VMID16;16921692+17891693 /*17901694 * What the page table walker can address actually depends on which17911695 * descriptor format is in use, but since a) we don't know that yet,···17981696 dev_warn(smmu->dev,17991697 "failed to set DMA mask for table walker\n");1800169818011801- if (smmu->version == ARM_SMMU_V1) {16991699+ if (smmu->version < ARM_SMMU_V2) {18021700 smmu->va_size = smmu->ipa_size;18031803- size = SZ_4K | SZ_2M | SZ_1G;17011701+ if (smmu->version == ARM_SMMU_V1_64K)17021702+ smmu->features |= ARM_SMMU_FEAT_FMT_AARCH64_64K;18041703 } else {18051704 size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK;18061705 smmu->va_size = arm_smmu_id_size_to_bits(size);18071807-#ifndef CONFIG_64BIT18081808- smmu->va_size = min(32UL, smmu->va_size);18091809-#endif18101810- size = 0;18111706 if (id & ID2_PTFS_4K)18121812- size |= SZ_4K | SZ_2M | SZ_1G;17071707+ smmu->features |= ARM_SMMU_FEAT_FMT_AARCH64_4K;18131708 if (id & ID2_PTFS_16K)18141814- size |= SZ_16K | SZ_32M;17091709+ smmu->features |= ARM_SMMU_FEAT_FMT_AARCH64_16K;18151710 if (id & ID2_PTFS_64K)18161816- size |= SZ_64K | SZ_512M;17111711+ smmu->features |= ARM_SMMU_FEAT_FMT_AARCH64_64K;18171712 }17131713+17141714+ /* Now we've corralled the various formats, what'll it do? */17151715+ size = 0;17161716+ if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH32_S)17171717+ size |= SZ_4K | SZ_64K | SZ_1M | SZ_16M;17181718+ if (smmu->features &17191719+ (ARM_SMMU_FEAT_FMT_AARCH32_L | ARM_SMMU_FEAT_FMT_AARCH64_4K))17201720+ size |= SZ_4K | SZ_2M | SZ_1G;17211721+ if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_16K)17221722+ size |= SZ_16K | SZ_32M;17231723+ if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_64K)17241724+ size |= SZ_64K | SZ_512M;1818172518191726 arm_smmu_ops.pgsize_bitmap &= size;18201727 dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n", size);···18391728 return 0;18401729}1841173017311731+struct arm_smmu_match_data {17321732+ enum arm_smmu_arch_version version;17331733+ enum arm_smmu_implementation model;17341734+};17351735+17361736+#define ARM_SMMU_MATCH_DATA(name, ver, imp) \17371737+static struct arm_smmu_match_data name = { .version = ver, .model = imp }17381738+17391739+ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU);17401740+ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU);17411741+ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU);17421742+ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500);17431743+ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2);17441744+18421745static const struct of_device_id arm_smmu_of_match[] = {18431843- { .compatible = "arm,smmu-v1", .data = (void *)ARM_SMMU_V1 },18441844- { .compatible = "arm,smmu-v2", .data = (void *)ARM_SMMU_V2 },18451845- { .compatible = "arm,mmu-400", .data = (void *)ARM_SMMU_V1 },18461846- { .compatible = "arm,mmu-401", .data = (void *)ARM_SMMU_V1 },18471847- { .compatible = "arm,mmu-500", .data = (void *)ARM_SMMU_V2 },17461746+ { .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 },17471747+ { .compatible = "arm,smmu-v2", .data = &smmu_generic_v2 },17481748+ { .compatible = "arm,mmu-400", .data = &smmu_generic_v1 },17491749+ { .compatible = "arm,mmu-401", .data = &arm_mmu401 },17501750+ { .compatible = "arm,mmu-500", .data = &arm_mmu500 },17511751+ { .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 },18481752 { },18491753};18501754MODULE_DEVICE_TABLE(of, arm_smmu_of_match);···18671741static int arm_smmu_device_dt_probe(struct platform_device *pdev)18681742{18691743 const struct of_device_id *of_id;17441744+ const struct arm_smmu_match_data *data;18701745 struct resource *res;18711746 struct arm_smmu_device *smmu;18721747 struct device *dev = &pdev->dev;···18831756 smmu->dev = dev;1884175718851758 of_id = of_match_node(arm_smmu_of_match, dev->of_node);18861886- smmu->version = (enum arm_smmu_arch_version)of_id->data;17591759+ data = of_id->data;17601760+ smmu->version = data->version;17611761+ smmu->model = data->model;1887176218881763 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);18891764 smmu->base = devm_ioremap_resource(dev, res);···1951182219521823 parse_driver_options(smmu);1953182419541954- if (smmu->version > ARM_SMMU_V1 &&18251825+ if (smmu->version == ARM_SMMU_V2 &&19551826 smmu->num_context_banks != smmu->num_context_irqs) {19561827 dev_err(dev,19571828 "found only %d context interrupt(s) but %d required\n",