Skip to contentSkip to conversation

ARM: pmu: provide a registration mechanism for IRQs [v3]

PATCH New Will Deacon 4 participants 13 messages Mar 25, 2010 – Apr 29, 2010

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover ARM: pmu: provide a registration mechanism for IRQs [v3]

This is version 3 of the patch series originally posted here:

v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2010-March/011162.html
v2: http://lists.infradead.org/pipermail/linux-arm-kernel/2010-March/011339.html

Changes from version 2 include:

- PXA PMU registration moved out of mach-pxa and into plat-pxa
- Use of a platform_device to represent the PMU
- Fixes in pmu.c in response to comments from Jamie Iles
- Taken against 2.6.34-rc2

I'd like to submit this to the patch system soon, so please let me know if the mach-* and plat-* changes require any further work.

Cc Russell King - ARM Linux <[email protected]>
Cc Jamie Iles <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Leo Chen <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Eric Miao <[email protected]>

Will Deacon (6):
ARM: pmu: register IRQs at runtime
ARM: Realview: register PMU IRQs during board initialisation
ARM: OMAP: register PMU IRQs during board initialisation
ARM: BCMRING: register PMU IRQ during board initialisation
ARM: iop3xx: register PMU IRQs during board initialisation
ARM: pxa: register PMU IRQs during board initialisation

 arch/arm/include/asm/pmu.h               |   32 ++++----
 arch/arm/kernel/perf_event.c             |   36 +++++----
 arch/arm/kernel/pmu.c                    |  127 +++++++++++++++++++----------
 arch/arm/mach-bcmring/arch.c             |   16 ++++
 arch/arm/mach-omap2/devices.c            |   34 ++++++++
 arch/arm/mach-realview/realview_eb.c     |   32 ++++++++
 arch/arm/mach-realview/realview_pb1176.c |   15 ++++
 arch/arm/mach-realview/realview_pb11mp.c |   32 ++++++++
 arch/arm/mach-realview/realview_pba8.c   |   15 ++++
 arch/arm/mach-realview/realview_pbx.c    |   32 ++++++++
 arch/arm/plat-iop/Makefile               |    2 +
 arch/arm/plat-iop/pmu.c                  |   40 +++++++++
 arch/arm/plat-pxa/Makefile               |    2 +-
 arch/arm/plat-pxa/pmu.c                  |   33 ++++++++
 14 files changed, 371 insertions(+), 77 deletions(-)
 create mode 100644 arch/arm/plat-iop/pmu.c
 create mode 100644 arch/arm/plat-pxa/pmu.c
#1 lore raw

PATCH 1/6 ARM: pmu: register IRQs at runtime

The current PMU infrastructure for ARM requires that the IRQs for the PMU device are fixed at compile time and are selected based on the ARCH_ or MACH_ flags. This has the disadvantage of tying the Kernel down to a particular board as far as profiling is concerned.

This patch replaces the compile-time IRQ registration with a runtime mechanism which allows the IRQs to be registered with the framework as a platform_device.

A further advantage of this change is that there is scope for registering different types of performance counters in the future by changing the id of the platform_device and attaching different resources to it.

Cc Russell King - ARM Linux <[email protected]>
Cc Jamie Iles <[email protected]>
---
 arch/arm/include/asm/pmu.h   |   32 ++++++-----
 arch/arm/kernel/perf_event.c |   36 ++++++------
 arch/arm/kernel/pmu.c        |  127 +++++++++++++++++++++++++++--------------
 3 files changed, 119 insertions(+), 76 deletions(-)
arch/arm/include/asm/pmu.h +17 -15
index 2829b9f..8ccea01 100644
@@ -12,33 +12,33 @@
 #ifndef __ARM_PMU_H__
 #define __ARM_PMU_H__
 
-#ifdef CONFIG_CPU_HAS_PMU
-
-struct pmu_irqs {
-	const int   *irqs;
-	int	    num_irqs;
+enum arm_pmu_type {
+	ARM_PMU_DEVICE_CPU	= 0,
+	ARM_NUM_PMU_DEVICES,
 };
 
+#ifdef CONFIG_CPU_HAS_PMU
+
 /**
  * reserve_pmu() - reserve the hardware performance counters
  *
  * Reserve the hardware performance counters in the system for exclusive use.
- * The 'struct pmu_irqs' for the system is returned on success, ERR_PTR()
+ * The platform_device for the system is returned on success, ERR_PTR()
  * encoded error on failure.
  */
-extern const struct pmu_irqs *
-reserve_pmu(void);
+extern struct platform_device *
+reserve_pmu(enum arm_pmu_type device);
 
 /**
  * release_pmu() - Relinquish control of the performance counters
  *
  * Release the performance counters and allow someone else to use them.
  * Callers must have disabled the counters and released IRQs before calling
- * this. The 'struct pmu_irqs' returned from reserve_pmu() must be passed as
+ * this. The platform_device returned from reserve_pmu() must be passed as
  * a cookie.
  */
 extern int
-release_pmu(const struct pmu_irqs *irqs);
+release_pmu(struct platform_device *pdev);
 
 /**
  * init_pmu() - Initialise the PMU.
@@ -48,24 +48,26 @@ release_pmu(const struct pmu_irqs *irqs);
  * the actual hardware initialisation.
  */
 extern int
-init_pmu(void);
+init_pmu(enum arm_pmu_type device);
 
 #else /* CONFIG_CPU_HAS_PMU */
 
-static inline const struct pmu_irqs *
-reserve_pmu(void)
+#include <linux/err.h>
+
+static inline struct platform_device *
+reserve_pmu(enum arm_pmu_type device)
 {
 	return ERR_PTR(-ENODEV);
 }
 
 static inline int
-release_pmu(const struct pmu_irqs *irqs)
+release_pmu(struct platform_device *pdev)
 {
 	return -ENODEV;
 }
 
 static inline int
-init_pmu(void)
+init_pmu(enum arm_pmu_type device)
 {
 	return -ENODEV;
 }
arch/arm/kernel/perf_event.c +19 -17
index 9e70f20..0c1a447 100644
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/perf_event.h>
+#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 
@@ -26,7 +27,7 @@
 #include <asm/pmu.h>
 #include <asm/stacktrace.h>
 
-static const struct pmu_irqs *pmu_irqs;
+static struct platform_device *pmu_device;
 
 /*
  * Hardware lock to serialize accesses to PMU registers. Needed for the
@@ -317,35 +318,36 @@ armpmu_reserve_hardware(void)
 	int i;
 	int err;
 
-	pmu_irqs = reserve_pmu();
-	if (IS_ERR(pmu_irqs)) {
+	pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
+	if (IS_ERR(pmu_device)) {
 		pr_warning("unable to reserve pmu\n");
-		return PTR_ERR(pmu_irqs);
+		return PTR_ERR(pmu_device);
 	}
 
-	init_pmu();
+	init_pmu(ARM_PMU_DEVICE_CPU);
 
-	if (pmu_irqs->num_irqs < 1) {
+	if (pmu_device->num_resources < 1) {
 		pr_err("no irqs for PMUs defined\n");
 		return -ENODEV;
 	}
 
-	for (i = 0; i < pmu_irqs->num_irqs; ++i) {
-		err = request_irq(pmu_irqs->irqs[i], armpmu->handle_irq,
+	for (i = 0; i < pmu_device->num_resources; ++i) {
+		err = request_irq(platform_get_irq(pmu_device, i),
+				  armpmu->handle_irq,
 				  IRQF_DISABLED | IRQF_NOBALANCING,
 				  "armpmu", NULL);
 		if (err) {
-			pr_warning("unable to request IRQ%d for ARM "
-				   "perf counters\n", pmu_irqs->irqs[i]);
+			pr_warning("unable to request IRQ%d for ARM perf "
+				"counters\n", platform_get_irq(pmu_device, i));
 			break;
 		}
 	}
 
 	if (err) {
 		for (i = i - 1; i >= 0; --i)
-			free_irq(pmu_irqs->irqs[i], NULL);
-		release_pmu(pmu_irqs);
-		pmu_irqs = NULL;
+			free_irq(platform_get_irq(pmu_device, i), NULL);
+		release_pmu(pmu_device);
+		pmu_device = NULL;
 	}
 
 	return err;
@@ -356,12 +358,12 @@ armpmu_release_hardware(void)
 {
 	int i;
 
-	for (i = pmu_irqs->num_irqs - 1; i >= 0; --i)
-		free_irq(pmu_irqs->irqs[i], NULL);
+	for (i = pmu_device->num_resources - 1; i >= 0; --i)
+		free_irq(platform_get_irq(pmu_device, i), NULL);
 	armpmu->stop();
 
-	release_pmu(pmu_irqs);
-	pmu_irqs = NULL;
+	release_pmu(pmu_device);
+	pmu_device = NULL;
 }
 
 static atomic_t active_events = ATOMIC_INIT(0);
arch/arm/kernel/pmu.c +83 -44

171 lines not on this page · raw message

Signature · 1 line
1.6.3.3
#2 lore raw

PATCH 2/6 ARM: Realview: register PMU IRQs during board initialisation

This patch updates the initialisation routines for the Realview boards so that they register their PMU IRQs with the PMU framework in the Kernel.

---
 arch/arm/mach-realview/realview_eb.c     |   32 ++++++++++++++++++++++++++++++
 arch/arm/mach-realview/realview_pb1176.c |   15 ++++++++++++++
 arch/arm/mach-realview/realview_pb11mp.c |   32 ++++++++++++++++++++++++++++++
 arch/arm/mach-realview/realview_pba8.c   |   15 ++++++++++++++
 arch/arm/mach-realview/realview_pbx.c    |   32 ++++++++++++++++++++++++++++++
 5 files changed, 126 insertions(+), 0 deletions(-)
arch/arm/mach-realview/realview_eb.c +32 -0
index 7d857d3..a4a101a 100644
@@ -31,6 +31,7 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
+#include <asm/pmu.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/icst307.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -294,6 +295,36 @@ static struct resource realview_eb_isp1761_resources[] = {
 	},
 };
 
+static struct resource pmu_resources[] = {
+	[0] = {
+		.start		= IRQ_EB11MP_PMU_CPU0,
+		.end		= IRQ_EB11MP_PMU_CPU0,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start		= IRQ_EB11MP_PMU_CPU1,
+		.end		= IRQ_EB11MP_PMU_CPU1,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start		= IRQ_EB11MP_PMU_CPU2,
+		.end		= IRQ_EB11MP_PMU_CPU2,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start		= IRQ_EB11MP_PMU_CPU3,
+		.end		= IRQ_EB11MP_PMU_CPU3,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device pmu_device = {
+	.name			= "arm-pmu",
+	.id			= ARM_PMU_DEVICE_CPU,
+	.num_resources		= ARRAY_SIZE(pmu_resources),
+	.resource		= pmu_resources,
+};
+
 static void __init gic_init_irq(void)
 {
 	if (core_tile_eb11mp() || core_tile_a9mp()) {
@@ -407,6 +438,7 @@ static void __init realview_eb_init(void)
 		 * Bits:  .... ...0 0111 1001 0000 .... .... .... */
 		l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
 #endif
+		platform_device_register(&pmu_device);
 	}
 
 	realview_flash_register(&realview_eb_flash_resource, 1);
arch/arm/mach-realview/realview_pb1176.c +15 -0
index 44392e5..85429cb 100644
@@ -31,6 +31,7 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
+#include <asm/pmu.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/icst307.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -263,6 +264,19 @@ static struct resource realview_pb1176_isp1761_resources[] = {
 	},
 };
 
+static struct resource pmu_resource = {
+	.start		= IRQ_DC1176_PMU_CPU0,
+	.end		= IRQ_DC1176_PMU_CPU0,
+	.flags		= IORESOURCE_IRQ,
+};
+
+static struct platform_device pmu_device = {
+	.name			= "arm-pmu",
+	.id			= ARM_PMU_DEVICE_CPU,
+	.num_resources		= 1,
+	.resource		= &pmu_resource,
+};
+
 static void __init gic_init_irq(void)
 {
 	/* ARM1176 DevChip GIC, primary */
@@ -324,6 +338,7 @@ static void __init realview_pb1176_init(void)
 	realview_eth_register(NULL, realview_pb1176_smsc911x_resources);
 	platform_device_register(&realview_i2c_device);
 	realview_usb_register(realview_pb1176_isp1761_resources);
+	platform_device_register(&pmu_device);
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 		struct amba_device *d = amba_devs[i];
arch/arm/mach-realview/realview_pb11mp.c +32 -0
index 3e02731..3ab4447 100644
@@ -31,6 +31,7 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
+#include <asm/pmu.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/icst307.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -260,6 +261,36 @@ static struct resource realview_pb11mp_isp1761_resources[] = {
 	},
 };
 
+static struct resource pmu_resources[] = {
+	[0] = {
+		.start		= IRQ_TC11MP_PMU_CPU0,
+		.end		= IRQ_TC11MP_PMU_CPU0,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start		= IRQ_TC11MP_PMU_CPU1,
+		.end		= IRQ_TC11MP_PMU_CPU1,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start		= IRQ_TC11MP_PMU_CPU2,
+		.end		= IRQ_TC11MP_PMU_CPU2,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start		= IRQ_TC11MP_PMU_CPU3,
+		.end		= IRQ_TC11MP_PMU_CPU3,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device pmu_device = {
+	.name			= "arm-pmu",
+	.id			= ARM_PMU_DEVICE_CPU,
+	.num_resources		= ARRAY_SIZE(pmu_resources),
+	.resource		= pmu_resources,
+};
+
 static void __init gic_init_irq(void)
 {
 	unsigned int pldctrl;
@@ -329,6 +360,7 @@ static void __init realview_pb11mp_init(void)
 	platform_device_register(&realview_i2c_device);
 	platform_device_register(&realview_cf_device);
 	realview_usb_register(realview_pb11mp_isp1761_resources);
+	platform_device_register(&pmu_device);
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 		struct amba_device *d = amba_devs[i];
arch/arm/mach-realview/realview_pba8.c +15 -0
index fe4e25c..7b36ea9 100644
@@ -30,6 +30,7 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
+#include <asm/pmu.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/icst307.h>
 
@@ -250,6 +251,19 @@ static struct resource realview_pba8_isp1761_resources[] = {
 	},
 };
 
+static struct resource pmu_resource = {
+	.start		= IRQ_PBA8_PMU,
+	.end		= IRQ_PBA8_PMU,
+	.flags		= IORESOURCE_IRQ,
+};
+
+static struct platform_device pmu_device = {
+	.name			= "arm-pmu",
+	.id			= ARM_PMU_DEVICE_CPU,
+	.num_resources		= 1,
+	.resource		= &pmu_resource,
+};
+
 static void __init gic_init_irq(void)
 {
 	/* ARM PB-A8 on-board GIC */
@@ -296,6 +310,7 @@ static void __init realview_pba8_init(void)
 	platform_device_register(&realview_i2c_device);
 	platform_device_register(&realview_cf_device);
 	realview_usb_register(realview_pba8_isp1761_resources);
+	platform_device_register(&pmu_device);
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 		struct amba_device *d = amba_devs[i];
arch/arm/mach-realview/realview_pbx.c +32 -0
index d94857e..a235ba3 100644
@@ -29,6 +29,7 @@
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
+#include <asm/pmu.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -270,6 +271,36 @@ static struct resource realview_pbx_isp1761_resources[] = {
 	},
 };
 
+static struct resource pmu_resources[] = {
+	[0] = {
+		.start		= IRQ_PBX_PMU_CPU0,
+		.end		= IRQ_PBX_PMU_CPU0,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start		= IRQ_PBX_PMU_CPU1,
+		.end		= IRQ_PBX_PMU_CPU1,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start		= IRQ_PBX_PMU_CPU2,
+		.end		= IRQ_PBX_PMU_CPU2,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start		= IRQ_PBX_PMU_CPU3,
+		.end		= IRQ_PBX_PMU_CPU3,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device pmu_device = {
+	.name			= "arm-pmu",
+	.id			= ARM_PMU_DEVICE_CPU,
+	.num_resources		= ARRAY_SIZE(pmu_resources),
+	.resource		= pmu_resources,
+};
+
 static void __init gic_init_irq(void)
 {
 	/* ARM PBX on-board GIC */
@@ -354,6 +385,7 @@ static void __init realview_pbx_init(void)
 		/* 16KB way size, 8-way associativity, parity disabled
 		 * Bits:  .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */
 		l2x0_init(l2x0_base, 0x02520000, 0xc0000fff);
+		platform_device_register(&pmu_device);
 	}
 #endif
 
Signature · 1 line
1.6.3.3
#3 lore raw

PATCH 3/6 ARM: OMAP: register PMU IRQs during board initialisation

This patch updates the initialisation routines for the OMAP2 and OMAP3 boards so that they register their PMU IRQs with the PMU framework in the Kernel.

---
 arch/arm/mach-omap2/devices.c |   34 ++++++++++++++++++++++++++++++++++
 1 files changed, 34 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/devices.c +34 -0
index 23e4d77..4a1c232 100644
@@ -17,8 +17,10 @@
 #include <linux/clk.h>
 
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
+#include <asm/pmu.h>
 
 #include <plat/control.h>
 #include <plat/tc.h>
@@ -453,6 +455,37 @@ static void omap_init_mcspi(void)
 static inline void omap_init_mcspi(void) {}
 #endif
 
+static struct resource omap2_pmu_resource = {
+	.start	= 3,
+	.end	= 3,
+	.flags	= IORESOURCE_IRQ,
+};
+
+static struct resource omap3_pmu_resource = {
+	.start	= INT_34XX_BENCH_MPU_EMUL,
+	.end	= INT_34XX_BENCH_MPU_EMUL,
+	.flags	= IORESOURCE_IRQ,
+};
+
+static struct platform_device omap_pmu_device = {
+	.name		= "arm-pmu",
+	.id		= ARM_PMU_DEVICE_CPU,
+	.num_resources	= 1,
+};
+
+static void omap_init_pmu(void)
+{
+	if (cpu_is_omap24xx())
+		omap_pmu_device.resource = &omap2_pmu_resource;
+	else if (cpu_is_omap34xx())
+		omap_pmu_device.resource = &omap3_pmu_resource;
+	else
+		return;
+
+	platform_device_register(&omap_pmu_device);
+}
+
+
 #ifdef CONFIG_OMAP_SHA1_MD5
 static struct resource sha1_md5_resources[] = {
 	{
@@ -797,6 +830,7 @@ static int __init omap2_init_devices(void)
 	omap_init_camera();
 	omap_init_mbox();
 	omap_init_mcspi();
+	omap_init_pmu();
 	omap_hdq_init();
 	omap_init_sti();
 	omap_init_sha1_md5();
Signature · 1 line
1.6.3.3
#4 lore raw

PATCH 4/6 ARM: BCMRING: register PMU IRQ during board initialisation

This patch updates the initialisation routine for the BCMRING platform so that it registers its PMU IRQ with the PMU framework in the Kernel.

---
 arch/arm/mach-bcmring/arch.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
arch/arm/mach-bcmring/arch.c +16 -0
index 53dd2a9..2f13919 100644
@@ -29,6 +29,7 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/time.h>
+#include <asm/pmu.h>
 
 #include <asm/mach/arch.h>
 #include <mach/dma.h>
@@ -85,8 +86,23 @@ static struct platform_device nand_device = {
 	.num_resources	= ARRAY_SIZE(nand_resource),
 };
 
+static struct resource pmu_resource = {
+	.start	= IRQ_PMUIRQ,
+	.end	= IRQ_PMUIRQ,
+	.flags	= IORESOURCE_IRQ,
+};
+
+static struct platform_device pmu_device = {
+	.name		= "arm-pmu",
+	.id		= ARM_PMU_DEVICE_CPU,
+	.resource	= &pmu_resource,
+	.num_resources	= 1,
+};
+
+
 static struct platform_device *devices[] __initdata = {
 	&nand_device,
+	&pmu_device,
 };
 
 /****************************************************************************
Signature · 1 line
1.6.3.3
#5 lore raw

PATCH 5/6 ARM: iop3xx: register PMU IRQs during board initialisation

This patch adds an initcall for the iop3xx platforms so that they register their PMU IRQS with the PMU framework in the Kernel.

Cc Lennert Buytenhek <[email protected]>
---
 arch/arm/plat-iop/Makefile |    2 ++
 arch/arm/plat-iop/pmu.c    |   40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-iop/pmu.c
arch/arm/plat-iop/Makefile +2 -0
index 36bff03..69b09c1 100644
@@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_IOP32X) += time.o
 obj-$(CONFIG_ARCH_IOP32X) += io.o
 obj-$(CONFIG_ARCH_IOP32X) += cp6.o
 obj-$(CONFIG_ARCH_IOP32X) += adma.o
+obj-$(CONFIG_ARCH_IOP32X) += pmu.o
 
 # IOP33X
 obj-$(CONFIG_ARCH_IOP33X) += gpio.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_ARCH_IOP33X) += time.o
 obj-$(CONFIG_ARCH_IOP33X) += io.o
 obj-$(CONFIG_ARCH_IOP33X) += cp6.o
 obj-$(CONFIG_ARCH_IOP33X) += adma.o
+obj-$(CONFIG_ARCH_IOP33X) += pmu.o
 
 # IOP13XX
 obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
arch/arm/plat-iop/pmu.c new file +40 -0
new file mode 100644
index 0000000..a2024b8
@@ -0,0 +1,40 @@
+/*
+ * PMU IRQ registration for the iop3xx xscale PMU families.
+ * Copyright (C) 2010 Will Deacon, ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <asm/pmu.h>
+#include <mach/irqs.h>
+
+static struct resource pmu_resource = {
+#ifdef CONFIG_ARCH_IOP32X
+	.start	= IRQ_IOP32X_CORE_PMU,
+	.end	= IRQ_IOP32X_CORE_PMU,
+#endif
+#ifdef CONFIG_ARCH_IOP33X
+	.start	= IRQ_IOP33X_CORE_PMU,
+	.end	= IRQ_IOP33X_CORE_PMU,
+#endif
+	.flags	= IORESOURCE_IRQ,
+};
+
+static struct platform_device pmu_device = {
+	.name		= "arm-pmu",
+	.id		= ARM_PMU_DEVICE_CPU,
+	.resource	= &pmu_resource,
+	.num_resources	= 1,
+};
+
+static int __init iop3xx_pmu_init(void)
+{
+	platform_device_register(&pmu_device);
+	return 0;
+}
+
+arch_initcall(iop3xx_pmu_init);
Signature · 1 line
1.6.3.3
#6 lore raw

PATCH 6/6 ARM: pxa: register PMU IRQs during board initialisation

This patch adds an initcall for the pxa platforms so that they register their PMU IRQs with the PMU framework in the Kernel.

---
 arch/arm/plat-pxa/Makefile |    2 +-
 arch/arm/plat-pxa/pmu.c    |   33 +++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/plat-pxa/pmu.c
arch/arm/plat-pxa/Makefile +1 -1
index 0264bfb..f68da35 100644
@@ -2,7 +2,7 @@
 # Makefile for code common across different PXA processor families
 #
 
-obj-y	:= dma.o
+obj-y	:= dma.o pmu.o
 
 obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_PXA3xx)		+= mfp.o
arch/arm/plat-pxa/pmu.c new file +33 -0
new file mode 100644
index 0000000..267ceb6
@@ -0,0 +1,33 @@
+/*
+ * PMU IRQ registration for the PXA xscale PMU families.
+ * Copyright (C) 2010 Will Deacon, ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <asm/pmu.h>
+#include <mach/irqs.h>
+
+static struct resource pmu_resource = {
+	.start	= IRQ_PMU,
+	.end	= IRQ_PMU,
+	.flags	= IORESOURCE_IRQ,
+};
+
+static struct platform_device pmu_device = {
+	.name		= "arm-pmu",
+	.id		= ARM_PMU_DEVICE_CPU,
+	.resource	= &pmu_resource,
+	.num_resources	= 1,
+};
+
+static int __init pxa_pmu_init(void)
+{
+	platform_device_register(&pmu_device);
+	return 0;
+}
+arch_initcall(pxa_pmu_init);
Signature · 1 line
1.6.3.3
#7 lore raw

PATCH 4/6 ARM: BCMRING: register PMU IRQ during board initialisation

In reply to Will Deacon

Thanks Will.

I like this version using the platform device.

Quoted 49 lines · Will Deacon

This patch updates the initialisation routine for the BCMRING platform so that it registers its PMU IRQ with the PMU framework in the Kernel.

---
 arch/arm/mach-bcmring/arch.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
arch/arm/mach-bcmring/arch.c +16 -0
index 53dd2a9..2f13919 100644
@@ -29,6 +29,7 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/time.h>
+#include <asm/pmu.h>
 
 #include <asm/mach/arch.h>
 #include <mach/dma.h>
@@ -85,8 +86,23 @@ static struct platform_device nand_device = {
 	.num_resources	= ARRAY_SIZE(nand_resource),
 };
 
+static struct resource pmu_resource = {
+	.start	= IRQ_PMUIRQ,
+	.end	= IRQ_PMUIRQ,
+	.flags	= IORESOURCE_IRQ,
+};
+
+static struct platform_device pmu_device = {
+	.name		= "arm-pmu",
+	.id		= ARM_PMU_DEVICE_CPU,
+	.resource	= &pmu_resource,
+	.num_resources	= 1,
+};
+
+
 static struct platform_device *devices[] __initdata = {
 	&nand_device,
+	&pmu_device,
 };
 
 /****************************************************************************
Signature · 1 line
1.6.3.3
Signature · 4 lines
Leo Hao Chen

------------------------
Life is short, run long.
#8 lore raw

PATCH 1/6 ARM: pmu: register IRQs at runtime

In reply to Will Deacon
Quoted 15 lines · Will Deacon

The current PMU infrastructure for ARM requires that the IRQs for the PMU device are fixed at compile time and are selected based on the ARCH_ or MACH_ flags. This has the disadvantage of tying the Kernel down to a particular board as far as profiling is concerned.

This patch replaces the compile-time IRQ registration with a runtime mechanism which allows the IRQs to be registered with the framework as a platform_device.

A further advantage of this change is that there is scope for registering different types of performance counters in the future by changing the id of the platform_device and attaching different resources to it.

Cc Russell King - ARM Linux <[email protected]>
Cc Jamie Iles <[email protected]>

[snip]

Quoted 7 lines
arch/arm/kernel/perf_event.c +3 -2
-	for (i = 0; i < pmu_irqs->num_irqs; ++i) {
-		err = request_irq(pmu_irqs->irqs[i], armpmu->handle_irq,
+	for (i = 0; i < pmu_device->num_resources; ++i) {
+		err = request_irq(platform_get_irq(pmu_device, i),
+				  armpmu->handle_irq,
 				  IRQF_DISABLED | IRQF_NOBALANCING,
 				  "armpmu", NULL);

[snip]

arch/arm/kernel/perf_event.c armpmu_release_hardware(void) · line 362

Quoted 8 lines
arch/arm/kernel/perf_event.c +2 -2
@@ -356,12 +358,12 @@ armpmu_release_hardware(void)
 {
 	int i;
 
-	for (i = pmu_irqs->num_irqs - 1; i >= 0; --i)
-		free_irq(pmu_irqs->irqs[i], NULL);
+	for (i = pmu_device->num_resources - 1; i >= 0; --i)
+		free_irq(platform_get_irq(pmu_device, i), NULL);

Hi Will,

This looks fine at the moment as all PMU's only have IRQ resources but if we ever have any with memory resources then we'll need to check the return value of platform_get_irq() to make sure that the resource is a valid IRQ. Apologies for not spotting it before! If we had:

	int irq = platform_get_irq(pmu_device, i);
	if (irq < 0)
		continue;

or something similar to be a bit future proof then I'm happy with that and:

Jamie

#9 lore raw

cover ARM: pmu: provide a registration mechanism for IRQs [v3]

In reply to Will Deacon
Quoted 4 lines · Will Deacon

This is version 3 of the patch series originally posted here:

v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2010-March/011162.html
v2: http://lists.infradead.org/pipermail/linux-arm-kernel/2010-March/011339.html

Unfortunately, these patches are inter-dependent - if I apply the realview patch to my 'versatile' branch without the first patch, then it breaks the realview build because ARM_PMU_DEVICE_CPU is not defined.

But if I apply the first patch initially, everything using the new PMU infrastructure breaks until the other patches are applied.

Please can we have an ordered set which doesn't break compilation. What I think should happen is the first patch should introduce the new definitions required for the platform data, and the rest of the first patch should come at the very end.

Thanks.

#10 lore raw

cover ARM: pmu: provide a registration mechanism for IRQs [v3]

Hi Russell,

Quoted 4 lines

Please can we have an ordered set which doesn't break compilation. What I think should happen is the first patch should introduce the new definitions required for the platform data, and the rest of the first patch should come at the very end.

Sorry about this. I've split up the first patch so that the first half is now:

ARM: pmu: add enum describing PMU types

This patch adds an enum describing the potential PMU device types in preparation for PMU device registration via platform devices.

arch/arm/include/asm/pmu.h +5 -0
index 2829b9f..44bec1f 100644
@@ -12,6 +12,11 @@
 #ifndef __ARM_PMU_H__
 #define __ARM_PMU_H__
 
+enum arm_pmu_type {
+       ARM_PMU_DEVICE_CPU      = 0,
+       ARM_NUM_PMU_DEVICES,
+};
+
 #ifdef CONFIG_CPU_HAS_PMU
 
 struct pmu_irqs {

which gets rid of the compilation failures. I can either supersede the existing patch with two more or resubmit the whole series. Which would you prefer?

Thanks,

Will

#11 lore raw

cover ARM: pmu: provide a registration mechanism for IRQs [v3]

Quoted 34 lines · Will Deacon

Hi Russell,

Quoted 4 lines

Please can we have an ordered set which doesn't break compilation. What I think should happen is the first patch should introduce the new definitions required for the platform data, and the rest of the first patch should come at the very end.

Sorry about this. I've split up the first patch so that the first half is now:

ARM: pmu: add enum describing PMU types

This patch adds an enum describing the potential PMU device types in preparation for PMU device registration via platform devices.

arch/arm/include/asm/pmu.h +5 -0
index 2829b9f..44bec1f 100644
@@ -12,6 +12,11 @@
 #ifndef __ARM_PMU_H__
 #define __ARM_PMU_H__
 
+enum arm_pmu_type {
+       ARM_PMU_DEVICE_CPU      = 0,
+       ARM_NUM_PMU_DEVICES,
+};
+
 #ifdef CONFIG_CPU_HAS_PMU
 
 struct pmu_irqs {
Quoted 3 lines

which gets rid of the compilation failures. I can either supersede the existing patch with two more or resubmit the whole series. Which would you prefer?

Can you just deal with the single patch to be superseded; the rest are fine.

#12 lore raw

cover ARM: pmu: provide a registration mechanism for IRQs [v3]

Hello Russell,

Quoted 2 lines

Can you just deal with the single patch to be superseded; the rest are fine.

I've submitted the replacement patches as 6063/1 and 6064/1.

Thanks,

Will