135135#define DART_T8110_TCR 0x1000
136136#define DART_T8110_TCR_REMAP GENMASK(11, 8)
137137#define DART_T8110_TCR_REMAP_EN BIT(7)
138+ #define DART_T8110_TCR_FOUR_LEVEL BIT(3)
138139#define DART_T8110_TCR_BYPASS_DAPF BIT(2)
139140#define DART_T8110_TCR_BYPASS_DART BIT(1)
140141#define DART_T8110_TCR_TRANSLATE_ENABLE BIT(0)
@@ -179,6 +180,7 @@ struct apple_dart_hw {
179180 u32 tcr_enabled ;
180181 u32 tcr_disabled ;
181182 u32 tcr_bypass ;
183+ u32 tcr_4level ;
182184
183185 u32 ttbr ;
184186 u32 ttbr_valid ;
@@ -223,6 +225,7 @@ struct apple_dart {
223225 u32 supports_bypass : 1 ;
224226 u32 force_bypass : 1 ;
225227 u32 locked : 1 ;
228+ u32 four_level : 1 ;
226229
227230 struct iommu_group * sid2group [DART_MAX_STREAMS ];
228231 struct iommu_device iommu ;
@@ -311,14 +314,17 @@ static struct apple_dart_domain *to_dart_domain(struct iommu_domain *dom)
311314}
312315
313316static void
314- apple_dart_hw_enable_translation (struct apple_dart_stream_map * stream_map )
317+ apple_dart_hw_enable_translation (struct apple_dart_stream_map * stream_map , int levels )
315318{
316319 struct apple_dart * dart = stream_map -> dart ;
317320 int sid ;
318321
322+ WARN_ON (levels != 3 && levels != 4 );
323+ WARN_ON (levels == 4 && !dart -> four_level );
319324 WARN_ON (stream_map -> dart -> locked );
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 )
@@ -667,7 +673,8 @@ apple_dart_setup_translation(struct apple_dart_domain *domain,
667673 for (; i < stream_map -> dart -> hw -> ttbr_count ; ++ i )
668674 apple_dart_hw_clear_ttbr (stream_map , i );
669675
670- apple_dart_hw_enable_translation (stream_map );
676+ apple_dart_hw_enable_translation (stream_map ,
677+ pgtbl_cfg -> apple_dart_cfg .n_levels );
671678 }
672679 stream_map -> dart -> hw -> invalidate_tlb (stream_map );
673680}
@@ -749,6 +756,19 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
749756 ttbr = readl (dart -> regs + DART_TTBR (dart , sid , 0 ));
750757
751758 WARN_ON (!(ttbr & dart -> hw -> ttbr_valid ));
759+
760+ /* If the DART is locked, we need to keep the translation level count. */
761+ if (dart -> hw -> tcr_4level && dart -> ias > 36 ) {
762+ if (readl (dart -> regs + DART_TCR (dart , sid )) & dart -> hw -> tcr_4level ) {
763+ if (dart -> ias < 37 ) {
764+ dev_info (dart -> dev , "Expanded to ias=37 due to lock\n" );
765+ pgtbl_cfg .ias = 37 ;
766+ }
767+ } else if (dart -> ias > 36 ) {
768+ dev_info (dart -> dev , "Limited to ias=36 due to lock\n" );
769+ pgtbl_cfg .ias = 36 ;
770+ }
771+ }
752772 }
753773
754774 dart_domain -> pgtbl_ops =
@@ -760,7 +780,7 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain,
760780
761781 domain -> pgsize_bitmap = pgtbl_cfg .pgsize_bitmap ;
762782 domain -> geometry .aperture_start = 0 ;
763- domain -> geometry .aperture_end = (dma_addr_t )DMA_BIT_MASK (dart -> ias );
783+ domain -> geometry .aperture_end = (dma_addr_t )DMA_BIT_MASK (pgtbl_cfg . ias );
764784 domain -> geometry .force_aperture = true;
765785
766786 dart_domain -> finalized = true;
@@ -1295,6 +1315,7 @@ static int apple_dart_probe(struct platform_device *pdev)
12951315 dart -> ias = FIELD_GET (DART_T8110_PARAMS3_VA_WIDTH , dart_params [2 ]);
12961316 dart -> oas = FIELD_GET (DART_T8110_PARAMS3_PA_WIDTH , dart_params [2 ]);
12971317 dart -> num_streams = FIELD_GET (DART_T8110_PARAMS4_NUM_SIDS , dart_params [3 ]);
1318+ dart -> four_level = dart -> ias > 36 ;
12981319 break ;
12991320 }
13001321
@@ -1334,8 +1355,9 @@ static int apple_dart_probe(struct platform_device *pdev)
13341355
13351356 dev_info (
13361357 & pdev -> dev ,
1337- "DART [pagesize %x, %d streams, bypass support: %d, bypass forced: %d, locked: %d] initialized\n" ,
1338- dart -> pgsize , dart -> num_streams , dart -> supports_bypass , dart -> force_bypass , dart -> locked );
1358+ "DART [pagesize %x, %d streams, bypass support: %d, bypass forced: %d, locked: %d, AS %d -> %d] initialized\n" ,
1359+ dart -> pgsize , dart -> num_streams , dart -> supports_bypass , dart -> force_bypass , dart -> locked ,
1360+ dart -> ias , dart -> oas );
13391361 return 0 ;
13401362
13411363err_sysfs_remove :
@@ -1432,6 +1454,7 @@ static const struct apple_dart_hw apple_dart_hw_t8110 = {
14321454 .tcr_enabled = DART_T8110_TCR_TRANSLATE_ENABLE ,
14331455 .tcr_disabled = 0 ,
14341456 .tcr_bypass = DART_T8110_TCR_BYPASS_DAPF | DART_T8110_TCR_BYPASS_DART ,
1457+ .tcr_4level = DART_T8110_TCR_FOUR_LEVEL ,
14351458
14361459 .ttbr = DART_T8110_TTBR ,
14371460 .ttbr_valid = DART_T8110_TTBR_VALID ,
0 commit comments