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 ;
@@ -312,13 +315,16 @@ static struct apple_dart_domain *to_dart_domain(struct iommu_domain *dom)
312315}
313316
314317static void
315- apple_dart_hw_enable_translation (struct apple_dart_stream_map * stream_map )
318+ apple_dart_hw_enable_translation (struct apple_dart_stream_map * stream_map , int levels )
316319{
317320 struct apple_dart * dart = stream_map -> dart ;
318321 int sid ;
319322
323+ WARN_ON (levels != 3 && levels != 4 );
324+ WARN_ON (levels == 4 && !dart -> four_level );
320325 for_each_set_bit (sid , stream_map -> sidmap , dart -> num_streams )
321- writel (dart -> hw -> tcr_enabled , dart -> regs + DART_TCR (dart , sid ));
326+ writel (dart -> hw -> tcr_enabled | (levels == 4 ? dart -> hw -> tcr_4level : 0 ),
327+ dart -> regs + DART_TCR (dart , sid ));
322328}
323329
324330static void apple_dart_hw_disable_dma (struct apple_dart_stream_map * stream_map )
@@ -653,7 +659,8 @@ apple_dart_setup_translation(struct apple_dart_domain *domain,
653659 for (; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
654660 apple_dart_hw_clear_ttbr (stream_map , i );
655661
656- apple_dart_hw_enable_translation (stream_map );
662+ apple_dart_hw_enable_translation (stream_map ,
663+ pgtbl_cfg -> apple_dart_cfg .n_levels );
657664 stream_map -> dart -> hw -> invalidate_tlb (stream_map );
658665}
659666
@@ -719,6 +726,19 @@ static int apple_dart_finalize_domain(struct apple_dart_domain *dart_domain,
719726 ttbr = readl (dart -> regs + DART_TTBR (dart , sid , 0 ));
720727
721728 WARN_ON (!(ttbr & dart -> hw -> ttbr_valid ));
729+
730+ /* If the DART is locked, we need to keep the translation level count. */
731+ if (dart -> hw -> tcr_4level && dart -> ias > 36 ) {
732+ if (readl (dart -> regs + DART_TCR (dart , sid )) & dart -> hw -> tcr_4level ) {
733+ if (dart -> ias < 37 ) {
734+ dev_info (dart -> dev , "Expanded to ias=37 due to lock\n" );
735+ pgtbl_cfg .ias = 37 ;
736+ }
737+ } else if (dart -> ias > 36 ) {
738+ dev_info (dart -> dev , "Limited to ias=36 due to lock\n" );
739+ pgtbl_cfg .ias = 36 ;
740+ }
741+ }
722742 }
723743
724744 dart_domain -> pgtbl_ops = alloc_io_pgtable_ops (dart -> hw -> fmt , & pgtbl_cfg ,
@@ -731,7 +751,7 @@ static int apple_dart_finalize_domain(struct apple_dart_domain *dart_domain,
731751 dart_domain -> domain .pgsize_bitmap = pgtbl_cfg .pgsize_bitmap ;
732752 dart_domain -> domain .geometry .aperture_start = 0 ;
733753 dart_domain -> domain .geometry .aperture_end =
734- (dma_addr_t )DMA_BIT_MASK (dart -> ias );
754+ (dma_addr_t )DMA_BIT_MASK (pgtbl_cfg . ias );
735755 dart_domain -> domain .geometry .force_aperture = true;
736756
737757 dart_domain -> finalized = true;
@@ -1337,6 +1357,7 @@ static int apple_dart_probe(struct platform_device *pdev)
13371357 dart -> ias = FIELD_GET (DART_T8110_PARAMS3_VA_WIDTH , dart_params [2 ]);
13381358 dart -> oas = FIELD_GET (DART_T8110_PARAMS3_PA_WIDTH , dart_params [2 ]);
13391359 dart -> num_streams = FIELD_GET (DART_T8110_PARAMS4_NUM_SIDS , dart_params [3 ]);
1360+ dart -> four_level = dart -> ias > 36 ;
13401361 break ;
13411362 }
13421363
@@ -1379,9 +1400,9 @@ static int apple_dart_probe(struct platform_device *pdev)
13791400
13801401 dev_info (
13811402 & pdev -> dev ,
1382- "DART [pagesize %x, %d streams, bypass support: %d, bypass forced: %d, locked: %d] initialized\n" ,
1403+ "DART [pagesize %x, %d streams, bypass support: %d, bypass forced: %d, locked: %d, AS %d -> %d ] initialized\n" ,
13831404 dart -> pgsize , dart -> num_streams , dart -> supports_bypass ,
1384- dart -> pgsize > PAGE_SIZE , dart -> locked );
1405+ dart -> pgsize > PAGE_SIZE , dart -> locked , dart -> ias , dart -> oas );
13851406 return 0 ;
13861407
13871408err_sysfs_remove :
@@ -1505,6 +1526,7 @@ static const struct apple_dart_hw apple_dart_hw_t8110 = {
15051526 .tcr_enabled = DART_T8110_TCR_TRANSLATE_ENABLE ,
15061527 .tcr_disabled = 0 ,
15071528 .tcr_bypass = DART_T8110_TCR_BYPASS_DAPF | DART_T8110_TCR_BYPASS_DART ,
1529+ .tcr_4level = DART_T8110_TCR_FOUR_LEVEL ,
15081530
15091531 .ttbr = DART_T8110_TTBR ,
15101532 .ttbr_valid = DART_T8110_TTBR_VALID ,
0 commit comments