136136#define DART_T8110_TCR 0x1000
137137#define DART_T8110_TCR_REMAP GENMASK(11, 8)
138138#define DART_T8110_TCR_REMAP_EN BIT(7)
139+ #define DART_T8110_TCR_FOUR_LEVEL BIT(3)
139140#define DART_T8110_TCR_BYPASS_DAPF BIT(2)
140141#define DART_T8110_TCR_BYPASS_DART BIT(1)
141142#define DART_T8110_TCR_TRANSLATE_ENABLE BIT(0)
@@ -180,6 +181,7 @@ struct apple_dart_hw {
180181 u32 tcr_enabled ;
181182 u32 tcr_disabled ;
182183 u32 tcr_bypass ;
184+ u32 tcr_4level ;
183185
184186 u32 ttbr ;
185187 u32 ttbr_valid ;
@@ -224,6 +226,7 @@ struct apple_dart {
224226 u32 supports_bypass : 1 ;
225227 u32 force_bypass : 1 ;
226228 u32 locked : 1 ;
229+ u32 four_level : 1 ;
227230
228231 struct iommu_group * sid2group [DART_MAX_STREAMS ];
229232 struct iommu_device iommu ;
@@ -309,14 +312,17 @@ static struct apple_dart_domain *to_dart_domain(struct iommu_domain *dom)
309312}
310313
311314static void
312- apple_dart_hw_enable_translation (struct apple_dart_stream_map * stream_map )
315+ apple_dart_hw_enable_translation (struct apple_dart_stream_map * stream_map , int levels )
313316{
314317 struct apple_dart * dart = stream_map -> dart ;
315318 int sid ;
316319
320+ WARN_ON (levels != 3 && levels != 4 );
321+ WARN_ON (levels == 4 && !dart -> four_level );
317322 WARN_ON (stream_map -> dart -> locked );
318323 for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams )
319- writel (dart -> hw -> tcr_enabled , dart -> regs + DART_TCR (dart , sid ));
324+ writel (dart -> hw -> tcr_enabled | (levels == 4 ? dart -> hw -> tcr_4level : 0 ),
325+ dart -> regs + DART_TCR (dart , sid ));
320326}
321327
322328static void apple_dart_hw_disable_dma (struct apple_dart_stream_map * stream_map )
@@ -571,7 +577,8 @@ apple_dart_setup_translation(struct apple_dart_domain *domain,
571577 for (; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
572578 apple_dart_hw_clear_ttbr (stream_map , i );
573579
574- apple_dart_hw_enable_translation (stream_map );
580+ apple_dart_hw_enable_translation (stream_map ,
581+ pgtbl_cfg -> apple_dart_cfg .n_levels );
575582 }
576583 stream_map -> dart -> hw -> invalidate_tlb (stream_map );
577584}
@@ -661,6 +668,19 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
661668 phys = ((phys_addr_t ) ttbr ) << dart -> hw -> ttbr_shift ;
662669 pgtbl_cfg .apple_dart_cfg .ttbr [0 ] = phys ;
663670 pgtbl_cfg .quirks |= IO_PGTABLE_QUIRK_APPLE_LOCKED ;
671+
672+ /* If the DART is locked, we need to keep the translation level count. */
673+ if (dart -> hw -> tcr_4level && dart -> ias > 36 ) {
674+ if (readl (dart -> regs + DART_TCR (dart , sid )) & dart -> hw -> tcr_4level ) {
675+ if (dart -> ias < 37 ) {
676+ dev_info (dart -> dev , "Expanded to ias=37 due to lock\n" );
677+ pgtbl_cfg .ias = 37 ;
678+ }
679+ } else if (dart -> ias > 36 ) {
680+ dev_info (dart -> dev , "Limited to ias=36 due to lock\n" );
681+ pgtbl_cfg .ias = 36 ;
682+ }
683+ }
664684 }
665685
666686 dart_domain -> pgtbl_ops =
@@ -672,7 +692,7 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
672692
673693 domain -> pgsize_bitmap = pgtbl_cfg .pgsize_bitmap ;
674694 domain -> geometry .aperture_start = 0 ;
675- domain -> geometry .aperture_end = (dma_addr_t )DMA_BIT_MASK (dart -> ias );
695+ domain -> geometry .aperture_end = (dma_addr_t )DMA_BIT_MASK (pgtbl_cfg . ias );
676696 domain -> geometry .force_aperture = true;
677697
678698 dart_domain -> finalized = true;
@@ -1211,6 +1231,7 @@ static int apple_dart_probe(struct platform_device *pdev)
12111231 dart -> ias = FIELD_GET (DART_T8110_PARAMS3_VA_WIDTH , dart_params [2 ]);
12121232 dart -> oas = FIELD_GET (DART_T8110_PARAMS3_PA_WIDTH , dart_params [2 ]);
12131233 dart -> num_streams = FIELD_GET (DART_T8110_PARAMS4_NUM_SIDS , dart_params [3 ]);
1234+ dart -> four_level = dart -> ias > 36 ;
12141235 break ;
12151236 }
12161237
@@ -1250,8 +1271,9 @@ static int apple_dart_probe(struct platform_device *pdev)
12501271
12511272 dev_info (
12521273 & pdev -> dev ,
1253- "DART [pagesize %x, %d streams, bypass support: %d, bypass forced: %d, locked: %d] initialized\n" ,
1254- dart -> pgsize , dart -> num_streams , dart -> supports_bypass , dart -> force_bypass , dart -> locked );
1274+ "DART [pagesize %x, %d streams, bypass support: %d, bypass forced: %d, locked: %d, AS %d -> %d] initialized\n" ,
1275+ dart -> pgsize , dart -> num_streams , dart -> supports_bypass , dart -> force_bypass , dart -> locked ,
1276+ dart -> ias , dart -> oas );
12551277 return 0 ;
12561278
12571279err_sysfs_remove :
@@ -1350,6 +1372,7 @@ static const struct apple_dart_hw apple_dart_hw_t8110 = {
13501372 .tcr_enabled = DART_T8110_TCR_TRANSLATE_ENABLE ,
13511373 .tcr_disabled = 0 ,
13521374 .tcr_bypass = DART_T8110_TCR_BYPASS_DAPF | DART_T8110_TCR_BYPASS_DART ,
1375+ .tcr_4level = DART_T8110_TCR_FOUR_LEVEL ,
13531376
13541377 .ttbr = DART_T8110_TTBR ,
13551378 .ttbr_valid = DART_T8110_TTBR_VALID ,
0 commit comments