55
66#define pr_fmt (fmt ) "GICv5 ITS: " fmt
77
8+ #include <linux/acpi.h>
9+ #include <linux/acpi_iort.h>
810#include <linux/bitmap.h>
911#include <linux/iommu.h>
1012#include <linux/init.h>
@@ -1115,7 +1117,7 @@ static int gicv5_its_init_domain(struct gicv5_its_chip_data *its, struct irq_dom
11151117}
11161118
11171119static int __init gicv5_its_init_bases (void __iomem * its_base , struct fwnode_handle * handle ,
1118- struct irq_domain * parent_domain )
1120+ struct irq_domain * parent_domain , bool noncoherent )
11191121{
11201122 struct device_node * np = to_of_node (handle );
11211123 struct gicv5_its_chip_data * its_node ;
@@ -1208,7 +1210,8 @@ static int __init gicv5_its_init(struct device_node *node)
12081210 }
12091211
12101212 ret = gicv5_its_init_bases (its_base , of_fwnode_handle (node ),
1211- gicv5_global_data .lpi_domain );
1213+ gicv5_global_data .lpi_domain ,
1214+ of_property_read_bool (node , "dma-noncoherent" ));
12121215 if (ret )
12131216 goto out_unmap ;
12141217
@@ -1231,3 +1234,128 @@ void __init gicv5_its_of_probe(struct device_node *parent)
12311234 pr_err ("Failed to init ITS %s\n" , np -> full_name );
12321235 }
12331236}
1237+
1238+ #ifdef CONFIG_ACPI
1239+
1240+ #define ACPI_GICV5_ITS_MEM_SIZE (SZ_64K)
1241+
1242+ static struct acpi_madt_gicv5_translator * current_its_entry __initdata ;
1243+ static struct fwnode_handle * current_its_fwnode __initdata ;
1244+
1245+ static int __init gic_acpi_parse_madt_its_translate (union acpi_subtable_headers * header ,
1246+ const unsigned long end )
1247+ {
1248+ struct acpi_madt_gicv5_translate_frame * its_frame ;
1249+ struct fwnode_handle * msi_dom_handle ;
1250+ struct resource res = {};
1251+ int err ;
1252+
1253+ its_frame = (struct acpi_madt_gicv5_translate_frame * )header ;
1254+ if (its_frame -> linked_translator_id != current_its_entry -> translator_id )
1255+ return 0 ;
1256+
1257+ res .start = its_frame -> base_address ;
1258+ res .end = its_frame -> base_address + ACPI_GICV5_ITS_MEM_SIZE - 1 ;
1259+ res .flags = IORESOURCE_MEM ;
1260+
1261+ msi_dom_handle = irq_domain_alloc_parented_fwnode (& res .start , current_its_fwnode );
1262+ if (!msi_dom_handle ) {
1263+ pr_err ("ITS@%pa: Unable to allocate GICv5 ITS translate domain token\n" ,
1264+ & res .start );
1265+ return - ENOMEM ;
1266+ }
1267+
1268+ err = iort_register_domain_token (its_frame -> translate_frame_id , res .start ,
1269+ msi_dom_handle );
1270+ if (err ) {
1271+ pr_err ("ITS@%pa: Unable to register GICv5 ITS domain token (ITS TRANSLATE FRAME ID %d) to IORT\n" ,
1272+ & res .start , its_frame -> translate_frame_id );
1273+ irq_domain_free_fwnode (msi_dom_handle );
1274+ return err ;
1275+ }
1276+
1277+ return 0 ;
1278+ }
1279+
1280+ static int __init gic_acpi_free_madt_its_translate (union acpi_subtable_headers * header ,
1281+ const unsigned long end )
1282+ {
1283+ struct acpi_madt_gicv5_translate_frame * its_frame ;
1284+ struct fwnode_handle * msi_dom_handle ;
1285+
1286+ its_frame = (struct acpi_madt_gicv5_translate_frame * )header ;
1287+ if (its_frame -> linked_translator_id != current_its_entry -> translator_id )
1288+ return 0 ;
1289+
1290+ msi_dom_handle = iort_find_domain_token (its_frame -> translate_frame_id );
1291+ if (!msi_dom_handle )
1292+ return 0 ;
1293+
1294+ iort_deregister_domain_token (its_frame -> translate_frame_id );
1295+ irq_domain_free_fwnode (msi_dom_handle );
1296+
1297+ return 0 ;
1298+ }
1299+
1300+ static int __init gic_acpi_parse_madt_its (union acpi_subtable_headers * header ,
1301+ const unsigned long end )
1302+ {
1303+ struct acpi_madt_gicv5_translator * its_entry ;
1304+ struct fwnode_handle * dom_handle ;
1305+ struct resource res = {};
1306+ void __iomem * its_base ;
1307+ int err ;
1308+
1309+ its_entry = (struct acpi_madt_gicv5_translator * )header ;
1310+ res .start = its_entry -> base_address ;
1311+ res .end = its_entry -> base_address + ACPI_GICV5_ITS_MEM_SIZE - 1 ;
1312+ res .flags = IORESOURCE_MEM ;
1313+
1314+ if (!request_mem_region (res .start , resource_size (& res ), "GICv5 ITS" ))
1315+ return - EBUSY ;
1316+
1317+ dom_handle = irq_domain_alloc_fwnode (& res .start );
1318+ if (!dom_handle ) {
1319+ pr_err ("ITS@%pa: Unable to allocate GICv5 ITS domain token\n" ,
1320+ & res .start );
1321+ err = - ENOMEM ;
1322+ goto out_rel_res ;
1323+ }
1324+
1325+ current_its_entry = its_entry ;
1326+ current_its_fwnode = dom_handle ;
1327+
1328+ acpi_table_parse_madt (ACPI_MADT_TYPE_GICV5_ITS_TRANSLATE ,
1329+ gic_acpi_parse_madt_its_translate , 0 );
1330+
1331+ its_base = ioremap (res .start , ACPI_GICV5_ITS_MEM_SIZE );
1332+ if (!its_base ) {
1333+ err = - ENOMEM ;
1334+ goto out_unregister ;
1335+ }
1336+
1337+ err = gicv5_its_init_bases (its_base , dom_handle , gicv5_global_data .lpi_domain ,
1338+ its_entry -> flags & ACPI_MADT_GICV5_ITS_NON_COHERENT );
1339+ if (err )
1340+ goto out_unmap ;
1341+
1342+ return 0 ;
1343+
1344+ out_unmap :
1345+ iounmap (its_base );
1346+ out_unregister :
1347+ acpi_table_parse_madt (ACPI_MADT_TYPE_GICV5_ITS_TRANSLATE ,
1348+ gic_acpi_free_madt_its_translate , 0 );
1349+ irq_domain_free_fwnode (dom_handle );
1350+ out_rel_res :
1351+ release_mem_region (res .start , resource_size (& res ));
1352+ return err ;
1353+ }
1354+
1355+ void __init gicv5_its_acpi_probe (void )
1356+ {
1357+ acpi_table_parse_madt (ACPI_MADT_TYPE_GICV5_ITS , gic_acpi_parse_madt_its , 0 );
1358+ }
1359+ #else
1360+ void __init gicv5_its_acpi_probe (void ) { }
1361+ #endif
0 commit comments