diff options
| -rw-r--r-- | drivers/perf/arm_smmuv3_pmu.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c index a6d2e3ce94df..a4f4b488a2de 100644 --- a/drivers/perf/arm_smmuv3_pmu.c +++ b/drivers/perf/arm_smmuv3_pmu.c | |||
| @@ -67,6 +67,7 @@ | |||
| 67 | #define SMMU_PMCG_OVSSET0 0xCC0 | 67 | #define SMMU_PMCG_OVSSET0 0xCC0 |
| 68 | #define SMMU_PMCG_CFGR 0xE00 | 68 | #define SMMU_PMCG_CFGR 0xE00 |
| 69 | #define SMMU_PMCG_CFGR_SID_FILTER_TYPE BIT(23) | 69 | #define SMMU_PMCG_CFGR_SID_FILTER_TYPE BIT(23) |
| 70 | #define SMMU_PMCG_CFGR_MSI BIT(21) | ||
| 70 | #define SMMU_PMCG_CFGR_RELOC_CTRS BIT(20) | 71 | #define SMMU_PMCG_CFGR_RELOC_CTRS BIT(20) |
| 71 | #define SMMU_PMCG_CFGR_SIZE GENMASK(13, 8) | 72 | #define SMMU_PMCG_CFGR_SIZE GENMASK(13, 8) |
| 72 | #define SMMU_PMCG_CFGR_NCTR GENMASK(5, 0) | 73 | #define SMMU_PMCG_CFGR_NCTR GENMASK(5, 0) |
| @@ -77,6 +78,12 @@ | |||
| 77 | #define SMMU_PMCG_IRQ_CTRL 0xE50 | 78 | #define SMMU_PMCG_IRQ_CTRL 0xE50 |
| 78 | #define SMMU_PMCG_IRQ_CTRL_IRQEN BIT(0) | 79 | #define SMMU_PMCG_IRQ_CTRL_IRQEN BIT(0) |
| 79 | #define SMMU_PMCG_IRQ_CFG0 0xE58 | 80 | #define SMMU_PMCG_IRQ_CFG0 0xE58 |
| 81 | #define SMMU_PMCG_IRQ_CFG1 0xE60 | ||
| 82 | #define SMMU_PMCG_IRQ_CFG2 0xE64 | ||
| 83 | |||
| 84 | /* MSI config fields */ | ||
| 85 | #define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2) | ||
| 86 | #define MSI_CFG2_MEMATTR_DEVICE_nGnRE 0x1 | ||
| 80 | 87 | ||
| 81 | #define SMMU_PMCG_DEFAULT_FILTER_SPAN 1 | 88 | #define SMMU_PMCG_DEFAULT_FILTER_SPAN 1 |
| 82 | #define SMMU_PMCG_DEFAULT_FILTER_SID GENMASK(31, 0) | 89 | #define SMMU_PMCG_DEFAULT_FILTER_SID GENMASK(31, 0) |
| @@ -580,11 +587,62 @@ static irqreturn_t smmu_pmu_handle_irq(int irq_num, void *data) | |||
| 580 | return IRQ_HANDLED; | 587 | return IRQ_HANDLED; |
| 581 | } | 588 | } |
| 582 | 589 | ||
| 590 | static void smmu_pmu_free_msis(void *data) | ||
| 591 | { | ||
| 592 | struct device *dev = data; | ||
| 593 | |||
| 594 | platform_msi_domain_free_irqs(dev); | ||
| 595 | } | ||
| 596 | |||
| 597 | static void smmu_pmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg) | ||
| 598 | { | ||
| 599 | phys_addr_t doorbell; | ||
| 600 | struct device *dev = msi_desc_to_dev(desc); | ||
| 601 | struct smmu_pmu *pmu = dev_get_drvdata(dev); | ||
| 602 | |||
| 603 | doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo; | ||
| 604 | doorbell &= MSI_CFG0_ADDR_MASK; | ||
| 605 | |||
| 606 | writeq_relaxed(doorbell, pmu->reg_base + SMMU_PMCG_IRQ_CFG0); | ||
| 607 | writel_relaxed(msg->data, pmu->reg_base + SMMU_PMCG_IRQ_CFG1); | ||
| 608 | writel_relaxed(MSI_CFG2_MEMATTR_DEVICE_nGnRE, | ||
| 609 | pmu->reg_base + SMMU_PMCG_IRQ_CFG2); | ||
| 610 | } | ||
| 611 | |||
| 612 | static void smmu_pmu_setup_msi(struct smmu_pmu *pmu) | ||
| 613 | { | ||
| 614 | struct msi_desc *desc; | ||
| 615 | struct device *dev = pmu->dev; | ||
| 616 | int ret; | ||
| 617 | |||
| 618 | /* Clear MSI address reg */ | ||
| 619 | writeq_relaxed(0, pmu->reg_base + SMMU_PMCG_IRQ_CFG0); | ||
| 620 | |||
| 621 | /* MSI supported or not */ | ||
| 622 | if (!(readl(pmu->reg_base + SMMU_PMCG_CFGR) & SMMU_PMCG_CFGR_MSI)) | ||
| 623 | return; | ||
| 624 | |||
| 625 | ret = platform_msi_domain_alloc_irqs(dev, 1, smmu_pmu_write_msi_msg); | ||
| 626 | if (ret) { | ||
| 627 | dev_warn(dev, "failed to allocate MSIs\n"); | ||
| 628 | return; | ||
| 629 | } | ||
| 630 | |||
| 631 | desc = first_msi_entry(dev); | ||
| 632 | if (desc) | ||
| 633 | pmu->irq = desc->irq; | ||
| 634 | |||
| 635 | /* Add callback to free MSIs on teardown */ | ||
| 636 | devm_add_action(dev, smmu_pmu_free_msis, dev); | ||
| 637 | } | ||
| 638 | |||
| 583 | static int smmu_pmu_setup_irq(struct smmu_pmu *pmu) | 639 | static int smmu_pmu_setup_irq(struct smmu_pmu *pmu) |
| 584 | { | 640 | { |
| 585 | unsigned long flags = IRQF_NOBALANCING | IRQF_SHARED | IRQF_NO_THREAD; | 641 | unsigned long flags = IRQF_NOBALANCING | IRQF_SHARED | IRQF_NO_THREAD; |
| 586 | int irq, ret = -ENXIO; | 642 | int irq, ret = -ENXIO; |
| 587 | 643 | ||
| 644 | smmu_pmu_setup_msi(pmu); | ||
| 645 | |||
| 588 | irq = pmu->irq; | 646 | irq = pmu->irq; |
| 589 | if (irq) | 647 | if (irq) |
| 590 | ret = devm_request_irq(pmu->dev, irq, smmu_pmu_handle_irq, | 648 | ret = devm_request_irq(pmu->dev, irq, smmu_pmu_handle_irq, |
