Skip to content

Commit d8bcc87

Browse files
marcanjoergroedel
authored andcommitted
iommu: dart: Add t8110 DART support
Now that we have the driver properly parameterized, we can add support for T8110 DARTs. These DARTs drop the multiple TTBRs (which only make sense with legacy 4K page platforms) and instead add support for new features and more stream IDs. The register layout is different, but the pagetable format is the same as T6000. Reviewed-by: Sven Peter <[email protected]> Signed-off-by: Hector Martin <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent b76c68f commit d8bcc87

File tree

1 file changed

+200
-5
lines changed

1 file changed

+200
-5
lines changed

drivers/iommu/apple-dart.c

Lines changed: 200 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,62 @@
8585
#define DART_T8020_TTBR_ADDR_FIELD_SHIFT 0
8686
#define DART_T8020_TTBR_SHIFT 12
8787

88+
/* T8110 registers */
89+
90+
#define DART_T8110_PARAMS3 0x08
91+
#define DART_T8110_PARAMS3_PA_WIDTH GENMASK(29, 24)
92+
#define DART_T8110_PARAMS3_VA_WIDTH GENMASK(21, 16)
93+
#define DART_T8110_PARAMS3_VER_MAJ GENMASK(15, 8)
94+
#define DART_T8110_PARAMS3_VER_MIN GENMASK(7, 0)
95+
96+
#define DART_T8110_PARAMS4 0x0c
97+
#define DART_T8110_PARAMS4_NUM_CLIENTS GENMASK(24, 16)
98+
#define DART_T8110_PARAMS4_NUM_SIDS GENMASK(8, 0)
99+
100+
#define DART_T8110_TLB_CMD 0x80
101+
#define DART_T8110_TLB_CMD_BUSY BIT(31)
102+
#define DART_T8110_TLB_CMD_OP GENMASK(10, 8)
103+
#define DART_T8110_TLB_CMD_OP_FLUSH_ALL 0
104+
#define DART_T8110_TLB_CMD_OP_FLUSH_SID 1
105+
#define DART_T8110_TLB_CMD_STREAM GENMASK(7, 0)
106+
107+
#define DART_T8110_ERROR 0x100
108+
#define DART_T8110_ERROR_STREAM GENMASK(27, 20)
109+
#define DART_T8110_ERROR_CODE GENMASK(14, 0)
110+
#define DART_T8110_ERROR_FLAG BIT(31)
111+
112+
#define DART_T8110_ERROR_MASK 0x104
113+
114+
#define DART_T8110_ERROR_READ_FAULT BIT(4)
115+
#define DART_T8110_ERROR_WRITE_FAULT BIT(3)
116+
#define DART_T8110_ERROR_NO_PTE BIT(3)
117+
#define DART_T8110_ERROR_NO_PMD BIT(2)
118+
#define DART_T8110_ERROR_NO_PGD BIT(1)
119+
#define DART_T8110_ERROR_NO_TTBR BIT(0)
120+
121+
#define DART_T8110_ERROR_ADDR_LO 0x170
122+
#define DART_T8110_ERROR_ADDR_HI 0x174
123+
124+
#define DART_T8110_PROTECT 0x200
125+
#define DART_T8110_UNPROTECT 0x204
126+
#define DART_T8110_PROTECT_LOCK 0x208
127+
#define DART_T8110_PROTECT_TTBR_TCR BIT(0)
128+
129+
#define DART_T8110_ENABLE_STREAMS 0xc00
130+
#define DART_T8110_DISABLE_STREAMS 0xc20
131+
132+
#define DART_T8110_TCR 0x1000
133+
#define DART_T8110_TCR_REMAP GENMASK(11, 8)
134+
#define DART_T8110_TCR_REMAP_EN BIT(7)
135+
#define DART_T8110_TCR_BYPASS_DAPF BIT(2)
136+
#define DART_T8110_TCR_BYPASS_DART BIT(1)
137+
#define DART_T8110_TCR_TRANSLATE_ENABLE BIT(0)
138+
139+
#define DART_T8110_TTBR 0x1400
140+
#define DART_T8110_TTBR_VALID BIT(0)
141+
#define DART_T8110_TTBR_ADDR_FIELD_SHIFT 2
142+
#define DART_T8110_TTBR_SHIFT 14
143+
88144
#define DART_TCR(dart, sid) ((dart)->hw->tcr + ((sid) << 2))
89145

90146
#define DART_TTBR(dart, sid, idx) ((dart)->hw->ttbr + \
@@ -93,7 +149,14 @@
93149

94150
struct apple_dart_stream_map;
95151

152+
enum dart_type {
153+
DART_T8020,
154+
DART_T6000,
155+
DART_T8110,
156+
};
157+
96158
struct apple_dart_hw {
159+
enum dart_type type;
97160
irqreturn_t (*irq_handler)(int irq, void *dev);
98161
int (*invalidate_tlb)(struct apple_dart_stream_map *stream_map);
99162

@@ -149,6 +212,8 @@ struct apple_dart {
149212

150213
spinlock_t lock;
151214

215+
u32 ias;
216+
u32 oas;
152217
u32 pgsize;
153218
u32 num_streams;
154219
u32 supports_bypass : 1;
@@ -330,13 +395,58 @@ apple_dart_t8020_hw_stream_command(struct apple_dart_stream_map *stream_map,
330395
return 0;
331396
}
332397

398+
static int
399+
apple_dart_t8110_hw_tlb_command(struct apple_dart_stream_map *stream_map,
400+
u32 command)
401+
{
402+
struct apple_dart *dart = stream_map->dart;
403+
unsigned long flags;
404+
int ret = 0;
405+
int sid;
406+
407+
spin_lock_irqsave(&dart->lock, flags);
408+
409+
for_each_set_bit(sid, stream_map->sidmap, dart->num_streams) {
410+
u32 val = FIELD_PREP(DART_T8110_TLB_CMD_OP, command) |
411+
FIELD_PREP(DART_T8110_TLB_CMD_STREAM, sid);
412+
writel(val, dart->regs + DART_T8110_TLB_CMD);
413+
414+
ret = readl_poll_timeout_atomic(
415+
dart->regs + DART_T8110_TLB_CMD, val,
416+
!(val & DART_T8110_TLB_CMD_BUSY), 1,
417+
DART_STREAM_COMMAND_BUSY_TIMEOUT);
418+
419+
if (ret)
420+
break;
421+
422+
}
423+
424+
spin_unlock_irqrestore(&dart->lock, flags);
425+
426+
if (ret) {
427+
dev_err(stream_map->dart->dev,
428+
"busy bit did not clear after command %x for stream %d\n",
429+
command, sid);
430+
return ret;
431+
}
432+
433+
return 0;
434+
}
435+
333436
static int
334437
apple_dart_t8020_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
335438
{
336439
return apple_dart_t8020_hw_stream_command(
337440
stream_map, DART_T8020_STREAM_COMMAND_INVALIDATE);
338441
}
339442

443+
static int
444+
apple_dart_t8110_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map)
445+
{
446+
return apple_dart_t8110_hw_tlb_command(
447+
stream_map, DART_T8110_TLB_CMD_OP_FLUSH_SID);
448+
}
449+
340450
static int apple_dart_hw_reset(struct apple_dart *dart)
341451
{
342452
u32 config;
@@ -363,6 +473,9 @@ static int apple_dart_hw_reset(struct apple_dart *dart)
363473
/* clear any pending errors before the interrupt is unmasked */
364474
writel(readl(dart->regs + dart->hw->error), dart->regs + dart->hw->error);
365475

476+
if (dart->hw->type == DART_T8110)
477+
writel(0, dart->regs + DART_T8110_ERROR_MASK);
478+
366479
return dart->hw->invalidate_tlb(&stream_map);
367480
}
368481

@@ -478,8 +591,8 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
478591

479592
pgtbl_cfg = (struct io_pgtable_cfg){
480593
.pgsize_bitmap = dart->pgsize,
481-
.ias = 32,
482-
.oas = dart->hw->oas,
594+
.ias = dart->ias,
595+
.oas = dart->oas,
483596
.coherent_walk = 1,
484597
.iommu_dev = dart->dev,
485598
};
@@ -493,7 +606,7 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
493606

494607
domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
495608
domain->geometry.aperture_start = 0;
496-
domain->geometry.aperture_end = DMA_BIT_MASK(32);
609+
domain->geometry.aperture_end = (dma_addr_t)DMA_BIT_MASK(dart->ias);
497610
domain->geometry.force_aperture = true;
498611

499612
dart_domain->finalized = true;
@@ -880,10 +993,49 @@ static irqreturn_t apple_dart_t8020_irq(int irq, void *dev)
880993
return IRQ_HANDLED;
881994
}
882995

996+
static irqreturn_t apple_dart_t8110_irq(int irq, void *dev)
997+
{
998+
struct apple_dart *dart = dev;
999+
const char *fault_name = NULL;
1000+
u32 error = readl(dart->regs + DART_T8110_ERROR);
1001+
u32 error_code = FIELD_GET(DART_T8110_ERROR_CODE, error);
1002+
u32 addr_lo = readl(dart->regs + DART_T8110_ERROR_ADDR_LO);
1003+
u32 addr_hi = readl(dart->regs + DART_T8110_ERROR_ADDR_HI);
1004+
u64 addr = addr_lo | (((u64)addr_hi) << 32);
1005+
u8 stream_idx = FIELD_GET(DART_T8110_ERROR_STREAM, error);
1006+
1007+
if (!(error & DART_T8110_ERROR_FLAG))
1008+
return IRQ_NONE;
1009+
1010+
/* there should only be a single bit set but let's use == to be sure */
1011+
if (error_code == DART_T8110_ERROR_READ_FAULT)
1012+
fault_name = "READ FAULT";
1013+
else if (error_code == DART_T8110_ERROR_WRITE_FAULT)
1014+
fault_name = "WRITE FAULT";
1015+
else if (error_code == DART_T8110_ERROR_NO_PTE)
1016+
fault_name = "NO PTE FOR IOVA";
1017+
else if (error_code == DART_T8110_ERROR_NO_PMD)
1018+
fault_name = "NO PMD FOR IOVA";
1019+
else if (error_code == DART_T8110_ERROR_NO_PGD)
1020+
fault_name = "NO PGD FOR IOVA";
1021+
else if (error_code == DART_T8110_ERROR_NO_TTBR)
1022+
fault_name = "NO TTBR FOR IOVA";
1023+
else
1024+
fault_name = "unknown";
1025+
1026+
dev_err_ratelimited(
1027+
dart->dev,
1028+
"translation fault: status:0x%x stream:%d code:0x%x (%s) at 0x%llx",
1029+
error, stream_idx, error_code, fault_name, addr);
1030+
1031+
writel(error, dart->regs + DART_T8110_ERROR);
1032+
return IRQ_HANDLED;
1033+
}
1034+
8831035
static int apple_dart_probe(struct platform_device *pdev)
8841036
{
8851037
int ret;
886-
u32 dart_params[2];
1038+
u32 dart_params[4];
8871039
struct resource *res;
8881040
struct apple_dart *dart;
8891041
struct device *dev = &pdev->dev;
@@ -923,7 +1075,22 @@ static int apple_dart_probe(struct platform_device *pdev)
9231075
dart->pgsize = 1 << FIELD_GET(DART_PARAMS1_PAGE_SHIFT, dart_params[0]);
9241076
dart->supports_bypass = dart_params[1] & DART_PARAMS2_BYPASS_SUPPORT;
9251077

926-
dart->num_streams = dart->hw->max_sid_count;
1078+
switch (dart->hw->type) {
1079+
case DART_T8020:
1080+
case DART_T6000:
1081+
dart->ias = 32;
1082+
dart->oas = dart->hw->oas;
1083+
dart->num_streams = dart->hw->max_sid_count;
1084+
break;
1085+
1086+
case DART_T8110:
1087+
dart_params[2] = readl(dart->regs + DART_T8110_PARAMS3);
1088+
dart_params[3] = readl(dart->regs + DART_T8110_PARAMS4);
1089+
dart->ias = FIELD_GET(DART_T8110_PARAMS3_VA_WIDTH, dart_params[2]);
1090+
dart->oas = FIELD_GET(DART_T8110_PARAMS3_PA_WIDTH, dart_params[2]);
1091+
dart->num_streams = FIELD_GET(DART_T8110_PARAMS4_NUM_SIDS, dart_params[3]);
1092+
break;
1093+
}
9271094

9281095
if (dart->num_streams > DART_MAX_STREAMS) {
9291096
dev_err(&pdev->dev, "Too many streams (%d > %d)\n",
@@ -986,6 +1153,7 @@ static int apple_dart_remove(struct platform_device *pdev)
9861153
}
9871154

9881155
static const struct apple_dart_hw apple_dart_hw_t8103 = {
1156+
.type = DART_T8020,
9891157
.irq_handler = apple_dart_t8020_irq,
9901158
.invalidate_tlb = apple_dart_t8020_hw_invalidate_tlb,
9911159
.oas = 36,
@@ -1010,6 +1178,7 @@ static const struct apple_dart_hw apple_dart_hw_t8103 = {
10101178
.ttbr_count = 4,
10111179
};
10121180
static const struct apple_dart_hw apple_dart_hw_t6000 = {
1181+
.type = DART_T6000,
10131182
.irq_handler = apple_dart_t8020_irq,
10141183
.invalidate_tlb = apple_dart_t8020_hw_invalidate_tlb,
10151184
.oas = 42,
@@ -1034,6 +1203,31 @@ static const struct apple_dart_hw apple_dart_hw_t6000 = {
10341203
.ttbr_count = 4,
10351204
};
10361205

1206+
static const struct apple_dart_hw apple_dart_hw_t8110 = {
1207+
.type = DART_T8110,
1208+
.irq_handler = apple_dart_t8110_irq,
1209+
.invalidate_tlb = apple_dart_t8110_hw_invalidate_tlb,
1210+
.fmt = APPLE_DART2,
1211+
.max_sid_count = 256,
1212+
1213+
.enable_streams = DART_T8110_ENABLE_STREAMS,
1214+
.lock = DART_T8110_PROTECT,
1215+
.lock_bit = DART_T8110_PROTECT_TTBR_TCR,
1216+
1217+
.error = DART_T8110_ERROR,
1218+
1219+
.tcr = DART_T8110_TCR,
1220+
.tcr_enabled = DART_T8110_TCR_TRANSLATE_ENABLE,
1221+
.tcr_disabled = 0,
1222+
.tcr_bypass = DART_T8110_TCR_BYPASS_DAPF | DART_T8110_TCR_BYPASS_DART,
1223+
1224+
.ttbr = DART_T8110_TTBR,
1225+
.ttbr_valid = DART_T8110_TTBR_VALID,
1226+
.ttbr_addr_field_shift = DART_T8110_TTBR_ADDR_FIELD_SHIFT,
1227+
.ttbr_shift = DART_T8110_TTBR_SHIFT,
1228+
.ttbr_count = 1,
1229+
};
1230+
10371231
static __maybe_unused int apple_dart_suspend(struct device *dev)
10381232
{
10391233
struct apple_dart *dart = dev_get_drvdata(dev);
@@ -1075,6 +1269,7 @@ DEFINE_SIMPLE_DEV_PM_OPS(apple_dart_pm_ops, apple_dart_suspend, apple_dart_resum
10751269

10761270
static const struct of_device_id apple_dart_of_match[] = {
10771271
{ .compatible = "apple,t8103-dart", .data = &apple_dart_hw_t8103 },
1272+
{ .compatible = "apple,t8110-dart", .data = &apple_dart_hw_t8110 },
10781273
{ .compatible = "apple,t6000-dart", .data = &apple_dart_hw_t6000 },
10791274
{},
10801275
};

0 commit comments

Comments
 (0)