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 ;
@@ -222,6 +224,7 @@ struct apple_dart {
222224 u32 num_streams ;
223225 u32 supports_bypass : 1 ;
224226 u32 locked : 1 ;
227+ u32 four_level : 1 ;
225228
226229 struct iommu_group * sid2group [DART_MAX_STREAMS ];
227230 struct iommu_device iommu ;
@@ -310,14 +313,17 @@ static struct apple_dart_domain *to_dart_domain(struct iommu_domain *dom)
310313}
311314
312315static void
313- apple_dart_hw_enable_translation (struct apple_dart_stream_map * stream_map )
316+ apple_dart_hw_enable_translation (struct apple_dart_stream_map * stream_map , int levels )
314317{
315318 struct apple_dart * dart = stream_map -> dart ;
316319 int sid ;
317320
321+ WARN_ON (levels != 3 && levels != 4 );
322+ WARN_ON (levels == 4 && !dart -> four_level );
318323 WARN_ON (stream_map -> dart -> locked );
319324 for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams )
320- writel (dart -> hw -> tcr_enabled , dart -> regs + DART_TCR (dart , sid ));
325+ writel (dart -> hw -> tcr_enabled | (levels == 4 ? dart -> hw -> tcr_4level : 0 ),
326+ dart -> regs + DART_TCR (dart , sid ));
321327}
322328
323329static void apple_dart_hw_disable_dma (struct apple_dart_stream_map * stream_map )
@@ -669,7 +675,8 @@ apple_dart_setup_translation(struct apple_dart_domain *domain,
669675 for (; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
670676 apple_dart_hw_clear_ttbr (stream_map , i );
671677
672- apple_dart_hw_enable_translation (stream_map );
678+ apple_dart_hw_enable_translation (stream_map ,
679+ pgtbl_cfg -> apple_dart_cfg .n_levels );
673680 }
674681 stream_map -> dart -> hw -> invalidate_tlb (stream_map );
675682}
@@ -753,6 +760,19 @@ static int apple_dart_finalize_domain(struct apple_dart_domain *dart_domain,
753760 ttbr = readl (dart -> regs + DART_TTBR (dart , sid , 0 ));
754761
755762 WARN_ON (!(ttbr & dart -> hw -> ttbr_valid ));
763+
764+ /* If the DART is locked, we need to keep the translation level count. */
765+ if (dart -> hw -> tcr_4level && dart -> ias > 36 ) {
766+ if (readl (dart -> regs + DART_TCR (dart , sid )) & dart -> hw -> tcr_4level ) {
767+ if (dart -> ias < 37 ) {
768+ dev_info (dart -> dev , "Expanded to ias=37 due to lock\n" );
769+ pgtbl_cfg .ias = 37 ;
770+ }
771+ } else if (dart -> ias > 36 ) {
772+ dev_info (dart -> dev , "Limited to ias=36 due to lock\n" );
773+ pgtbl_cfg .ias = 36 ;
774+ }
775+ }
756776 }
757777
758778 dart_domain -> pgtbl_ops = alloc_io_pgtable_ops (dart -> hw -> fmt , & pgtbl_cfg ,
@@ -765,7 +785,7 @@ static int apple_dart_finalize_domain(struct apple_dart_domain *dart_domain,
765785 dart_domain -> domain .pgsize_bitmap = pgtbl_cfg .pgsize_bitmap ;
766786 dart_domain -> domain .geometry .aperture_start = 0 ;
767787 dart_domain -> domain .geometry .aperture_end =
768- (dma_addr_t )DMA_BIT_MASK (dart -> ias );
788+ (dma_addr_t )DMA_BIT_MASK (pgtbl_cfg . ias );
769789 dart_domain -> domain .geometry .force_aperture = true;
770790
771791 dart_domain -> finalized = true;
@@ -1336,6 +1356,7 @@ static int apple_dart_probe(struct platform_device *pdev)
13361356 dart -> ias = FIELD_GET (DART_T8110_PARAMS3_VA_WIDTH , dart_params [2 ]);
13371357 dart -> oas = FIELD_GET (DART_T8110_PARAMS3_PA_WIDTH , dart_params [2 ]);
13381358 dart -> num_streams = FIELD_GET (DART_T8110_PARAMS4_NUM_SIDS , dart_params [3 ]);
1359+ dart -> four_level = dart -> ias > 36 ;
13391360 break ;
13401361 }
13411362
@@ -1373,9 +1394,9 @@ static int apple_dart_probe(struct platform_device *pdev)
13731394
13741395 dev_info (
13751396 & pdev -> dev ,
1376- "DART [pagesize %x, %d streams, bypass support: %d, bypass forced: %d, locked: %d] initialized\n" ,
1397+ "DART [pagesize %x, %d streams, bypass support: %d, bypass forced: %d, locked: %d, AS %d -> %d ] initialized\n" ,
13771398 dart -> pgsize , dart -> num_streams , dart -> supports_bypass ,
1378- dart -> pgsize > PAGE_SIZE , dart -> locked );
1399+ dart -> pgsize > PAGE_SIZE , dart -> locked , dart -> ias , dart -> oas );
13791400 return 0 ;
13801401
13811402err_sysfs_remove :
@@ -1499,6 +1520,7 @@ static const struct apple_dart_hw apple_dart_hw_t8110 = {
14991520 .tcr_enabled = DART_T8110_TCR_TRANSLATE_ENABLE ,
15001521 .tcr_disabled = 0 ,
15011522 .tcr_bypass = DART_T8110_TCR_BYPASS_DAPF | DART_T8110_TCR_BYPASS_DART ,
1523+ .tcr_4level = DART_T8110_TCR_FOUR_LEVEL ,
15021524
15031525 .ttbr = DART_T8110_TTBR ,
15041526 .ttbr_valid = DART_T8110_TTBR_VALID ,
0 commit comments