Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf/arm-cci: Untangle global cci_ctrl_base

Depending directly on the bus driver's global cci_ctrl_base variable
is a little unpleasant, and exporting it to allow the PMU driver to
be modular would be even more so. Let's make things a little better
abstracted by adding the control register block to the cci_pmu instance
data alongside the PMU register block, and communicating the mapped
address from the bus driver via platform data.

It's not practical to try the same thing for the bus driver itself,
given that the globals are entangled with the hairy assembly code for
port control, so we leave them be there. It would however be prudent
to move them to the __ro_after_init section in passing, since the
addresses really should never be changing once set.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

authored by

Robin Murphy and committed by
Arnd Bergmann
e9c112c9 32837954

+37 -27
+13 -4
drivers/bus/arm-cci.c
··· 25 25 #include <asm/cacheflush.h> 26 26 #include <asm/smp_plat.h> 27 27 28 - /* Referenced read-only by the PMU driver; see drivers/perf/arm-cci.c */ 29 - void __iomem *cci_ctrl_base; 30 - static unsigned long cci_ctrl_phys; 28 + static void __iomem *cci_ctrl_base __ro_after_init; 29 + static unsigned long cci_ctrl_phys __ro_after_init; 31 30 32 31 #ifdef CONFIG_ARM_CCI400_PORT_CTRL 33 32 struct cci_nb_ports { ··· 55 56 {}, 56 57 }; 57 58 59 + static const struct of_dev_auxdata arm_cci_auxdata[] = { 60 + OF_DEV_AUXDATA("arm,cci-400-pmu", 0, NULL, &cci_ctrl_base), 61 + OF_DEV_AUXDATA("arm,cci-400-pmu,r0", 0, NULL, &cci_ctrl_base), 62 + OF_DEV_AUXDATA("arm,cci-400-pmu,r1", 0, NULL, &cci_ctrl_base), 63 + OF_DEV_AUXDATA("arm,cci-500-pmu,r0", 0, NULL, &cci_ctrl_base), 64 + OF_DEV_AUXDATA("arm,cci-550-pmu,r0", 0, NULL, &cci_ctrl_base), 65 + {} 66 + }; 67 + 58 68 #define DRIVER_NAME "ARM-CCI" 59 69 60 70 static int cci_platform_probe(struct platform_device *pdev) ··· 71 63 if (!cci_probed()) 72 64 return -ENODEV; 73 65 74 - return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); 66 + return of_platform_populate(pdev->dev.of_node, NULL, 67 + arm_cci_auxdata, &pdev->dev); 75 68 } 76 69 77 70 static struct platform_driver cci_platform_driver = {
+24 -23
drivers/perf/arm-cci.c
··· 16 16 #include <linux/slab.h> 17 17 #include <linux/spinlock.h> 18 18 19 - extern void __iomem *const cci_ctrl_base; 20 - 21 19 #define DRIVER_NAME "ARM-CCI PMU" 22 20 23 21 #define CCI_PMCR 0x0100 ··· 88 90 89 91 struct cci_pmu { 90 92 void __iomem *base; 93 + void __iomem *ctrl_base; 91 94 struct pmu pmu; 92 95 int cpu; 93 96 int nr_irqs; ··· 359 360 return -ENOENT; 360 361 } 361 362 362 - static int probe_cci400_revision(void) 363 + static int probe_cci400_revision(struct cci_pmu *cci_pmu) 363 364 { 364 365 int rev; 365 - rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK; 366 + rev = readl_relaxed(cci_pmu->ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK; 366 367 rev >>= CCI_PID2_REV_SHIFT; 367 368 368 369 if (rev < CCI400_R1_PX) ··· 371 372 return CCI400_R1; 372 373 } 373 374 374 - static const struct cci_pmu_model *probe_cci_model(void) 375 + static const struct cci_pmu_model *probe_cci_model(struct cci_pmu *cci_pmu) 375 376 { 376 377 if (platform_has_secure_cci_access()) 377 - return &cci_pmu_models[probe_cci400_revision()]; 378 + return &cci_pmu_models[probe_cci400_revision(cci_pmu)]; 378 379 return NULL; 379 380 } 380 381 #else /* !CONFIG_ARM_CCI400_PMU */ 381 - static inline struct cci_pmu_model *probe_cci_model(void) 382 + static inline struct cci_pmu_model *probe_cci_model(struct cci_pmu *cci_pmu) 382 383 { 383 384 return NULL; 384 385 } ··· 661 662 u32 val; 662 663 663 664 /* Enable all the PMU counters. */ 664 - val = readl_relaxed(cci_ctrl_base + CCI_PMCR) | CCI_PMCR_CEN; 665 - writel(val, cci_ctrl_base + CCI_PMCR); 665 + val = readl_relaxed(cci_pmu->ctrl_base + CCI_PMCR) | CCI_PMCR_CEN; 666 + writel(val, cci_pmu->ctrl_base + CCI_PMCR); 666 667 } 667 668 668 669 /* Should be called with cci_pmu->hw_events->pmu_lock held */ ··· 673 674 } 674 675 675 676 /* Should be called with cci_pmu->hw_events->pmu_lock held */ 676 - static void __cci_pmu_disable(void) 677 + static void __cci_pmu_disable(struct cci_pmu *cci_pmu) 677 678 { 678 679 u32 val; 679 680 680 681 /* Disable all the PMU counters. */ 681 - val = readl_relaxed(cci_ctrl_base + CCI_PMCR) & ~CCI_PMCR_CEN; 682 - writel(val, cci_ctrl_base + CCI_PMCR); 682 + val = readl_relaxed(cci_pmu->ctrl_base + CCI_PMCR) & ~CCI_PMCR_CEN; 683 + writel(val, cci_pmu->ctrl_base + CCI_PMCR); 683 684 } 684 685 685 686 static ssize_t cci_pmu_format_show(struct device *dev, ··· 781 782 * Returns the number of programmable counters actually implemented 782 783 * by the cci 783 784 */ 784 - static u32 pmu_get_max_counters(void) 785 + static u32 pmu_get_max_counters(struct cci_pmu *cci_pmu) 785 786 { 786 - return (readl_relaxed(cci_ctrl_base + CCI_PMCR) & 787 + return (readl_relaxed(cci_pmu->ctrl_base + CCI_PMCR) & 787 788 CCI_PMCR_NCNT_MASK) >> CCI_PMCR_NCNT_SHIFT; 788 789 } 789 790 ··· 964 965 pmu_set_event(cci_pmu, i, event->hw.config_base); 965 966 } 966 967 967 - __cci_pmu_disable(); 968 + __cci_pmu_disable(cci_pmu); 968 969 969 970 pmu_restore_counters(cci_pmu, saved_mask); 970 971 } ··· 1025 1026 raw_spin_lock_irqsave(&events->pmu_lock, flags); 1026 1027 1027 1028 /* Disable the PMU while we walk through the counters */ 1028 - __cci_pmu_disable(); 1029 + __cci_pmu_disable(cci_pmu); 1029 1030 /* 1030 1031 * Iterate over counters and update the corresponding perf events. 1031 1032 * This should work regardless of whether we have per-counter overflow ··· 1107 1108 unsigned long flags; 1108 1109 1109 1110 raw_spin_lock_irqsave(&hw_events->pmu_lock, flags); 1110 - __cci_pmu_disable(); 1111 + __cci_pmu_disable(cci_pmu); 1111 1112 raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags); 1112 1113 } 1113 1114 ··· 1437 1438 }; 1438 1439 1439 1440 cci_pmu->plat_device = pdev; 1440 - num_cntrs = pmu_get_max_counters(); 1441 + num_cntrs = pmu_get_max_counters(cci_pmu); 1441 1442 if (num_cntrs > cci_pmu->model->num_hw_cntrs) { 1442 1443 dev_warn(&pdev->dev, 1443 1444 "PMU implements more counters(%d) than supported by" ··· 1610 1611 * them explicitly on an error, as it would end up in driver 1611 1612 * detach. 1612 1613 */ 1614 + cci_pmu = devm_kzalloc(dev, sizeof(*cci_pmu), GFP_KERNEL); 1615 + if (!cci_pmu) 1616 + return ERR_PTR(-ENOMEM); 1617 + 1618 + cci_pmu->ctrl_base = *(void __iomem **)dev->platform_data; 1619 + 1613 1620 model = of_device_get_match_data(dev); 1614 1621 if (!model) { 1615 1622 dev_warn(dev, 1616 1623 "DEPRECATED compatible property, requires secure access to CCI registers"); 1617 - model = probe_cci_model(); 1624 + model = probe_cci_model(cci_pmu); 1618 1625 } 1619 1626 if (!model) { 1620 1627 dev_warn(dev, "CCI PMU version not supported\n"); 1621 1628 return ERR_PTR(-ENODEV); 1622 1629 } 1623 - 1624 - cci_pmu = devm_kzalloc(dev, sizeof(*cci_pmu), GFP_KERNEL); 1625 - if (!cci_pmu) 1626 - return ERR_PTR(-ENOMEM); 1627 1630 1628 1631 cci_pmu->model = model; 1629 1632 cci_pmu->irqs = devm_kcalloc(dev, CCI_PMU_MAX_HW_CNTRS(model),