aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Leeder <nleeder@codeaurora.org>2019-03-26 11:17:50 -0400
committerWill Deacon <will.deacon@arm.com>2019-04-04 08:44:05 -0400
commit24e516049360eda85cf3fe9903221d43886c2689 (patch)
tree91dc7a7b7bc59c29cff016cb922bee5cbc021989
parent79a3aaa7b82e3106be97842dedfd8429248896e6 (diff)
ACPI/IORT: Add support for PMCG
Add support for the SMMU Performance Monitor Counter Group information from ACPI. This is in preparation for its use in the SMMUv3 PMU driver. Signed-off-by: Neil Leeder <nleeder@codeaurora.org> Signed-off-by: Hanjun Guo <guohanjun@huawei.com> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--drivers/acpi/arm64/iort.c117
-rw-r--r--include/linux/acpi_iort.h7
2 files changed, 100 insertions, 24 deletions
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index e48894e002ba..e2c9b26bbee6 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -356,7 +356,8 @@ static struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
356 if (map->flags & ACPI_IORT_ID_SINGLE_MAPPING) { 356 if (map->flags & ACPI_IORT_ID_SINGLE_MAPPING) {
357 if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT || 357 if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
358 node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX || 358 node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX ||
359 node->type == ACPI_IORT_NODE_SMMU_V3) { 359 node->type == ACPI_IORT_NODE_SMMU_V3 ||
360 node->type == ACPI_IORT_NODE_PMCG) {
360 *id_out = map->output_base; 361 *id_out = map->output_base;
361 return parent; 362 return parent;
362 } 363 }
@@ -394,6 +395,8 @@ static int iort_get_id_mapping_index(struct acpi_iort_node *node)
394 } 395 }
395 396
396 return smmu->id_mapping_index; 397 return smmu->id_mapping_index;
398 case ACPI_IORT_NODE_PMCG:
399 return 0;
397 default: 400 default:
398 return -EINVAL; 401 return -EINVAL;
399 } 402 }
@@ -1218,14 +1221,23 @@ static void __init arm_smmu_v3_init_resources(struct resource *res,
1218 } 1221 }
1219} 1222}
1220 1223
1221static bool __init arm_smmu_v3_is_coherent(struct acpi_iort_node *node) 1224static void __init arm_smmu_v3_dma_configure(struct device *dev,
1225 struct acpi_iort_node *node)
1222{ 1226{
1223 struct acpi_iort_smmu_v3 *smmu; 1227 struct acpi_iort_smmu_v3 *smmu;
1228 enum dev_dma_attr attr;
1224 1229
1225 /* Retrieve SMMUv3 specific data */ 1230 /* Retrieve SMMUv3 specific data */
1226 smmu = (struct acpi_iort_smmu_v3 *)node->node_data; 1231 smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
1227 1232
1228 return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE; 1233 attr = (smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE) ?
1234 DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT;
1235
1236 /* We expect the dma masks to be equivalent for all SMMUv3 set-ups */
1237 dev->dma_mask = &dev->coherent_dma_mask;
1238
1239 /* Configure DMA for the page table walker */
1240 acpi_dma_configure(dev, attr);
1229} 1241}
1230 1242
1231#if defined(CONFIG_ACPI_NUMA) 1243#if defined(CONFIG_ACPI_NUMA)
@@ -1301,30 +1313,82 @@ static void __init arm_smmu_init_resources(struct resource *res,
1301 } 1313 }
1302} 1314}
1303 1315
1304static bool __init arm_smmu_is_coherent(struct acpi_iort_node *node) 1316static void __init arm_smmu_dma_configure(struct device *dev,
1317 struct acpi_iort_node *node)
1305{ 1318{
1306 struct acpi_iort_smmu *smmu; 1319 struct acpi_iort_smmu *smmu;
1320 enum dev_dma_attr attr;
1307 1321
1308 /* Retrieve SMMU specific data */ 1322 /* Retrieve SMMU specific data */
1309 smmu = (struct acpi_iort_smmu *)node->node_data; 1323 smmu = (struct acpi_iort_smmu *)node->node_data;
1310 1324
1311 return smmu->flags & ACPI_IORT_SMMU_COHERENT_WALK; 1325 attr = (smmu->flags & ACPI_IORT_SMMU_COHERENT_WALK) ?
1326 DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT;
1327
1328 /* We expect the dma masks to be equivalent for SMMU set-ups */
1329 dev->dma_mask = &dev->coherent_dma_mask;
1330
1331 /* Configure DMA for the page table walker */
1332 acpi_dma_configure(dev, attr);
1333}
1334
1335static int __init arm_smmu_v3_pmcg_count_resources(struct acpi_iort_node *node)
1336{
1337 struct acpi_iort_pmcg *pmcg;
1338
1339 /* Retrieve PMCG specific data */
1340 pmcg = (struct acpi_iort_pmcg *)node->node_data;
1341
1342 /*
1343 * There are always 2 memory resources.
1344 * If the overflow_gsiv is present then add that for a total of 3.
1345 */
1346 return pmcg->overflow_gsiv ? 3 : 2;
1347}
1348
1349static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res,
1350 struct acpi_iort_node *node)
1351{
1352 struct acpi_iort_pmcg *pmcg;
1353
1354 /* Retrieve PMCG specific data */
1355 pmcg = (struct acpi_iort_pmcg *)node->node_data;
1356
1357 res[0].start = pmcg->page0_base_address;
1358 res[0].end = pmcg->page0_base_address + SZ_4K - 1;
1359 res[0].flags = IORESOURCE_MEM;
1360 res[1].start = pmcg->page1_base_address;
1361 res[1].end = pmcg->page1_base_address + SZ_4K - 1;
1362 res[1].flags = IORESOURCE_MEM;
1363
1364 if (pmcg->overflow_gsiv)
1365 acpi_iort_register_irq(pmcg->overflow_gsiv, "overflow",
1366 ACPI_EDGE_SENSITIVE, &res[2]);
1367}
1368
1369static int __init arm_smmu_v3_pmcg_add_platdata(struct platform_device *pdev)
1370{
1371 u32 model = IORT_SMMU_V3_PMCG_GENERIC;
1372
1373 return platform_device_add_data(pdev, &model, sizeof(model));
1312} 1374}
1313 1375
1314struct iort_dev_config { 1376struct iort_dev_config {
1315 const char *name; 1377 const char *name;
1316 int (*dev_init)(struct acpi_iort_node *node); 1378 int (*dev_init)(struct acpi_iort_node *node);
1317 bool (*dev_is_coherent)(struct acpi_iort_node *node); 1379 void (*dev_dma_configure)(struct device *dev,
1380 struct acpi_iort_node *node);
1318 int (*dev_count_resources)(struct acpi_iort_node *node); 1381 int (*dev_count_resources)(struct acpi_iort_node *node);
1319 void (*dev_init_resources)(struct resource *res, 1382 void (*dev_init_resources)(struct resource *res,
1320 struct acpi_iort_node *node); 1383 struct acpi_iort_node *node);
1321 void (*dev_set_proximity)(struct device *dev, 1384 void (*dev_set_proximity)(struct device *dev,
1322 struct acpi_iort_node *node); 1385 struct acpi_iort_node *node);
1386 int (*dev_add_platdata)(struct platform_device *pdev);
1323}; 1387};
1324 1388
1325static const struct iort_dev_config iort_arm_smmu_v3_cfg __initconst = { 1389static const struct iort_dev_config iort_arm_smmu_v3_cfg __initconst = {
1326 .name = "arm-smmu-v3", 1390 .name = "arm-smmu-v3",
1327 .dev_is_coherent = arm_smmu_v3_is_coherent, 1391 .dev_dma_configure = arm_smmu_v3_dma_configure,
1328 .dev_count_resources = arm_smmu_v3_count_resources, 1392 .dev_count_resources = arm_smmu_v3_count_resources,
1329 .dev_init_resources = arm_smmu_v3_init_resources, 1393 .dev_init_resources = arm_smmu_v3_init_resources,
1330 .dev_set_proximity = arm_smmu_v3_set_proximity, 1394 .dev_set_proximity = arm_smmu_v3_set_proximity,
@@ -1332,9 +1396,16 @@ static const struct iort_dev_config iort_arm_smmu_v3_cfg __initconst = {
1332 1396
1333static const struct iort_dev_config iort_arm_smmu_cfg __initconst = { 1397static const struct iort_dev_config iort_arm_smmu_cfg __initconst = {
1334 .name = "arm-smmu", 1398 .name = "arm-smmu",
1335 .dev_is_coherent = arm_smmu_is_coherent, 1399 .dev_dma_configure = arm_smmu_dma_configure,
1336 .dev_count_resources = arm_smmu_count_resources, 1400 .dev_count_resources = arm_smmu_count_resources,
1337 .dev_init_resources = arm_smmu_init_resources 1401 .dev_init_resources = arm_smmu_init_resources,
1402};
1403
1404static const struct iort_dev_config iort_arm_smmu_v3_pmcg_cfg __initconst = {
1405 .name = "arm-smmu-v3-pmcg",
1406 .dev_count_resources = arm_smmu_v3_pmcg_count_resources,
1407 .dev_init_resources = arm_smmu_v3_pmcg_init_resources,
1408 .dev_add_platdata = arm_smmu_v3_pmcg_add_platdata,
1338}; 1409};
1339 1410
1340static __init const struct iort_dev_config *iort_get_dev_cfg( 1411static __init const struct iort_dev_config *iort_get_dev_cfg(
@@ -1345,6 +1416,8 @@ static __init const struct iort_dev_config *iort_get_dev_cfg(
1345 return &iort_arm_smmu_v3_cfg; 1416 return &iort_arm_smmu_v3_cfg;
1346 case ACPI_IORT_NODE_SMMU: 1417 case ACPI_IORT_NODE_SMMU:
1347 return &iort_arm_smmu_cfg; 1418 return &iort_arm_smmu_cfg;
1419 case ACPI_IORT_NODE_PMCG:
1420 return &iort_arm_smmu_v3_pmcg_cfg;
1348 default: 1421 default:
1349 return NULL; 1422 return NULL;
1350 } 1423 }
@@ -1362,7 +1435,6 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
1362 struct fwnode_handle *fwnode; 1435 struct fwnode_handle *fwnode;
1363 struct platform_device *pdev; 1436 struct platform_device *pdev;
1364 struct resource *r; 1437 struct resource *r;
1365 enum dev_dma_attr attr;
1366 int ret, count; 1438 int ret, count;
1367 1439
1368 pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO); 1440 pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO);
@@ -1393,19 +1465,19 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
1393 goto dev_put; 1465 goto dev_put;
1394 1466
1395 /* 1467 /*
1396 * Add a copy of IORT node pointer to platform_data to 1468 * Platform devices based on PMCG nodes uses platform_data to
1397 * be used to retrieve IORT data information. 1469 * pass the hardware model info to the driver. For others, add
1470 * a copy of IORT node pointer to platform_data to be used to
1471 * retrieve IORT data information.
1398 */ 1472 */
1399 ret = platform_device_add_data(pdev, &node, sizeof(node)); 1473 if (ops->dev_add_platdata)
1474 ret = ops->dev_add_platdata(pdev);
1475 else
1476 ret = platform_device_add_data(pdev, &node, sizeof(node));
1477
1400 if (ret) 1478 if (ret)
1401 goto dev_put; 1479 goto dev_put;
1402 1480
1403 /*
1404 * We expect the dma masks to be equivalent for
1405 * all SMMUs set-ups
1406 */
1407 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
1408
1409 fwnode = iort_get_fwnode(node); 1481 fwnode = iort_get_fwnode(node);
1410 1482
1411 if (!fwnode) { 1483 if (!fwnode) {
@@ -1415,11 +1487,8 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
1415 1487
1416 pdev->dev.fwnode = fwnode; 1488 pdev->dev.fwnode = fwnode;
1417 1489
1418 attr = ops->dev_is_coherent && ops->dev_is_coherent(node) ? 1490 if (ops->dev_dma_configure)
1419 DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT; 1491 ops->dev_dma_configure(&pdev->dev, node);
1420
1421 /* Configure DMA for the page table walker */
1422 acpi_dma_configure(&pdev->dev, attr);
1423 1492
1424 iort_set_device_domain(&pdev->dev, node); 1493 iort_set_device_domain(&pdev->dev, node);
1425 1494
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 38cd77b39a64..052ef7b9f985 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -26,6 +26,13 @@
26#define IORT_IRQ_MASK(irq) (irq & 0xffffffffULL) 26#define IORT_IRQ_MASK(irq) (irq & 0xffffffffULL)
27#define IORT_IRQ_TRIGGER_MASK(irq) ((irq >> 32) & 0xffffffffULL) 27#define IORT_IRQ_TRIGGER_MASK(irq) ((irq >> 32) & 0xffffffffULL)
28 28
29/*
30 * PMCG model identifiers for use in smmu pmu driver. Please note
31 * that this is purely for the use of software and has nothing to
32 * do with hardware or with IORT specification.
33 */
34#define IORT_SMMU_V3_PMCG_GENERIC 0x00000000 /* Generic SMMUv3 PMCG */
35
29int iort_register_domain_token(int trans_id, phys_addr_t base, 36int iort_register_domain_token(int trans_id, phys_addr_t base,
30 struct fwnode_handle *fw_node); 37 struct fwnode_handle *fw_node);
31void iort_deregister_domain_token(int trans_id); 38void iort_deregister_domain_token(int trans_id);