Skip to content

Commit 4c00889

Browse files
committed
Merge branch 'arm/smmu' into arm/mediatek
2 parents 1ee9feb + dbe8e6a commit 4c00889

29 files changed

+1943
-1043
lines changed

MAINTAINERS

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,8 +1350,7 @@ M: Will Deacon <[email protected]>
13501350
R: Robin Murphy <[email protected]>
13511351
L: [email protected] (moderated for non-subscribers)
13521352
S: Maintained
1353-
F: drivers/iommu/arm-smmu.c
1354-
F: drivers/iommu/arm-smmu-v3.c
1353+
F: drivers/iommu/arm-smmu*
13551354
F: drivers/iommu/io-pgtable-arm.c
13561355
F: drivers/iommu/io-pgtable-arm-v7s.c
13571356

drivers/gpu/drm/panfrost/panfrost_mmu.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ void panfrost_mmu_unmap(struct panfrost_gem_object *bo)
222222
size_t unmapped_page;
223223
size_t pgsize = get_pgsize(iova, len - unmapped_len);
224224

225-
unmapped_page = ops->unmap(ops, iova, pgsize);
225+
unmapped_page = ops->unmap(ops, iova, pgsize, NULL);
226226
if (!unmapped_page)
227227
break;
228228

@@ -247,20 +247,28 @@ static void mmu_tlb_inv_context_s1(void *cookie)
247247
mmu_hw_do_operation(pfdev, 0, 0, ~0UL, AS_COMMAND_FLUSH_MEM);
248248
}
249249

250-
static void mmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
251-
size_t granule, bool leaf, void *cookie)
252-
{}
253-
254250
static void mmu_tlb_sync_context(void *cookie)
255251
{
256252
//struct panfrost_device *pfdev = cookie;
257253
// TODO: Wait 1000 GPU cycles for HW_ISSUE_6367/T60X
258254
}
259255

260-
static const struct iommu_gather_ops mmu_tlb_ops = {
256+
static void mmu_tlb_flush_walk(unsigned long iova, size_t size, size_t granule,
257+
void *cookie)
258+
{
259+
mmu_tlb_sync_context(cookie);
260+
}
261+
262+
static void mmu_tlb_flush_leaf(unsigned long iova, size_t size, size_t granule,
263+
void *cookie)
264+
{
265+
mmu_tlb_sync_context(cookie);
266+
}
267+
268+
static const struct iommu_flush_ops mmu_tlb_ops = {
261269
.tlb_flush_all = mmu_tlb_inv_context_s1,
262-
.tlb_add_flush = mmu_tlb_inv_range_nosync,
263-
.tlb_sync = mmu_tlb_sync_context,
270+
.tlb_flush_walk = mmu_tlb_flush_walk,
271+
.tlb_flush_leaf = mmu_tlb_flush_leaf,
264272
};
265273

266274
static const char *access_type_name(struct panfrost_device *pfdev,

drivers/iommu/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
1313
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
1414
obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
1515
obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
16-
obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
16+
obj-$(CONFIG_ARM_SMMU) += arm-smmu.o arm-smmu-impl.o
1717
obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
1818
obj-$(CONFIG_DMAR_TABLE) += dmar.o
1919
obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o

drivers/iommu/amd_iommu.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3055,7 +3055,8 @@ static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
30553055
}
30563056

30573057
static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
3058-
size_t page_size)
3058+
size_t page_size,
3059+
struct iommu_iotlb_gather *gather)
30593060
{
30603061
struct protection_domain *domain = to_pdomain(dom);
30613062
size_t unmap_size;
@@ -3196,9 +3197,10 @@ static void amd_iommu_flush_iotlb_all(struct iommu_domain *domain)
31963197
domain_flush_complete(dom);
31973198
}
31983199

3199-
static void amd_iommu_iotlb_range_add(struct iommu_domain *domain,
3200-
unsigned long iova, size_t size)
3200+
static void amd_iommu_iotlb_sync(struct iommu_domain *domain,
3201+
struct iommu_iotlb_gather *gather)
32013202
{
3203+
amd_iommu_flush_iotlb_all(domain);
32023204
}
32033205

32043206
const struct iommu_ops amd_iommu_ops = {
@@ -3219,8 +3221,7 @@ const struct iommu_ops amd_iommu_ops = {
32193221
.is_attach_deferred = amd_iommu_is_attach_deferred,
32203222
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
32213223
.flush_iotlb_all = amd_iommu_flush_iotlb_all,
3222-
.iotlb_range_add = amd_iommu_iotlb_range_add,
3223-
.iotlb_sync = amd_iommu_flush_iotlb_all,
3224+
.iotlb_sync = amd_iommu_iotlb_sync,
32243225
};
32253226

32263227
/*****************************************************************************

drivers/iommu/arm-smmu-impl.c

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
// Miscellaneous Arm SMMU implementation and integration quirks
3+
// Copyright (C) 2019 Arm Limited
4+
5+
#define pr_fmt(fmt) "arm-smmu: " fmt
6+
7+
#include <linux/bitfield.h>
8+
#include <linux/of.h>
9+
10+
#include "arm-smmu.h"
11+
12+
13+
static int arm_smmu_gr0_ns(int offset)
14+
{
15+
switch(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;
23+
default:
24+
return offset;
25+
}
26+
}
27+
28+
static u32 arm_smmu_read_ns(struct arm_smmu_device *smmu, int page,
29+
int offset)
30+
{
31+
if (page == ARM_SMMU_GR0)
32+
offset = arm_smmu_gr0_ns(offset);
33+
return readl_relaxed(arm_smmu_page(smmu, page) + offset);
34+
}
35+
36+
static void arm_smmu_write_ns(struct arm_smmu_device *smmu, int page,
37+
int offset, u32 val)
38+
{
39+
if (page == ARM_SMMU_GR0)
40+
offset = arm_smmu_gr0_ns(offset);
41+
writel_relaxed(val, arm_smmu_page(smmu, page) + offset);
42+
}
43+
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,
48+
};
49+
50+
51+
struct cavium_smmu {
52+
struct arm_smmu_device smmu;
53+
u32 id_base;
54+
};
55+
56+
static int cavium_cfg_probe(struct arm_smmu_device *smmu)
57+
{
58+
static atomic_t context_count = ATOMIC_INIT(0);
59+
struct cavium_smmu *cs = container_of(smmu, struct cavium_smmu, smmu);
60+
/*
61+
* Cavium CN88xx erratum #27704.
62+
* Ensure ASID and VMID allocation is unique across all SMMUs in
63+
* the system.
64+
*/
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");
67+
68+
return 0;
69+
}
70+
71+
static int cavium_init_context(struct arm_smmu_domain *smmu_domain)
72+
{
73+
struct cavium_smmu *cs = container_of(smmu_domain->smmu,
74+
struct cavium_smmu, smmu);
75+
76+
if (smmu_domain->stage == ARM_SMMU_DOMAIN_S2)
77+
smmu_domain->cfg.vmid += cs->id_base;
78+
else
79+
smmu_domain->cfg.asid += cs->id_base;
80+
81+
return 0;
82+
}
83+
84+
static const struct arm_smmu_impl cavium_impl = {
85+
.cfg_probe = cavium_cfg_probe,
86+
.init_context = cavium_init_context,
87+
};
88+
89+
static struct arm_smmu_device *cavium_smmu_impl_init(struct arm_smmu_device *smmu)
90+
{
91+
struct cavium_smmu *cs;
92+
93+
cs = devm_kzalloc(smmu->dev, sizeof(*cs), GFP_KERNEL);
94+
if (!cs)
95+
return ERR_PTR(-ENOMEM);
96+
97+
cs->smmu = *smmu;
98+
cs->smmu.impl = &cavium_impl;
99+
100+
devm_kfree(smmu->dev, smmu);
101+
102+
return &cs->smmu;
103+
}
104+
105+
106+
#define ARM_MMU500_ACTLR_CPRE (1 << 1)
107+
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)
111+
112+
static int arm_mmu500_reset(struct arm_smmu_device *smmu)
113+
{
114+
u32 reg, major;
115+
int i;
116+
/*
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...
120+
*/
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);
124+
if (major >= 2)
125+
reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
126+
/*
127+
* Allow unmatched Stream IDs to allocate bypass
128+
* TLB entries for reduced latency.
129+
*/
130+
reg |= ARM_MMU500_ACR_SMTNMB_TLBEN | ARM_MMU500_ACR_S2CRB_TLBEN;
131+
arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_sACR, reg);
132+
133+
/*
134+
* Disable MMU-500's not-particularly-beneficial next-page
135+
* prefetcher for the sake of errata #841119 and #826419.
136+
*/
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);
141+
}
142+
143+
return 0;
144+
}
145+
146+
static const struct arm_smmu_impl arm_mmu500_impl = {
147+
.reset = arm_mmu500_reset,
148+
};
149+
150+
151+
struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
152+
{
153+
/*
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.
158+
*/
159+
switch (smmu->model) {
160+
case ARM_MMU500:
161+
smmu->impl = &arm_mmu500_impl;
162+
break;
163+
case CAVIUM_SMMUV2:
164+
return cavium_smmu_impl_init(smmu);
165+
default:
166+
break;
167+
}
168+
169+
if (of_property_read_bool(smmu->dev->of_node,
170+
"calxeda,smmu-secure-config-access"))
171+
smmu->impl = &calxeda_impl;
172+
173+
return smmu;
174+
}

0 commit comments

Comments
 (0)