1 // SPDX-License-Identifier: GPL-2.0-only
2 // Miscellaneous Arm SMMU implementation and integration quirks
3 // Copyright (C) 2019 Arm Limited
5 #define pr_fmt(fmt) "arm-smmu: " fmt
7 #include <linux/bitfield.h>
13 static int arm_smmu_gr0_ns(int offset
)
16 case ARM_SMMU_GR0_sCR0
:
17 case ARM_SMMU_GR0_sACR
:
18 case ARM_SMMU_GR0_sGFSR
:
19 case ARM_SMMU_GR0_sGFSYNR0
:
20 case ARM_SMMU_GR0_sGFSYNR1
:
21 case ARM_SMMU_GR0_sGFSYNR2
:
22 return offset
+ 0x400;
28 static u32
arm_smmu_read_ns(struct arm_smmu_device
*smmu
, int page
,
31 if (page
== ARM_SMMU_GR0
)
32 offset
= arm_smmu_gr0_ns(offset
);
33 return readl_relaxed(arm_smmu_page(smmu
, page
) + offset
);
36 static void arm_smmu_write_ns(struct arm_smmu_device
*smmu
, int page
,
39 if (page
== ARM_SMMU_GR0
)
40 offset
= arm_smmu_gr0_ns(offset
);
41 writel_relaxed(val
, arm_smmu_page(smmu
, page
) + offset
);
44 /* Since we don't care for sGFAR, we can do without 64-bit accessors */
45 static const struct arm_smmu_impl calxeda_impl
= {
46 .read_reg
= arm_smmu_read_ns
,
47 .write_reg
= arm_smmu_write_ns
,
52 struct arm_smmu_device smmu
;
56 static int cavium_cfg_probe(struct arm_smmu_device
*smmu
)
58 static atomic_t context_count
= ATOMIC_INIT(0);
59 struct cavium_smmu
*cs
= container_of(smmu
, struct cavium_smmu
, smmu
);
61 * Cavium CN88xx erratum #27704.
62 * Ensure ASID and VMID allocation is unique across all SMMUs in
65 cs
->id_base
= atomic_fetch_add(smmu
->num_context_banks
, &context_count
);
66 dev_notice(smmu
->dev
, "\tenabling workaround for Cavium erratum 27704\n");
71 static int cavium_init_context(struct arm_smmu_domain
*smmu_domain
)
73 struct cavium_smmu
*cs
= container_of(smmu_domain
->smmu
,
74 struct cavium_smmu
, smmu
);
76 if (smmu_domain
->stage
== ARM_SMMU_DOMAIN_S2
)
77 smmu_domain
->cfg
.vmid
+= cs
->id_base
;
79 smmu_domain
->cfg
.asid
+= cs
->id_base
;
84 static const struct arm_smmu_impl cavium_impl
= {
85 .cfg_probe
= cavium_cfg_probe
,
86 .init_context
= cavium_init_context
,
89 static struct arm_smmu_device
*cavium_smmu_impl_init(struct arm_smmu_device
*smmu
)
91 struct cavium_smmu
*cs
;
93 cs
= devm_kzalloc(smmu
->dev
, sizeof(*cs
), GFP_KERNEL
);
95 return ERR_PTR(-ENOMEM
);
98 cs
->smmu
.impl
= &cavium_impl
;
100 devm_kfree(smmu
->dev
, smmu
);
106 #define ARM_MMU500_ACTLR_CPRE (1 << 1)
108 #define ARM_MMU500_ACR_CACHE_LOCK (1 << 26)
109 #define ARM_MMU500_ACR_S2CRB_TLBEN (1 << 10)
110 #define ARM_MMU500_ACR_SMTNMB_TLBEN (1 << 8)
112 int arm_mmu500_reset(struct arm_smmu_device
*smmu
)
117 * On MMU-500 r2p0 onwards we need to clear ACR.CACHE_LOCK before
118 * writes to the context bank ACTLRs will stick. And we just hope that
119 * Secure has also cleared SACR.CACHE_LOCK for this to take effect...
121 reg
= arm_smmu_gr0_read(smmu
, ARM_SMMU_GR0_ID7
);
122 major
= FIELD_GET(ID7_MAJOR
, reg
);
123 reg
= arm_smmu_gr0_read(smmu
, ARM_SMMU_GR0_sACR
);
125 reg
&= ~ARM_MMU500_ACR_CACHE_LOCK
;
127 * Allow unmatched Stream IDs to allocate bypass
128 * TLB entries for reduced latency.
130 reg
|= ARM_MMU500_ACR_SMTNMB_TLBEN
| ARM_MMU500_ACR_S2CRB_TLBEN
;
131 arm_smmu_gr0_write(smmu
, ARM_SMMU_GR0_sACR
, reg
);
134 * Disable MMU-500's not-particularly-beneficial next-page
135 * prefetcher for the sake of errata #841119 and #826419.
137 for (i
= 0; i
< smmu
->num_context_banks
; ++i
) {
138 reg
= arm_smmu_cb_read(smmu
, i
, ARM_SMMU_CB_ACTLR
);
139 reg
&= ~ARM_MMU500_ACTLR_CPRE
;
140 arm_smmu_cb_write(smmu
, i
, ARM_SMMU_CB_ACTLR
, reg
);
146 static const struct arm_smmu_impl arm_mmu500_impl
= {
147 .reset
= arm_mmu500_reset
,
151 struct arm_smmu_device
*arm_smmu_impl_init(struct arm_smmu_device
*smmu
)
154 * We will inevitably have to combine model-specific implementation
155 * quirks with platform-specific integration quirks, but everything
156 * we currently support happens to work out as straightforward
157 * mutually-exclusive assignments.
159 switch (smmu
->model
) {
161 smmu
->impl
= &arm_mmu500_impl
;
164 return cavium_smmu_impl_init(smmu
);
169 if (of_property_read_bool(smmu
->dev
->of_node
,
170 "calxeda,smmu-secure-config-access"))
171 smmu
->impl
= &calxeda_impl
;
173 if (of_device_is_compatible(smmu
->dev
->of_node
, "qcom,sdm845-smmu-500"))
174 return qcom_smmu_impl_init(smmu
);