diff options
29 files changed, 468 insertions, 449 deletions
diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt index 1c044eb320cc..343781b9f246 100644 --- a/Documentation/devicetree/bindings/arm/pmu.txt +++ b/Documentation/devicetree/bindings/arm/pmu.txt | |||
@@ -7,8 +7,12 @@ representation in the device tree should be done as under:- | |||
7 | Required properties: | 7 | Required properties: |
8 | 8 | ||
9 | - compatible : should be one of | 9 | - compatible : should be one of |
10 | "arm,cortex-a15-pmu" | ||
10 | "arm,cortex-a9-pmu" | 11 | "arm,cortex-a9-pmu" |
11 | "arm,cortex-a8-pmu" | 12 | "arm,cortex-a8-pmu" |
13 | "arm,cortex-a7-pmu" | ||
14 | "arm,cortex-a5-pmu" | ||
15 | "arm,arm11mpcore-pmu" | ||
12 | "arm,arm1176-pmu" | 16 | "arm,arm1176-pmu" |
13 | "arm,arm1136-pmu" | 17 | "arm,arm1136-pmu" |
14 | - interrupts : 1 combined interrupt or 1 per core. | 18 | - interrupts : 1 combined interrupt or 1 per core. |
diff --git a/MAINTAINERS b/MAINTAINERS index fdc0119963e7..437a7dd36843 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -595,7 +595,6 @@ M: Will Deacon <will.deacon@arm.com> | |||
595 | S: Maintained | 595 | S: Maintained |
596 | F: arch/arm/kernel/perf_event* | 596 | F: arch/arm/kernel/perf_event* |
597 | F: arch/arm/oprofile/common.c | 597 | F: arch/arm/oprofile/common.c |
598 | F: arch/arm/kernel/pmu.c | ||
599 | F: arch/arm/include/asm/pmu.h | 598 | F: arch/arm/include/asm/pmu.h |
600 | F: arch/arm/kernel/hw_breakpoint.c | 599 | F: arch/arm/kernel/hw_breakpoint.c |
601 | F: arch/arm/include/asm/hw_breakpoint.h | 600 | F: arch/arm/include/asm/hw_breakpoint.h |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c5f9ae5dbd1a..46ef5652da68 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1179,12 +1179,6 @@ config XSCALE_PMU | |||
1179 | depends on CPU_XSCALE | 1179 | depends on CPU_XSCALE |
1180 | default y | 1180 | default y |
1181 | 1181 | ||
1182 | config CPU_HAS_PMU | ||
1183 | depends on (CPU_V6 || CPU_V6K || CPU_V7 || XSCALE_PMU) && \ | ||
1184 | (!ARCH_OMAP3 || OMAP3_EMU) | ||
1185 | default y | ||
1186 | bool | ||
1187 | |||
1188 | config MULTI_IRQ_HANDLER | 1182 | config MULTI_IRQ_HANDLER |
1189 | bool | 1183 | bool |
1190 | help | 1184 | help |
@@ -1757,7 +1751,7 @@ config HIGHPTE | |||
1757 | 1751 | ||
1758 | config HW_PERF_EVENTS | 1752 | config HW_PERF_EVENTS |
1759 | bool "Enable hardware performance counter support for perf events" | 1753 | bool "Enable hardware performance counter support for perf events" |
1760 | depends on PERF_EVENTS && CPU_HAS_PMU | 1754 | depends on PERF_EVENTS |
1761 | default y | 1755 | default y |
1762 | help | 1756 | help |
1763 | Enable hardware performance counter support for perf events. If | 1757 | Enable hardware performance counter support for perf events. If |
diff --git a/arch/arm/configs/kzm9d_defconfig b/arch/arm/configs/kzm9d_defconfig index 26146ffea1a5..8c49df66cac3 100644 --- a/arch/arm/configs/kzm9d_defconfig +++ b/arch/arm/configs/kzm9d_defconfig | |||
@@ -8,6 +8,7 @@ CONFIG_LOG_BUF_SHIFT=16 | |||
8 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | 8 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
9 | CONFIG_SYSCTL_SYSCALL=y | 9 | CONFIG_SYSCTL_SYSCALL=y |
10 | CONFIG_EMBEDDED=y | 10 | CONFIG_EMBEDDED=y |
11 | CONFIG_PERF_EVENTS=y | ||
11 | CONFIG_SLAB=y | 12 | CONFIG_SLAB=y |
12 | # CONFIG_BLK_DEV_BSG is not set | 13 | # CONFIG_BLK_DEV_BSG is not set |
13 | # CONFIG_IOSCHED_DEADLINE is not set | 14 | # CONFIG_IOSCHED_DEADLINE is not set |
diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig index 2388c8610627..5d0c66708960 100644 --- a/arch/arm/configs/kzm9g_defconfig +++ b/arch/arm/configs/kzm9g_defconfig | |||
@@ -14,6 +14,7 @@ CONFIG_NAMESPACES=y | |||
14 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | 14 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
15 | CONFIG_SYSCTL_SYSCALL=y | 15 | CONFIG_SYSCTL_SYSCALL=y |
16 | CONFIG_EMBEDDED=y | 16 | CONFIG_EMBEDDED=y |
17 | CONFIG_PERF_EVENTS=y | ||
17 | CONFIG_SLAB=y | 18 | CONFIG_SLAB=y |
18 | CONFIG_MODULES=y | 19 | CONFIG_MODULES=y |
19 | CONFIG_MODULE_FORCE_LOAD=y | 20 | CONFIG_MODULE_FORCE_LOAD=y |
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index e074948d8143..625cd621a436 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h | |||
@@ -12,6 +12,13 @@ | |||
12 | #ifndef __ARM_PERF_EVENT_H__ | 12 | #ifndef __ARM_PERF_EVENT_H__ |
13 | #define __ARM_PERF_EVENT_H__ | 13 | #define __ARM_PERF_EVENT_H__ |
14 | 14 | ||
15 | /* Nothing to see here... */ | 15 | /* |
16 | * The ARMv7 CPU PMU supports up to 32 event counters. | ||
17 | */ | ||
18 | #define ARMPMU_MAX_HWEVENTS 32 | ||
19 | |||
20 | #define HW_OP_UNSUPPORTED 0xFFFF | ||
21 | #define C(_x) PERF_COUNT_HW_CACHE_##_x | ||
22 | #define CACHE_OP_UNSUPPORTED 0xFFFF | ||
16 | 23 | ||
17 | #endif /* __ARM_PERF_EVENT_H__ */ | 24 | #endif /* __ARM_PERF_EVENT_H__ */ |
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 4432305f4a2a..a26170dce02e 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h | |||
@@ -16,69 +16,30 @@ | |||
16 | #include <linux/perf_event.h> | 16 | #include <linux/perf_event.h> |
17 | 17 | ||
18 | /* | 18 | /* |
19 | * Types of PMUs that can be accessed directly and require mutual | ||
20 | * exclusion between profiling tools. | ||
21 | */ | ||
22 | enum arm_pmu_type { | ||
23 | ARM_PMU_DEVICE_CPU = 0, | ||
24 | ARM_NUM_PMU_DEVICES, | ||
25 | }; | ||
26 | |||
27 | /* | ||
28 | * struct arm_pmu_platdata - ARM PMU platform data | 19 | * struct arm_pmu_platdata - ARM PMU platform data |
29 | * | 20 | * |
30 | * @handle_irq: an optional handler which will be called from the | 21 | * @handle_irq: an optional handler which will be called from the |
31 | * interrupt and passed the address of the low level handler, | 22 | * interrupt and passed the address of the low level handler, |
32 | * and can be used to implement any platform specific handling | 23 | * and can be used to implement any platform specific handling |
33 | * before or after calling it. | 24 | * before or after calling it. |
34 | * @enable_irq: an optional handler which will be called after | 25 | * @runtime_resume: an optional handler which will be called by the |
35 | * request_irq and be used to handle some platform specific | 26 | * runtime PM framework following a call to pm_runtime_get(). |
36 | * irq enablement | 27 | * Note that if pm_runtime_get() is called more than once in |
37 | * @disable_irq: an optional handler which will be called before | 28 | * succession this handler will only be called once. |
38 | * free_irq and be used to handle some platform specific | 29 | * @runtime_suspend: an optional handler which will be called by the |
39 | * irq disablement | 30 | * runtime PM framework following a call to pm_runtime_put(). |
31 | * Note that if pm_runtime_get() is called more than once in | ||
32 | * succession this handler will only be called following the | ||
33 | * final call to pm_runtime_put() that actually disables the | ||
34 | * hardware. | ||
40 | */ | 35 | */ |
41 | struct arm_pmu_platdata { | 36 | struct arm_pmu_platdata { |
42 | irqreturn_t (*handle_irq)(int irq, void *dev, | 37 | irqreturn_t (*handle_irq)(int irq, void *dev, |
43 | irq_handler_t pmu_handler); | 38 | irq_handler_t pmu_handler); |
44 | void (*enable_irq)(int irq); | 39 | int (*runtime_resume)(struct device *dev); |
45 | void (*disable_irq)(int irq); | 40 | int (*runtime_suspend)(struct device *dev); |
46 | }; | 41 | }; |
47 | 42 | ||
48 | #ifdef CONFIG_CPU_HAS_PMU | ||
49 | |||
50 | /** | ||
51 | * reserve_pmu() - reserve the hardware performance counters | ||
52 | * | ||
53 | * Reserve the hardware performance counters in the system for exclusive use. | ||
54 | * Returns 0 on success or -EBUSY if the lock is already held. | ||
55 | */ | ||
56 | extern int | ||
57 | reserve_pmu(enum arm_pmu_type type); | ||
58 | |||
59 | /** | ||
60 | * release_pmu() - Relinquish control of the performance counters | ||
61 | * | ||
62 | * Release the performance counters and allow someone else to use them. | ||
63 | */ | ||
64 | extern void | ||
65 | release_pmu(enum arm_pmu_type type); | ||
66 | |||
67 | #else /* CONFIG_CPU_HAS_PMU */ | ||
68 | |||
69 | #include <linux/err.h> | ||
70 | |||
71 | static inline int | ||
72 | reserve_pmu(enum arm_pmu_type type) | ||
73 | { | ||
74 | return -ENODEV; | ||
75 | } | ||
76 | |||
77 | static inline void | ||
78 | release_pmu(enum arm_pmu_type type) { } | ||
79 | |||
80 | #endif /* CONFIG_CPU_HAS_PMU */ | ||
81 | |||
82 | #ifdef CONFIG_HW_PERF_EVENTS | 43 | #ifdef CONFIG_HW_PERF_EVENTS |
83 | 44 | ||
84 | /* The events for a given PMU register set. */ | 45 | /* The events for a given PMU register set. */ |
@@ -103,7 +64,6 @@ struct pmu_hw_events { | |||
103 | 64 | ||
104 | struct arm_pmu { | 65 | struct arm_pmu { |
105 | struct pmu pmu; | 66 | struct pmu pmu; |
106 | enum arm_pmu_type type; | ||
107 | cpumask_t active_irqs; | 67 | cpumask_t active_irqs; |
108 | char *name; | 68 | char *name; |
109 | irqreturn_t (*handle_irq)(int irq_num, void *dev); | 69 | irqreturn_t (*handle_irq)(int irq_num, void *dev); |
@@ -118,6 +78,8 @@ struct arm_pmu { | |||
118 | void (*start)(void); | 78 | void (*start)(void); |
119 | void (*stop)(void); | 79 | void (*stop)(void); |
120 | void (*reset)(void *); | 80 | void (*reset)(void *); |
81 | int (*request_irq)(irq_handler_t handler); | ||
82 | void (*free_irq)(void); | ||
121 | int (*map_event)(struct perf_event *event); | 83 | int (*map_event)(struct perf_event *event); |
122 | int num_events; | 84 | int num_events; |
123 | atomic_t active_events; | 85 | atomic_t active_events; |
@@ -129,7 +91,9 @@ struct arm_pmu { | |||
129 | 91 | ||
130 | #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) | 92 | #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) |
131 | 93 | ||
132 | int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type); | 94 | extern const struct dev_pm_ops armpmu_dev_pm_ops; |
95 | |||
96 | int armpmu_register(struct arm_pmu *armpmu, char *name, int type); | ||
133 | 97 | ||
134 | u64 armpmu_event_update(struct perf_event *event, | 98 | u64 armpmu_event_update(struct perf_event *event, |
135 | struct hw_perf_event *hwc, | 99 | struct hw_perf_event *hwc, |
@@ -139,6 +103,13 @@ int armpmu_event_set_period(struct perf_event *event, | |||
139 | struct hw_perf_event *hwc, | 103 | struct hw_perf_event *hwc, |
140 | int idx); | 104 | int idx); |
141 | 105 | ||
106 | int armpmu_map_event(struct perf_event *event, | ||
107 | const unsigned (*event_map)[PERF_COUNT_HW_MAX], | ||
108 | const unsigned (*cache_map)[PERF_COUNT_HW_CACHE_MAX] | ||
109 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
110 | [PERF_COUNT_HW_CACHE_RESULT_MAX], | ||
111 | u32 raw_event_mask); | ||
112 | |||
142 | #endif /* CONFIG_HW_PERF_EVENTS */ | 113 | #endif /* CONFIG_HW_PERF_EVENTS */ |
143 | 114 | ||
144 | #endif /* __ARM_PMU_H__ */ | 115 | #endif /* __ARM_PMU_H__ */ |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7ad2d5cf7008..1c4321430737 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -69,8 +69,7 @@ obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o | |||
69 | obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o | 69 | obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o |
70 | obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o | 70 | obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o |
71 | obj-$(CONFIG_IWMMXT) += iwmmxt.o | 71 | obj-$(CONFIG_IWMMXT) += iwmmxt.o |
72 | obj-$(CONFIG_CPU_HAS_PMU) += pmu.o | 72 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_event_cpu.o |
73 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o | ||
74 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt | 73 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt |
75 | obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o | 74 | obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o |
76 | 75 | ||
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index ab243b87118d..93971b1a4f0b 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -12,68 +12,15 @@ | |||
12 | */ | 12 | */ |
13 | #define pr_fmt(fmt) "hw perfevents: " fmt | 13 | #define pr_fmt(fmt) "hw perfevents: " fmt |
14 | 14 | ||
15 | #include <linux/bitmap.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
18 | #include <linux/export.h> | ||
19 | #include <linux/perf_event.h> | ||
20 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
21 | #include <linux/spinlock.h> | 17 | #include <linux/pm_runtime.h> |
22 | #include <linux/uaccess.h> | 18 | #include <linux/uaccess.h> |
23 | 19 | ||
24 | #include <asm/cputype.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <asm/irq_regs.h> | 20 | #include <asm/irq_regs.h> |
27 | #include <asm/pmu.h> | 21 | #include <asm/pmu.h> |
28 | #include <asm/stacktrace.h> | 22 | #include <asm/stacktrace.h> |
29 | 23 | ||
30 | /* | ||
31 | * ARMv6 supports a maximum of 3 events, starting from index 0. If we add | ||
32 | * another platform that supports more, we need to increase this to be the | ||
33 | * largest of all platforms. | ||
34 | * | ||
35 | * ARMv7 supports up to 32 events: | ||
36 | * cycle counter CCNT + 31 events counters CNT0..30. | ||
37 | * Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters. | ||
38 | */ | ||
39 | #define ARMPMU_MAX_HWEVENTS 32 | ||
40 | |||
41 | static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events); | ||
42 | static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask); | ||
43 | static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); | ||
44 | |||
45 | #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) | ||
46 | |||
47 | /* Set at runtime when we know what CPU type we are. */ | ||
48 | static struct arm_pmu *cpu_pmu; | ||
49 | |||
50 | const char *perf_pmu_name(void) | ||
51 | { | ||
52 | if (!cpu_pmu) | ||
53 | return NULL; | ||
54 | |||
55 | return cpu_pmu->pmu.name; | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(perf_pmu_name); | ||
58 | |||
59 | int perf_num_counters(void) | ||
60 | { | ||
61 | int max_events = 0; | ||
62 | |||
63 | if (cpu_pmu != NULL) | ||
64 | max_events = cpu_pmu->num_events; | ||
65 | |||
66 | return max_events; | ||
67 | } | ||
68 | EXPORT_SYMBOL_GPL(perf_num_counters); | ||
69 | |||
70 | #define HW_OP_UNSUPPORTED 0xFFFF | ||
71 | |||
72 | #define C(_x) \ | ||
73 | PERF_COUNT_HW_CACHE_##_x | ||
74 | |||
75 | #define CACHE_OP_UNSUPPORTED 0xFFFF | ||
76 | |||
77 | static int | 24 | static int |
78 | armpmu_map_cache_event(const unsigned (*cache_map) | 25 | armpmu_map_cache_event(const unsigned (*cache_map) |
79 | [PERF_COUNT_HW_CACHE_MAX] | 26 | [PERF_COUNT_HW_CACHE_MAX] |
@@ -104,7 +51,7 @@ armpmu_map_cache_event(const unsigned (*cache_map) | |||
104 | } | 51 | } |
105 | 52 | ||
106 | static int | 53 | static int |
107 | armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) | 54 | armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) |
108 | { | 55 | { |
109 | int mapping = (*event_map)[config]; | 56 | int mapping = (*event_map)[config]; |
110 | return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; | 57 | return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; |
@@ -116,19 +63,20 @@ armpmu_map_raw_event(u32 raw_event_mask, u64 config) | |||
116 | return (int)(config & raw_event_mask); | 63 | return (int)(config & raw_event_mask); |
117 | } | 64 | } |
118 | 65 | ||
119 | static int map_cpu_event(struct perf_event *event, | 66 | int |
120 | const unsigned (*event_map)[PERF_COUNT_HW_MAX], | 67 | armpmu_map_event(struct perf_event *event, |
121 | const unsigned (*cache_map) | 68 | const unsigned (*event_map)[PERF_COUNT_HW_MAX], |
122 | [PERF_COUNT_HW_CACHE_MAX] | 69 | const unsigned (*cache_map) |
123 | [PERF_COUNT_HW_CACHE_OP_MAX] | 70 | [PERF_COUNT_HW_CACHE_MAX] |
124 | [PERF_COUNT_HW_CACHE_RESULT_MAX], | 71 | [PERF_COUNT_HW_CACHE_OP_MAX] |
125 | u32 raw_event_mask) | 72 | [PERF_COUNT_HW_CACHE_RESULT_MAX], |
73 | u32 raw_event_mask) | ||
126 | { | 74 | { |
127 | u64 config = event->attr.config; | 75 | u64 config = event->attr.config; |
128 | 76 | ||
129 | switch (event->attr.type) { | 77 | switch (event->attr.type) { |
130 | case PERF_TYPE_HARDWARE: | 78 | case PERF_TYPE_HARDWARE: |
131 | return armpmu_map_event(event_map, config); | 79 | return armpmu_map_hw_event(event_map, config); |
132 | case PERF_TYPE_HW_CACHE: | 80 | case PERF_TYPE_HW_CACHE: |
133 | return armpmu_map_cache_event(cache_map, config); | 81 | return armpmu_map_cache_event(cache_map, config); |
134 | case PERF_TYPE_RAW: | 82 | case PERF_TYPE_RAW: |
@@ -222,7 +170,6 @@ armpmu_stop(struct perf_event *event, int flags) | |||
222 | */ | 170 | */ |
223 | if (!(hwc->state & PERF_HES_STOPPED)) { | 171 | if (!(hwc->state & PERF_HES_STOPPED)) { |
224 | armpmu->disable(hwc, hwc->idx); | 172 | armpmu->disable(hwc, hwc->idx); |
225 | barrier(); /* why? */ | ||
226 | armpmu_event_update(event, hwc, hwc->idx); | 173 | armpmu_event_update(event, hwc, hwc->idx); |
227 | hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; | 174 | hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; |
228 | } | 175 | } |
@@ -350,99 +297,41 @@ validate_group(struct perf_event *event) | |||
350 | return 0; | 297 | return 0; |
351 | } | 298 | } |
352 | 299 | ||
353 | static irqreturn_t armpmu_platform_irq(int irq, void *dev) | 300 | static irqreturn_t armpmu_dispatch_irq(int irq, void *dev) |
354 | { | 301 | { |
355 | struct arm_pmu *armpmu = (struct arm_pmu *) dev; | 302 | struct arm_pmu *armpmu = (struct arm_pmu *) dev; |
356 | struct platform_device *plat_device = armpmu->plat_device; | 303 | struct platform_device *plat_device = armpmu->plat_device; |
357 | struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev); | 304 | struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev); |
358 | 305 | ||
359 | return plat->handle_irq(irq, dev, armpmu->handle_irq); | 306 | if (plat && plat->handle_irq) |
307 | return plat->handle_irq(irq, dev, armpmu->handle_irq); | ||
308 | else | ||
309 | return armpmu->handle_irq(irq, dev); | ||
360 | } | 310 | } |
361 | 311 | ||
362 | static void | 312 | static void |
363 | armpmu_release_hardware(struct arm_pmu *armpmu) | 313 | armpmu_release_hardware(struct arm_pmu *armpmu) |
364 | { | 314 | { |
365 | int i, irq, irqs; | 315 | armpmu->free_irq(); |
366 | struct platform_device *pmu_device = armpmu->plat_device; | 316 | pm_runtime_put_sync(&armpmu->plat_device->dev); |
367 | struct arm_pmu_platdata *plat = | ||
368 | dev_get_platdata(&pmu_device->dev); | ||
369 | |||
370 | irqs = min(pmu_device->num_resources, num_possible_cpus()); | ||
371 | |||
372 | for (i = 0; i < irqs; ++i) { | ||
373 | if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs)) | ||
374 | continue; | ||
375 | irq = platform_get_irq(pmu_device, i); | ||
376 | if (irq >= 0) { | ||
377 | if (plat && plat->disable_irq) | ||
378 | plat->disable_irq(irq); | ||
379 | free_irq(irq, armpmu); | ||
380 | } | ||
381 | } | ||
382 | |||
383 | release_pmu(armpmu->type); | ||
384 | } | 317 | } |
385 | 318 | ||
386 | static int | 319 | static int |
387 | armpmu_reserve_hardware(struct arm_pmu *armpmu) | 320 | armpmu_reserve_hardware(struct arm_pmu *armpmu) |
388 | { | 321 | { |
389 | struct arm_pmu_platdata *plat; | 322 | int err; |
390 | irq_handler_t handle_irq; | ||
391 | int i, err, irq, irqs; | ||
392 | struct platform_device *pmu_device = armpmu->plat_device; | 323 | struct platform_device *pmu_device = armpmu->plat_device; |
393 | 324 | ||
394 | if (!pmu_device) | 325 | if (!pmu_device) |
395 | return -ENODEV; | 326 | return -ENODEV; |
396 | 327 | ||
397 | err = reserve_pmu(armpmu->type); | 328 | pm_runtime_get_sync(&pmu_device->dev); |
329 | err = armpmu->request_irq(armpmu_dispatch_irq); | ||
398 | if (err) { | 330 | if (err) { |
399 | pr_warning("unable to reserve pmu\n"); | 331 | armpmu_release_hardware(armpmu); |
400 | return err; | 332 | return err; |
401 | } | 333 | } |
402 | 334 | ||
403 | plat = dev_get_platdata(&pmu_device->dev); | ||
404 | if (plat && plat->handle_irq) | ||
405 | handle_irq = armpmu_platform_irq; | ||
406 | else | ||
407 | handle_irq = armpmu->handle_irq; | ||
408 | |||
409 | irqs = min(pmu_device->num_resources, num_possible_cpus()); | ||
410 | if (irqs < 1) { | ||
411 | pr_err("no irqs for PMUs defined\n"); | ||
412 | return -ENODEV; | ||
413 | } | ||
414 | |||
415 | for (i = 0; i < irqs; ++i) { | ||
416 | err = 0; | ||
417 | irq = platform_get_irq(pmu_device, i); | ||
418 | if (irq < 0) | ||
419 | continue; | ||
420 | |||
421 | /* | ||
422 | * If we have a single PMU interrupt that we can't shift, | ||
423 | * assume that we're running on a uniprocessor machine and | ||
424 | * continue. Otherwise, continue without this interrupt. | ||
425 | */ | ||
426 | if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) { | ||
427 | pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", | ||
428 | irq, i); | ||
429 | continue; | ||
430 | } | ||
431 | |||
432 | err = request_irq(irq, handle_irq, | ||
433 | IRQF_DISABLED | IRQF_NOBALANCING, | ||
434 | "arm-pmu", armpmu); | ||
435 | if (err) { | ||
436 | pr_err("unable to request IRQ%d for ARM PMU counters\n", | ||
437 | irq); | ||
438 | armpmu_release_hardware(armpmu); | ||
439 | return err; | ||
440 | } else if (plat && plat->enable_irq) | ||
441 | plat->enable_irq(irq); | ||
442 | |||
443 | cpumask_set_cpu(i, &armpmu->active_irqs); | ||
444 | } | ||
445 | |||
446 | return 0; | 335 | return 0; |
447 | } | 336 | } |
448 | 337 | ||
@@ -581,6 +470,32 @@ static void armpmu_disable(struct pmu *pmu) | |||
581 | armpmu->stop(); | 470 | armpmu->stop(); |
582 | } | 471 | } |
583 | 472 | ||
473 | #ifdef CONFIG_PM_RUNTIME | ||
474 | static int armpmu_runtime_resume(struct device *dev) | ||
475 | { | ||
476 | struct arm_pmu_platdata *plat = dev_get_platdata(dev); | ||
477 | |||
478 | if (plat && plat->runtime_resume) | ||
479 | return plat->runtime_resume(dev); | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int armpmu_runtime_suspend(struct device *dev) | ||
485 | { | ||
486 | struct arm_pmu_platdata *plat = dev_get_platdata(dev); | ||
487 | |||
488 | if (plat && plat->runtime_suspend) | ||
489 | return plat->runtime_suspend(dev); | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | #endif | ||
494 | |||
495 | const struct dev_pm_ops armpmu_dev_pm_ops = { | ||
496 | SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL) | ||
497 | }; | ||
498 | |||
584 | static void __init armpmu_init(struct arm_pmu *armpmu) | 499 | static void __init armpmu_init(struct arm_pmu *armpmu) |
585 | { | 500 | { |
586 | atomic_set(&armpmu->active_events, 0); | 501 | atomic_set(&armpmu->active_events, 0); |
@@ -598,174 +513,14 @@ static void __init armpmu_init(struct arm_pmu *armpmu) | |||
598 | }; | 513 | }; |
599 | } | 514 | } |
600 | 515 | ||
601 | int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type) | 516 | int armpmu_register(struct arm_pmu *armpmu, char *name, int type) |
602 | { | 517 | { |
603 | armpmu_init(armpmu); | 518 | armpmu_init(armpmu); |
519 | pr_info("enabled with %s PMU driver, %d counters available\n", | ||
520 | armpmu->name, armpmu->num_events); | ||
604 | return perf_pmu_register(&armpmu->pmu, name, type); | 521 | return perf_pmu_register(&armpmu->pmu, name, type); |
605 | } | 522 | } |
606 | 523 | ||
607 | /* Include the PMU-specific implementations. */ | ||
608 | #include "perf_event_xscale.c" | ||
609 | #include "perf_event_v6.c" | ||
610 | #include "perf_event_v7.c" | ||
611 | |||
612 | /* | ||
613 | * Ensure the PMU has sane values out of reset. | ||
614 | * This requires SMP to be available, so exists as a separate initcall. | ||
615 | */ | ||
616 | static int __init | ||
617 | cpu_pmu_reset(void) | ||
618 | { | ||
619 | if (cpu_pmu && cpu_pmu->reset) | ||
620 | return on_each_cpu(cpu_pmu->reset, NULL, 1); | ||
621 | return 0; | ||
622 | } | ||
623 | arch_initcall(cpu_pmu_reset); | ||
624 | |||
625 | /* | ||
626 | * PMU platform driver and devicetree bindings. | ||
627 | */ | ||
628 | static struct of_device_id armpmu_of_device_ids[] = { | ||
629 | {.compatible = "arm,cortex-a9-pmu"}, | ||
630 | {.compatible = "arm,cortex-a8-pmu"}, | ||
631 | {.compatible = "arm,arm1136-pmu"}, | ||
632 | {.compatible = "arm,arm1176-pmu"}, | ||
633 | {}, | ||
634 | }; | ||
635 | |||
636 | static struct platform_device_id armpmu_plat_device_ids[] = { | ||
637 | {.name = "arm-pmu"}, | ||
638 | {}, | ||
639 | }; | ||
640 | |||
641 | static int __devinit armpmu_device_probe(struct platform_device *pdev) | ||
642 | { | ||
643 | if (!cpu_pmu) | ||
644 | return -ENODEV; | ||
645 | |||
646 | cpu_pmu->plat_device = pdev; | ||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | static struct platform_driver armpmu_driver = { | ||
651 | .driver = { | ||
652 | .name = "arm-pmu", | ||
653 | .of_match_table = armpmu_of_device_ids, | ||
654 | }, | ||
655 | .probe = armpmu_device_probe, | ||
656 | .id_table = armpmu_plat_device_ids, | ||
657 | }; | ||
658 | |||
659 | static int __init register_pmu_driver(void) | ||
660 | { | ||
661 | return platform_driver_register(&armpmu_driver); | ||
662 | } | ||
663 | device_initcall(register_pmu_driver); | ||
664 | |||
665 | static struct pmu_hw_events *armpmu_get_cpu_events(void) | ||
666 | { | ||
667 | return &__get_cpu_var(cpu_hw_events); | ||
668 | } | ||
669 | |||
670 | static void __init cpu_pmu_init(struct arm_pmu *armpmu) | ||
671 | { | ||
672 | int cpu; | ||
673 | for_each_possible_cpu(cpu) { | ||
674 | struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu); | ||
675 | events->events = per_cpu(hw_events, cpu); | ||
676 | events->used_mask = per_cpu(used_mask, cpu); | ||
677 | raw_spin_lock_init(&events->pmu_lock); | ||
678 | } | ||
679 | armpmu->get_hw_events = armpmu_get_cpu_events; | ||
680 | armpmu->type = ARM_PMU_DEVICE_CPU; | ||
681 | } | ||
682 | |||
683 | /* | ||
684 | * PMU hardware loses all context when a CPU goes offline. | ||
685 | * When a CPU is hotplugged back in, since some hardware registers are | ||
686 | * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading | ||
687 | * junk values out of them. | ||
688 | */ | ||
689 | static int __cpuinit pmu_cpu_notify(struct notifier_block *b, | ||
690 | unsigned long action, void *hcpu) | ||
691 | { | ||
692 | if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) | ||
693 | return NOTIFY_DONE; | ||
694 | |||
695 | if (cpu_pmu && cpu_pmu->reset) | ||
696 | cpu_pmu->reset(NULL); | ||
697 | |||
698 | return NOTIFY_OK; | ||
699 | } | ||
700 | |||
701 | static struct notifier_block __cpuinitdata pmu_cpu_notifier = { | ||
702 | .notifier_call = pmu_cpu_notify, | ||
703 | }; | ||
704 | |||
705 | /* | ||
706 | * CPU PMU identification and registration. | ||
707 | */ | ||
708 | static int __init | ||
709 | init_hw_perf_events(void) | ||
710 | { | ||
711 | unsigned long cpuid = read_cpuid_id(); | ||
712 | unsigned long implementor = (cpuid & 0xFF000000) >> 24; | ||
713 | unsigned long part_number = (cpuid & 0xFFF0); | ||
714 | |||
715 | /* ARM Ltd CPUs. */ | ||
716 | if (0x41 == implementor) { | ||
717 | switch (part_number) { | ||
718 | case 0xB360: /* ARM1136 */ | ||
719 | case 0xB560: /* ARM1156 */ | ||
720 | case 0xB760: /* ARM1176 */ | ||
721 | cpu_pmu = armv6pmu_init(); | ||
722 | break; | ||
723 | case 0xB020: /* ARM11mpcore */ | ||
724 | cpu_pmu = armv6mpcore_pmu_init(); | ||
725 | break; | ||
726 | case 0xC080: /* Cortex-A8 */ | ||
727 | cpu_pmu = armv7_a8_pmu_init(); | ||
728 | break; | ||
729 | case 0xC090: /* Cortex-A9 */ | ||
730 | cpu_pmu = armv7_a9_pmu_init(); | ||
731 | break; | ||
732 | case 0xC050: /* Cortex-A5 */ | ||
733 | cpu_pmu = armv7_a5_pmu_init(); | ||
734 | break; | ||
735 | case 0xC0F0: /* Cortex-A15 */ | ||
736 | cpu_pmu = armv7_a15_pmu_init(); | ||
737 | break; | ||
738 | case 0xC070: /* Cortex-A7 */ | ||
739 | cpu_pmu = armv7_a7_pmu_init(); | ||
740 | break; | ||
741 | } | ||
742 | /* Intel CPUs [xscale]. */ | ||
743 | } else if (0x69 == implementor) { | ||
744 | part_number = (cpuid >> 13) & 0x7; | ||
745 | switch (part_number) { | ||
746 | case 1: | ||
747 | cpu_pmu = xscale1pmu_init(); | ||
748 | break; | ||
749 | case 2: | ||
750 | cpu_pmu = xscale2pmu_init(); | ||
751 | break; | ||
752 | } | ||
753 | } | ||
754 | |||
755 | if (cpu_pmu) { | ||
756 | pr_info("enabled with %s PMU driver, %d counters available\n", | ||
757 | cpu_pmu->name, cpu_pmu->num_events); | ||
758 | cpu_pmu_init(cpu_pmu); | ||
759 | register_cpu_notifier(&pmu_cpu_notifier); | ||
760 | armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW); | ||
761 | } else { | ||
762 | pr_info("no hardware support available\n"); | ||
763 | } | ||
764 | |||
765 | return 0; | ||
766 | } | ||
767 | early_initcall(init_hw_perf_events); | ||
768 | |||
769 | /* | 524 | /* |
770 | * Callchain handling code. | 525 | * Callchain handling code. |
771 | */ | 526 | */ |
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c new file mode 100644 index 000000000000..8d7d8d4de9d6 --- /dev/null +++ b/arch/arm/kernel/perf_event_cpu.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License version 2 as | ||
4 | * published by the Free Software Foundation. | ||
5 | * | ||
6 | * This program is distributed in the hope that it will be useful, | ||
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
9 | * GNU General Public License for more details. | ||
10 | * | ||
11 | * You should have received a copy of the GNU General Public License | ||
12 | * along with this program; if not, write to the Free Software | ||
13 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
14 | * | ||
15 | * Copyright (C) 2012 ARM Limited | ||
16 | * | ||
17 | * Author: Will Deacon <will.deacon@arm.com> | ||
18 | */ | ||
19 | #define pr_fmt(fmt) "CPU PMU: " fmt | ||
20 | |||
21 | #include <linux/bitmap.h> | ||
22 | #include <linux/export.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/of.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | |||
28 | #include <asm/cputype.h> | ||
29 | #include <asm/irq_regs.h> | ||
30 | #include <asm/pmu.h> | ||
31 | |||
32 | /* Set at runtime when we know what CPU type we are. */ | ||
33 | static struct arm_pmu *cpu_pmu; | ||
34 | |||
35 | static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events); | ||
36 | static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask); | ||
37 | static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); | ||
38 | |||
39 | /* | ||
40 | * Despite the names, these two functions are CPU-specific and are used | ||
41 | * by the OProfile/perf code. | ||
42 | */ | ||
43 | const char *perf_pmu_name(void) | ||
44 | { | ||
45 | if (!cpu_pmu) | ||
46 | return NULL; | ||
47 | |||
48 | return cpu_pmu->pmu.name; | ||
49 | } | ||
50 | EXPORT_SYMBOL_GPL(perf_pmu_name); | ||
51 | |||
52 | int perf_num_counters(void) | ||
53 | { | ||
54 | int max_events = 0; | ||
55 | |||
56 | if (cpu_pmu != NULL) | ||
57 | max_events = cpu_pmu->num_events; | ||
58 | |||
59 | return max_events; | ||
60 | } | ||
61 | EXPORT_SYMBOL_GPL(perf_num_counters); | ||
62 | |||
63 | /* Include the PMU-specific implementations. */ | ||
64 | #include "perf_event_xscale.c" | ||
65 | #include "perf_event_v6.c" | ||
66 | #include "perf_event_v7.c" | ||
67 | |||
68 | static struct pmu_hw_events *cpu_pmu_get_cpu_events(void) | ||
69 | { | ||
70 | return &__get_cpu_var(cpu_hw_events); | ||
71 | } | ||
72 | |||
73 | static void cpu_pmu_free_irq(void) | ||
74 | { | ||
75 | int i, irq, irqs; | ||
76 | struct platform_device *pmu_device = cpu_pmu->plat_device; | ||
77 | |||
78 | irqs = min(pmu_device->num_resources, num_possible_cpus()); | ||
79 | |||
80 | for (i = 0; i < irqs; ++i) { | ||
81 | if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs)) | ||
82 | continue; | ||
83 | irq = platform_get_irq(pmu_device, i); | ||
84 | if (irq >= 0) | ||
85 | free_irq(irq, cpu_pmu); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | static int cpu_pmu_request_irq(irq_handler_t handler) | ||
90 | { | ||
91 | int i, err, irq, irqs; | ||
92 | struct platform_device *pmu_device = cpu_pmu->plat_device; | ||
93 | |||
94 | if (!pmu_device) | ||
95 | return -ENODEV; | ||
96 | |||
97 | irqs = min(pmu_device->num_resources, num_possible_cpus()); | ||
98 | if (irqs < 1) { | ||
99 | pr_err("no irqs for PMUs defined\n"); | ||
100 | return -ENODEV; | ||
101 | } | ||
102 | |||
103 | for (i = 0; i < irqs; ++i) { | ||
104 | err = 0; | ||
105 | irq = platform_get_irq(pmu_device, i); | ||
106 | if (irq < 0) | ||
107 | continue; | ||
108 | |||
109 | /* | ||
110 | * If we have a single PMU interrupt that we can't shift, | ||
111 | * assume that we're running on a uniprocessor machine and | ||
112 | * continue. Otherwise, continue without this interrupt. | ||
113 | */ | ||
114 | if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) { | ||
115 | pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", | ||
116 | irq, i); | ||
117 | continue; | ||
118 | } | ||
119 | |||
120 | err = request_irq(irq, handler, IRQF_NOBALANCING, "arm-pmu", | ||
121 | cpu_pmu); | ||
122 | if (err) { | ||
123 | pr_err("unable to request IRQ%d for ARM PMU counters\n", | ||
124 | irq); | ||
125 | return err; | ||
126 | } | ||
127 | |||
128 | cpumask_set_cpu(i, &cpu_pmu->active_irqs); | ||
129 | } | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu) | ||
135 | { | ||
136 | int cpu; | ||
137 | for_each_possible_cpu(cpu) { | ||
138 | struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu); | ||
139 | events->events = per_cpu(hw_events, cpu); | ||
140 | events->used_mask = per_cpu(used_mask, cpu); | ||
141 | raw_spin_lock_init(&events->pmu_lock); | ||
142 | } | ||
143 | |||
144 | cpu_pmu->get_hw_events = cpu_pmu_get_cpu_events; | ||
145 | cpu_pmu->request_irq = cpu_pmu_request_irq; | ||
146 | cpu_pmu->free_irq = cpu_pmu_free_irq; | ||
147 | |||
148 | /* Ensure the PMU has sane values out of reset. */ | ||
149 | if (cpu_pmu && cpu_pmu->reset) | ||
150 | on_each_cpu(cpu_pmu->reset, NULL, 1); | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * PMU hardware loses all context when a CPU goes offline. | ||
155 | * When a CPU is hotplugged back in, since some hardware registers are | ||
156 | * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading | ||
157 | * junk values out of them. | ||
158 | */ | ||
159 | static int __cpuinit cpu_pmu_notify(struct notifier_block *b, | ||
160 | unsigned long action, void *hcpu) | ||
161 | { | ||
162 | if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) | ||
163 | return NOTIFY_DONE; | ||
164 | |||
165 | if (cpu_pmu && cpu_pmu->reset) | ||
166 | cpu_pmu->reset(NULL); | ||
167 | |||
168 | return NOTIFY_OK; | ||
169 | } | ||
170 | |||
171 | static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = { | ||
172 | .notifier_call = cpu_pmu_notify, | ||
173 | }; | ||
174 | |||
175 | /* | ||
176 | * PMU platform driver and devicetree bindings. | ||
177 | */ | ||
178 | static struct of_device_id __devinitdata cpu_pmu_of_device_ids[] = { | ||
179 | {.compatible = "arm,cortex-a15-pmu", .data = armv7_a15_pmu_init}, | ||
180 | {.compatible = "arm,cortex-a9-pmu", .data = armv7_a9_pmu_init}, | ||
181 | {.compatible = "arm,cortex-a8-pmu", .data = armv7_a8_pmu_init}, | ||
182 | {.compatible = "arm,cortex-a7-pmu", .data = armv7_a7_pmu_init}, | ||
183 | {.compatible = "arm,cortex-a5-pmu", .data = armv7_a5_pmu_init}, | ||
184 | {.compatible = "arm,arm11mpcore-pmu", .data = armv6mpcore_pmu_init}, | ||
185 | {.compatible = "arm,arm1176-pmu", .data = armv6pmu_init}, | ||
186 | {.compatible = "arm,arm1136-pmu", .data = armv6pmu_init}, | ||
187 | {}, | ||
188 | }; | ||
189 | |||
190 | static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = { | ||
191 | {.name = "arm-pmu"}, | ||
192 | {}, | ||
193 | }; | ||
194 | |||
195 | /* | ||
196 | * CPU PMU identification and probing. | ||
197 | */ | ||
198 | static struct arm_pmu *__devinit probe_current_pmu(void) | ||
199 | { | ||
200 | struct arm_pmu *pmu = NULL; | ||
201 | int cpu = get_cpu(); | ||
202 | unsigned long cpuid = read_cpuid_id(); | ||
203 | unsigned long implementor = (cpuid & 0xFF000000) >> 24; | ||
204 | unsigned long part_number = (cpuid & 0xFFF0); | ||
205 | |||
206 | pr_info("probing PMU on CPU %d\n", cpu); | ||
207 | |||
208 | /* ARM Ltd CPUs. */ | ||
209 | if (0x41 == implementor) { | ||
210 | switch (part_number) { | ||
211 | case 0xB360: /* ARM1136 */ | ||
212 | case 0xB560: /* ARM1156 */ | ||
213 | case 0xB760: /* ARM1176 */ | ||
214 | pmu = armv6pmu_init(); | ||
215 | break; | ||
216 | case 0xB020: /* ARM11mpcore */ | ||
217 | pmu = armv6mpcore_pmu_init(); | ||
218 | break; | ||
219 | case 0xC080: /* Cortex-A8 */ | ||
220 | pmu = armv7_a8_pmu_init(); | ||
221 | break; | ||
222 | case 0xC090: /* Cortex-A9 */ | ||
223 | pmu = armv7_a9_pmu_init(); | ||
224 | break; | ||
225 | case 0xC050: /* Cortex-A5 */ | ||
226 | pmu = armv7_a5_pmu_init(); | ||
227 | break; | ||
228 | case 0xC0F0: /* Cortex-A15 */ | ||
229 | pmu = armv7_a15_pmu_init(); | ||
230 | break; | ||
231 | case 0xC070: /* Cortex-A7 */ | ||
232 | pmu = armv7_a7_pmu_init(); | ||
233 | break; | ||
234 | } | ||
235 | /* Intel CPUs [xscale]. */ | ||
236 | } else if (0x69 == implementor) { | ||
237 | part_number = (cpuid >> 13) & 0x7; | ||
238 | switch (part_number) { | ||
239 | case 1: | ||
240 | pmu = xscale1pmu_init(); | ||
241 | break; | ||
242 | case 2: | ||
243 | pmu = xscale2pmu_init(); | ||
244 | break; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | put_cpu(); | ||
249 | return pmu; | ||
250 | } | ||
251 | |||
252 | static int __devinit cpu_pmu_device_probe(struct platform_device *pdev) | ||
253 | { | ||
254 | const struct of_device_id *of_id; | ||
255 | struct arm_pmu *(*init_fn)(void); | ||
256 | struct device_node *node = pdev->dev.of_node; | ||
257 | |||
258 | if (cpu_pmu) { | ||
259 | pr_info("attempt to register multiple PMU devices!"); | ||
260 | return -ENOSPC; | ||
261 | } | ||
262 | |||
263 | if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) { | ||
264 | init_fn = of_id->data; | ||
265 | cpu_pmu = init_fn(); | ||
266 | } else { | ||
267 | cpu_pmu = probe_current_pmu(); | ||
268 | } | ||
269 | |||
270 | if (!cpu_pmu) | ||
271 | return -ENODEV; | ||
272 | |||
273 | cpu_pmu->plat_device = pdev; | ||
274 | cpu_pmu_init(cpu_pmu); | ||
275 | register_cpu_notifier(&cpu_pmu_hotplug_notifier); | ||
276 | armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static struct platform_driver cpu_pmu_driver = { | ||
282 | .driver = { | ||
283 | .name = "arm-pmu", | ||
284 | .pm = &armpmu_dev_pm_ops, | ||
285 | .of_match_table = cpu_pmu_of_device_ids, | ||
286 | }, | ||
287 | .probe = cpu_pmu_device_probe, | ||
288 | .id_table = cpu_pmu_plat_device_ids, | ||
289 | }; | ||
290 | |||
291 | static int __init register_pmu_driver(void) | ||
292 | { | ||
293 | return platform_driver_register(&cpu_pmu_driver); | ||
294 | } | ||
295 | device_initcall(register_pmu_driver); | ||
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index c90fcb2b6967..6ccc07971745 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c | |||
@@ -645,7 +645,7 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc, | |||
645 | 645 | ||
646 | static int armv6_map_event(struct perf_event *event) | 646 | static int armv6_map_event(struct perf_event *event) |
647 | { | 647 | { |
648 | return map_cpu_event(event, &armv6_perf_map, | 648 | return armpmu_map_event(event, &armv6_perf_map, |
649 | &armv6_perf_cache_map, 0xFF); | 649 | &armv6_perf_cache_map, 0xFF); |
650 | } | 650 | } |
651 | 651 | ||
@@ -664,7 +664,7 @@ static struct arm_pmu armv6pmu = { | |||
664 | .max_period = (1LLU << 32) - 1, | 664 | .max_period = (1LLU << 32) - 1, |
665 | }; | 665 | }; |
666 | 666 | ||
667 | static struct arm_pmu *__init armv6pmu_init(void) | 667 | static struct arm_pmu *__devinit armv6pmu_init(void) |
668 | { | 668 | { |
669 | return &armv6pmu; | 669 | return &armv6pmu; |
670 | } | 670 | } |
@@ -679,7 +679,7 @@ static struct arm_pmu *__init armv6pmu_init(void) | |||
679 | 679 | ||
680 | static int armv6mpcore_map_event(struct perf_event *event) | 680 | static int armv6mpcore_map_event(struct perf_event *event) |
681 | { | 681 | { |
682 | return map_cpu_event(event, &armv6mpcore_perf_map, | 682 | return armpmu_map_event(event, &armv6mpcore_perf_map, |
683 | &armv6mpcore_perf_cache_map, 0xFF); | 683 | &armv6mpcore_perf_cache_map, 0xFF); |
684 | } | 684 | } |
685 | 685 | ||
@@ -698,17 +698,17 @@ static struct arm_pmu armv6mpcore_pmu = { | |||
698 | .max_period = (1LLU << 32) - 1, | 698 | .max_period = (1LLU << 32) - 1, |
699 | }; | 699 | }; |
700 | 700 | ||
701 | static struct arm_pmu *__init armv6mpcore_pmu_init(void) | 701 | static struct arm_pmu *__devinit armv6mpcore_pmu_init(void) |
702 | { | 702 | { |
703 | return &armv6mpcore_pmu; | 703 | return &armv6mpcore_pmu; |
704 | } | 704 | } |
705 | #else | 705 | #else |
706 | static struct arm_pmu *__init armv6pmu_init(void) | 706 | static struct arm_pmu *__devinit armv6pmu_init(void) |
707 | { | 707 | { |
708 | return NULL; | 708 | return NULL; |
709 | } | 709 | } |
710 | 710 | ||
711 | static struct arm_pmu *__init armv6mpcore_pmu_init(void) | 711 | static struct arm_pmu *__devinit armv6mpcore_pmu_init(void) |
712 | { | 712 | { |
713 | return NULL; | 713 | return NULL; |
714 | } | 714 | } |
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index f04070bd2183..bd4b090ebcfd 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c | |||
@@ -1204,31 +1204,31 @@ static void armv7pmu_reset(void *info) | |||
1204 | 1204 | ||
1205 | static int armv7_a8_map_event(struct perf_event *event) | 1205 | static int armv7_a8_map_event(struct perf_event *event) |
1206 | { | 1206 | { |
1207 | return map_cpu_event(event, &armv7_a8_perf_map, | 1207 | return armpmu_map_event(event, &armv7_a8_perf_map, |
1208 | &armv7_a8_perf_cache_map, 0xFF); | 1208 | &armv7_a8_perf_cache_map, 0xFF); |
1209 | } | 1209 | } |
1210 | 1210 | ||
1211 | static int armv7_a9_map_event(struct perf_event *event) | 1211 | static int armv7_a9_map_event(struct perf_event *event) |
1212 | { | 1212 | { |
1213 | return map_cpu_event(event, &armv7_a9_perf_map, | 1213 | return armpmu_map_event(event, &armv7_a9_perf_map, |
1214 | &armv7_a9_perf_cache_map, 0xFF); | 1214 | &armv7_a9_perf_cache_map, 0xFF); |
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | static int armv7_a5_map_event(struct perf_event *event) | 1217 | static int armv7_a5_map_event(struct perf_event *event) |
1218 | { | 1218 | { |
1219 | return map_cpu_event(event, &armv7_a5_perf_map, | 1219 | return armpmu_map_event(event, &armv7_a5_perf_map, |
1220 | &armv7_a5_perf_cache_map, 0xFF); | 1220 | &armv7_a5_perf_cache_map, 0xFF); |
1221 | } | 1221 | } |
1222 | 1222 | ||
1223 | static int armv7_a15_map_event(struct perf_event *event) | 1223 | static int armv7_a15_map_event(struct perf_event *event) |
1224 | { | 1224 | { |
1225 | return map_cpu_event(event, &armv7_a15_perf_map, | 1225 | return armpmu_map_event(event, &armv7_a15_perf_map, |
1226 | &armv7_a15_perf_cache_map, 0xFF); | 1226 | &armv7_a15_perf_cache_map, 0xFF); |
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | static int armv7_a7_map_event(struct perf_event *event) | 1229 | static int armv7_a7_map_event(struct perf_event *event) |
1230 | { | 1230 | { |
1231 | return map_cpu_event(event, &armv7_a7_perf_map, | 1231 | return armpmu_map_event(event, &armv7_a7_perf_map, |
1232 | &armv7_a7_perf_cache_map, 0xFF); | 1232 | &armv7_a7_perf_cache_map, 0xFF); |
1233 | } | 1233 | } |
1234 | 1234 | ||
@@ -1245,7 +1245,7 @@ static struct arm_pmu armv7pmu = { | |||
1245 | .max_period = (1LLU << 32) - 1, | 1245 | .max_period = (1LLU << 32) - 1, |
1246 | }; | 1246 | }; |
1247 | 1247 | ||
1248 | static u32 __init armv7_read_num_pmnc_events(void) | 1248 | static u32 __devinit armv7_read_num_pmnc_events(void) |
1249 | { | 1249 | { |
1250 | u32 nb_cnt; | 1250 | u32 nb_cnt; |
1251 | 1251 | ||
@@ -1256,7 +1256,7 @@ static u32 __init armv7_read_num_pmnc_events(void) | |||
1256 | return nb_cnt + 1; | 1256 | return nb_cnt + 1; |
1257 | } | 1257 | } |
1258 | 1258 | ||
1259 | static struct arm_pmu *__init armv7_a8_pmu_init(void) | 1259 | static struct arm_pmu *__devinit armv7_a8_pmu_init(void) |
1260 | { | 1260 | { |
1261 | armv7pmu.name = "ARMv7 Cortex-A8"; | 1261 | armv7pmu.name = "ARMv7 Cortex-A8"; |
1262 | armv7pmu.map_event = armv7_a8_map_event; | 1262 | armv7pmu.map_event = armv7_a8_map_event; |
@@ -1264,7 +1264,7 @@ static struct arm_pmu *__init armv7_a8_pmu_init(void) | |||
1264 | return &armv7pmu; | 1264 | return &armv7pmu; |
1265 | } | 1265 | } |
1266 | 1266 | ||
1267 | static struct arm_pmu *__init armv7_a9_pmu_init(void) | 1267 | static struct arm_pmu *__devinit armv7_a9_pmu_init(void) |
1268 | { | 1268 | { |
1269 | armv7pmu.name = "ARMv7 Cortex-A9"; | 1269 | armv7pmu.name = "ARMv7 Cortex-A9"; |
1270 | armv7pmu.map_event = armv7_a9_map_event; | 1270 | armv7pmu.map_event = armv7_a9_map_event; |
@@ -1272,7 +1272,7 @@ static struct arm_pmu *__init armv7_a9_pmu_init(void) | |||
1272 | return &armv7pmu; | 1272 | return &armv7pmu; |
1273 | } | 1273 | } |
1274 | 1274 | ||
1275 | static struct arm_pmu *__init armv7_a5_pmu_init(void) | 1275 | static struct arm_pmu *__devinit armv7_a5_pmu_init(void) |
1276 | { | 1276 | { |
1277 | armv7pmu.name = "ARMv7 Cortex-A5"; | 1277 | armv7pmu.name = "ARMv7 Cortex-A5"; |
1278 | armv7pmu.map_event = armv7_a5_map_event; | 1278 | armv7pmu.map_event = armv7_a5_map_event; |
@@ -1280,7 +1280,7 @@ static struct arm_pmu *__init armv7_a5_pmu_init(void) | |||
1280 | return &armv7pmu; | 1280 | return &armv7pmu; |
1281 | } | 1281 | } |
1282 | 1282 | ||
1283 | static struct arm_pmu *__init armv7_a15_pmu_init(void) | 1283 | static struct arm_pmu *__devinit armv7_a15_pmu_init(void) |
1284 | { | 1284 | { |
1285 | armv7pmu.name = "ARMv7 Cortex-A15"; | 1285 | armv7pmu.name = "ARMv7 Cortex-A15"; |
1286 | armv7pmu.map_event = armv7_a15_map_event; | 1286 | armv7pmu.map_event = armv7_a15_map_event; |
@@ -1289,7 +1289,7 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void) | |||
1289 | return &armv7pmu; | 1289 | return &armv7pmu; |
1290 | } | 1290 | } |
1291 | 1291 | ||
1292 | static struct arm_pmu *__init armv7_a7_pmu_init(void) | 1292 | static struct arm_pmu *__devinit armv7_a7_pmu_init(void) |
1293 | { | 1293 | { |
1294 | armv7pmu.name = "ARMv7 Cortex-A7"; | 1294 | armv7pmu.name = "ARMv7 Cortex-A7"; |
1295 | armv7pmu.map_event = armv7_a7_map_event; | 1295 | armv7pmu.map_event = armv7_a7_map_event; |
@@ -1298,27 +1298,27 @@ static struct arm_pmu *__init armv7_a7_pmu_init(void) | |||
1298 | return &armv7pmu; | 1298 | return &armv7pmu; |
1299 | } | 1299 | } |
1300 | #else | 1300 | #else |
1301 | static struct arm_pmu *__init armv7_a8_pmu_init(void) | 1301 | static struct arm_pmu *__devinit armv7_a8_pmu_init(void) |
1302 | { | 1302 | { |
1303 | return NULL; | 1303 | return NULL; |
1304 | } | 1304 | } |
1305 | 1305 | ||
1306 | static struct arm_pmu *__init armv7_a9_pmu_init(void) | 1306 | static struct arm_pmu *__devinit armv7_a9_pmu_init(void) |
1307 | { | 1307 | { |
1308 | return NULL; | 1308 | return NULL; |
1309 | } | 1309 | } |
1310 | 1310 | ||
1311 | static struct arm_pmu *__init armv7_a5_pmu_init(void) | 1311 | static struct arm_pmu *__devinit armv7_a5_pmu_init(void) |
1312 | { | 1312 | { |
1313 | return NULL; | 1313 | return NULL; |
1314 | } | 1314 | } |
1315 | 1315 | ||
1316 | static struct arm_pmu *__init armv7_a15_pmu_init(void) | 1316 | static struct arm_pmu *__devinit armv7_a15_pmu_init(void) |
1317 | { | 1317 | { |
1318 | return NULL; | 1318 | return NULL; |
1319 | } | 1319 | } |
1320 | 1320 | ||
1321 | static struct arm_pmu *__init armv7_a7_pmu_init(void) | 1321 | static struct arm_pmu *__devinit armv7_a7_pmu_init(void) |
1322 | { | 1322 | { |
1323 | return NULL; | 1323 | return NULL; |
1324 | } | 1324 | } |
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index f759fe0bab63..426e19f380a2 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c | |||
@@ -430,7 +430,7 @@ xscale1pmu_write_counter(int counter, u32 val) | |||
430 | 430 | ||
431 | static int xscale_map_event(struct perf_event *event) | 431 | static int xscale_map_event(struct perf_event *event) |
432 | { | 432 | { |
433 | return map_cpu_event(event, &xscale_perf_map, | 433 | return armpmu_map_event(event, &xscale_perf_map, |
434 | &xscale_perf_cache_map, 0xFF); | 434 | &xscale_perf_cache_map, 0xFF); |
435 | } | 435 | } |
436 | 436 | ||
@@ -449,7 +449,7 @@ static struct arm_pmu xscale1pmu = { | |||
449 | .max_period = (1LLU << 32) - 1, | 449 | .max_period = (1LLU << 32) - 1, |
450 | }; | 450 | }; |
451 | 451 | ||
452 | static struct arm_pmu *__init xscale1pmu_init(void) | 452 | static struct arm_pmu *__devinit xscale1pmu_init(void) |
453 | { | 453 | { |
454 | return &xscale1pmu; | 454 | return &xscale1pmu; |
455 | } | 455 | } |
@@ -816,17 +816,17 @@ static struct arm_pmu xscale2pmu = { | |||
816 | .max_period = (1LLU << 32) - 1, | 816 | .max_period = (1LLU << 32) - 1, |
817 | }; | 817 | }; |
818 | 818 | ||
819 | static struct arm_pmu *__init xscale2pmu_init(void) | 819 | static struct arm_pmu *__devinit xscale2pmu_init(void) |
820 | { | 820 | { |
821 | return &xscale2pmu; | 821 | return &xscale2pmu; |
822 | } | 822 | } |
823 | #else | 823 | #else |
824 | static struct arm_pmu *__init xscale1pmu_init(void) | 824 | static struct arm_pmu *__devinit xscale1pmu_init(void) |
825 | { | 825 | { |
826 | return NULL; | 826 | return NULL; |
827 | } | 827 | } |
828 | 828 | ||
829 | static struct arm_pmu *__init xscale2pmu_init(void) | 829 | static struct arm_pmu *__devinit xscale2pmu_init(void) |
830 | { | 830 | { |
831 | return NULL; | 831 | return NULL; |
832 | } | 832 | } |
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c deleted file mode 100644 index 2334bf8a650a..000000000000 --- a/arch/arm/kernel/pmu.c +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/pmu.c | ||
3 | * | ||
4 | * Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles | ||
5 | * Copyright (C) 2010 ARM Ltd, Will Deacon | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/err.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | |||
17 | #include <asm/pmu.h> | ||
18 | |||
19 | /* | ||
20 | * PMU locking to ensure mutual exclusion between different subsystems. | ||
21 | */ | ||
22 | static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)]; | ||
23 | |||
24 | int | ||
25 | reserve_pmu(enum arm_pmu_type type) | ||
26 | { | ||
27 | return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0; | ||
28 | } | ||
29 | EXPORT_SYMBOL_GPL(reserve_pmu); | ||
30 | |||
31 | void | ||
32 | release_pmu(enum arm_pmu_type type) | ||
33 | { | ||
34 | clear_bit_unlock(type, pmu_lock); | ||
35 | } | ||
36 | EXPORT_SYMBOL_GPL(release_pmu); | ||
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c index 45c97b1ee9b1..76e795323569 100644 --- a/arch/arm/mach-bcmring/arch.c +++ b/arch/arm/mach-bcmring/arch.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <asm/setup.h> | 29 | #include <asm/setup.h> |
30 | #include <asm/mach-types.h> | 30 | #include <asm/mach-types.h> |
31 | #include <asm/mach/time.h> | 31 | #include <asm/mach/time.h> |
32 | #include <asm/pmu.h> | ||
33 | 32 | ||
34 | #include <asm/mach/arch.h> | 33 | #include <asm/mach/arch.h> |
35 | #include <mach/dma.h> | 34 | #include <mach/dma.h> |
@@ -116,7 +115,7 @@ static struct resource pmu_resource = { | |||
116 | 115 | ||
117 | static struct platform_device pmu_device = { | 116 | static struct platform_device pmu_device = { |
118 | .name = "arm-pmu", | 117 | .name = "arm-pmu", |
119 | .id = ARM_PMU_DEVICE_CPU, | 118 | .id = -1, |
120 | .resource = &pmu_resource, | 119 | .resource = &pmu_resource, |
121 | .num_resources = 1, | 120 | .num_resources = 1, |
122 | }; | 121 | }; |
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index c00c68961bb8..02b9478b786f 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <mach/irqs.h> | 23 | #include <mach/irqs.h> |
24 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
25 | #include <asm/mach/map.h> | 25 | #include <asm/mach/map.h> |
26 | #include <asm/pmu.h> | ||
27 | 26 | ||
28 | #include "iomap.h" | 27 | #include "iomap.h" |
29 | #include <plat/board.h> | 28 | #include <plat/board.h> |
@@ -448,7 +447,7 @@ static struct resource omap3_pmu_resource = { | |||
448 | 447 | ||
449 | static struct platform_device omap_pmu_device = { | 448 | static struct platform_device omap_pmu_device = { |
450 | .name = "arm-pmu", | 449 | .name = "arm-pmu", |
451 | .id = ARM_PMU_DEVICE_CPU, | 450 | .id = -1, |
452 | .num_resources = 1, | 451 | .num_resources = 1, |
453 | }; | 452 | }; |
454 | 453 | ||
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 166eee5b8a70..c1f3b1279d97 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <linux/spi/pxa2xx_spi.h> | 6 | #include <linux/spi/pxa2xx_spi.h> |
7 | #include <linux/i2c/pxa-i2c.h> | 7 | #include <linux/i2c/pxa-i2c.h> |
8 | 8 | ||
9 | #include <asm/pmu.h> | ||
10 | #include <mach/udc.h> | 9 | #include <mach/udc.h> |
11 | #include <mach/pxa3xx-u2d.h> | 10 | #include <mach/pxa3xx-u2d.h> |
12 | #include <mach/pxafb.h> | 11 | #include <mach/pxafb.h> |
@@ -42,7 +41,7 @@ static struct resource pxa_resource_pmu = { | |||
42 | 41 | ||
43 | struct platform_device pxa_device_pmu = { | 42 | struct platform_device pxa_device_pmu = { |
44 | .name = "arm-pmu", | 43 | .name = "arm-pmu", |
45 | .id = ARM_PMU_DEVICE_CPU, | 44 | .id = -1, |
46 | .resource = &pxa_resource_pmu, | 45 | .resource = &pxa_resource_pmu, |
47 | .num_resources = 1, | 46 | .num_resources = 1, |
48 | }; | 47 | }; |
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index baf382c5e776..d7a6e9cebba4 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
33 | #include <asm/leds.h> | 33 | #include <asm/leds.h> |
34 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
35 | #include <asm/pmu.h> | ||
36 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
37 | #include <asm/hardware/gic.h> | 36 | #include <asm/hardware/gic.h> |
38 | #include <asm/hardware/cache-l2x0.h> | 37 | #include <asm/hardware/cache-l2x0.h> |
@@ -297,7 +296,7 @@ static struct resource pmu_resources[] = { | |||
297 | 296 | ||
298 | static struct platform_device pmu_device = { | 297 | static struct platform_device pmu_device = { |
299 | .name = "arm-pmu", | 298 | .name = "arm-pmu", |
300 | .id = ARM_PMU_DEVICE_CPU, | 299 | .id = -1, |
301 | .num_resources = ARRAY_SIZE(pmu_resources), | 300 | .num_resources = ARRAY_SIZE(pmu_resources), |
302 | .resource = pmu_resources, | 301 | .resource = pmu_resources, |
303 | }; | 302 | }; |
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index b1d7cafa1a6d..361f898884c8 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <asm/irq.h> | 34 | #include <asm/irq.h> |
35 | #include <asm/leds.h> | 35 | #include <asm/leds.h> |
36 | #include <asm/mach-types.h> | 36 | #include <asm/mach-types.h> |
37 | #include <asm/pmu.h> | ||
38 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
39 | #include <asm/hardware/gic.h> | 38 | #include <asm/hardware/gic.h> |
40 | #include <asm/hardware/cache-l2x0.h> | 39 | #include <asm/hardware/cache-l2x0.h> |
@@ -280,7 +279,7 @@ static struct resource pmu_resource = { | |||
280 | 279 | ||
281 | static struct platform_device pmu_device = { | 280 | static struct platform_device pmu_device = { |
282 | .name = "arm-pmu", | 281 | .name = "arm-pmu", |
283 | .id = ARM_PMU_DEVICE_CPU, | 282 | .id = -1, |
284 | .num_resources = 1, | 283 | .num_resources = 1, |
285 | .resource = &pmu_resource, | 284 | .resource = &pmu_resource, |
286 | }; | 285 | }; |
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index a98c536e3327..c56bc8d4d11b 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
33 | #include <asm/leds.h> | 33 | #include <asm/leds.h> |
34 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
35 | #include <asm/pmu.h> | ||
36 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
37 | #include <asm/hardware/gic.h> | 36 | #include <asm/hardware/gic.h> |
38 | #include <asm/hardware/cache-l2x0.h> | 37 | #include <asm/hardware/cache-l2x0.h> |
@@ -263,7 +262,7 @@ static struct resource pmu_resources[] = { | |||
263 | 262 | ||
264 | static struct platform_device pmu_device = { | 263 | static struct platform_device pmu_device = { |
265 | .name = "arm-pmu", | 264 | .name = "arm-pmu", |
266 | .id = ARM_PMU_DEVICE_CPU, | 265 | .id = -1, |
267 | .num_resources = ARRAY_SIZE(pmu_resources), | 266 | .num_resources = ARRAY_SIZE(pmu_resources), |
268 | .resource = pmu_resources, | 267 | .resource = pmu_resources, |
269 | }; | 268 | }; |
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 59650174e6ed..040937582453 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <asm/irq.h> | 31 | #include <asm/irq.h> |
32 | #include <asm/leds.h> | 32 | #include <asm/leds.h> |
33 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
34 | #include <asm/pmu.h> | ||
35 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
36 | #include <asm/hardware/gic.h> | 35 | #include <asm/hardware/gic.h> |
37 | 36 | ||
@@ -241,7 +240,7 @@ static struct resource pmu_resource = { | |||
241 | 240 | ||
242 | static struct platform_device pmu_device = { | 241 | static struct platform_device pmu_device = { |
243 | .name = "arm-pmu", | 242 | .name = "arm-pmu", |
244 | .id = ARM_PMU_DEVICE_CPU, | 243 | .id = -1, |
245 | .num_resources = 1, | 244 | .num_resources = 1, |
246 | .resource = &pmu_resource, | 245 | .resource = &pmu_resource, |
247 | }; | 246 | }; |
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 3f2f605624e9..97885dc11e8c 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
31 | #include <asm/leds.h> | 31 | #include <asm/leds.h> |
32 | #include <asm/mach-types.h> | 32 | #include <asm/mach-types.h> |
33 | #include <asm/pmu.h> | ||
34 | #include <asm/smp_twd.h> | 33 | #include <asm/smp_twd.h> |
35 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
36 | #include <asm/hardware/gic.h> | 35 | #include <asm/hardware/gic.h> |
@@ -280,7 +279,7 @@ static struct resource pmu_resources[] = { | |||
280 | 279 | ||
281 | static struct platform_device pmu_device = { | 280 | static struct platform_device pmu_device = { |
282 | .name = "arm-pmu", | 281 | .name = "arm-pmu", |
283 | .id = ARM_PMU_DEVICE_CPU, | 282 | .id = -1, |
284 | .num_resources = ARRAY_SIZE(pmu_resources), | 283 | .num_resources = ARRAY_SIZE(pmu_resources), |
285 | .resource = pmu_resources, | 284 | .resource = pmu_resources, |
286 | }; | 285 | }; |
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c index dae9aa68bb09..61446f30e397 100644 --- a/arch/arm/mach-shmobile/setup-emev2.c +++ b/arch/arm/mach-shmobile/setup-emev2.c | |||
@@ -356,6 +356,26 @@ static struct platform_device gio4_device = { | |||
356 | }, | 356 | }, |
357 | }; | 357 | }; |
358 | 358 | ||
359 | static struct resource pmu_resources[] = { | ||
360 | [0] = { | ||
361 | .start = 152, | ||
362 | .end = 152, | ||
363 | .flags = IORESOURCE_IRQ, | ||
364 | }, | ||
365 | [1] = { | ||
366 | .start = 153, | ||
367 | .end = 153, | ||
368 | .flags = IORESOURCE_IRQ, | ||
369 | }, | ||
370 | }; | ||
371 | |||
372 | static struct platform_device pmu_device = { | ||
373 | .name = "arm-pmu", | ||
374 | .id = -1, | ||
375 | .num_resources = ARRAY_SIZE(pmu_resources), | ||
376 | .resource = pmu_resources, | ||
377 | }; | ||
378 | |||
359 | static struct platform_device *emev2_early_devices[] __initdata = { | 379 | static struct platform_device *emev2_early_devices[] __initdata = { |
360 | &uart0_device, | 380 | &uart0_device, |
361 | &uart1_device, | 381 | &uart1_device, |
@@ -370,6 +390,7 @@ static struct platform_device *emev2_late_devices[] __initdata = { | |||
370 | &gio2_device, | 390 | &gio2_device, |
371 | &gio3_device, | 391 | &gio3_device, |
372 | &gio4_device, | 392 | &gio4_device, |
393 | &pmu_device, | ||
373 | }; | 394 | }; |
374 | 395 | ||
375 | void __init emev2_add_standard_devices(void) | 396 | void __init emev2_add_standard_devices(void) |
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index d230af656fc9..38ed2ddd3265 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c | |||
@@ -734,6 +734,26 @@ static struct platform_device mpdma0_device = { | |||
734 | }, | 734 | }, |
735 | }; | 735 | }; |
736 | 736 | ||
737 | static struct resource pmu_resources[] = { | ||
738 | [0] = { | ||
739 | .start = gic_spi(55), | ||
740 | .end = gic_spi(55), | ||
741 | .flags = IORESOURCE_IRQ, | ||
742 | }, | ||
743 | [1] = { | ||
744 | .start = gic_spi(56), | ||
745 | .end = gic_spi(56), | ||
746 | .flags = IORESOURCE_IRQ, | ||
747 | }, | ||
748 | }; | ||
749 | |||
750 | static struct platform_device pmu_device = { | ||
751 | .name = "arm-pmu", | ||
752 | .id = -1, | ||
753 | .num_resources = ARRAY_SIZE(pmu_resources), | ||
754 | .resource = pmu_resources, | ||
755 | }; | ||
756 | |||
737 | static struct platform_device *sh73a0_early_devices[] __initdata = { | 757 | static struct platform_device *sh73a0_early_devices[] __initdata = { |
738 | &scif0_device, | 758 | &scif0_device, |
739 | &scif1_device, | 759 | &scif1_device, |
@@ -757,6 +777,7 @@ static struct platform_device *sh73a0_late_devices[] __initdata = { | |||
757 | &i2c4_device, | 777 | &i2c4_device, |
758 | &dma0_device, | 778 | &dma0_device, |
759 | &mpdma0_device, | 779 | &mpdma0_device, |
780 | &pmu_device, | ||
760 | }; | 781 | }; |
761 | 782 | ||
762 | #define SRCR2 0xe61580b0 | 783 | #define SRCR2 0xe61580b0 |
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index c70e65ffa36b..61e9603744a7 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/fsl_devices.h> | 23 | #include <linux/fsl_devices.h> |
24 | #include <linux/serial_8250.h> | 24 | #include <linux/serial_8250.h> |
25 | #include <linux/i2c-tegra.h> | 25 | #include <linux/i2c-tegra.h> |
26 | #include <asm/pmu.h> | ||
27 | #include <mach/irqs.h> | 26 | #include <mach/irqs.h> |
28 | #include <mach/iomap.h> | 27 | #include <mach/iomap.h> |
29 | #include <mach/dma.h> | 28 | #include <mach/dma.h> |
@@ -516,7 +515,7 @@ static struct resource tegra_pmu_resources[] = { | |||
516 | 515 | ||
517 | struct platform_device tegra_pmu_device = { | 516 | struct platform_device tegra_pmu_device = { |
518 | .name = "arm-pmu", | 517 | .name = "arm-pmu", |
519 | .id = ARM_PMU_DEVICE_CPU, | 518 | .id = -1, |
520 | .num_resources = ARRAY_SIZE(tegra_pmu_resources), | 519 | .num_resources = ARRAY_SIZE(tegra_pmu_resources), |
521 | .resource = tegra_pmu_resources, | 520 | .resource = tegra_pmu_resources, |
522 | }; | 521 | }; |
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 2dd8593e72d0..8169f2c72d6c 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/mfd/abx500/ab8500.h> | 19 | #include <linux/mfd/abx500/ab8500.h> |
20 | 20 | ||
21 | #include <asm/mach/map.h> | 21 | #include <asm/mach/map.h> |
22 | #include <asm/pmu.h> | ||
23 | #include <plat/gpio-nomadik.h> | 22 | #include <plat/gpio-nomadik.h> |
24 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
25 | #include <mach/setup.h> | 24 | #include <mach/setup.h> |
@@ -122,7 +121,7 @@ struct arm_pmu_platdata db8500_pmu_platdata = { | |||
122 | 121 | ||
123 | static struct platform_device db8500_pmu_device = { | 122 | static struct platform_device db8500_pmu_device = { |
124 | .name = "arm-pmu", | 123 | .name = "arm-pmu", |
125 | .id = ARM_PMU_DEVICE_CPU, | 124 | .id = -1, |
126 | .num_resources = ARRAY_SIZE(db8500_pmu_resources), | 125 | .num_resources = ARRAY_SIZE(db8500_pmu_resources), |
127 | .resource = db8500_pmu_resources, | 126 | .resource = db8500_pmu_resources, |
128 | .dev.platform_data = &db8500_pmu_platdata, | 127 | .dev.platform_data = &db8500_pmu_platdata, |
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 61c492403b05..e4073a60a864 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <asm/hardware/arm_timer.h> | 13 | #include <asm/hardware/arm_timer.h> |
14 | #include <asm/hardware/cache-l2x0.h> | 14 | #include <asm/hardware/cache-l2x0.h> |
15 | #include <asm/hardware/gic.h> | 15 | #include <asm/hardware/gic.h> |
16 | #include <asm/pmu.h> | ||
17 | #include <asm/smp_scu.h> | 16 | #include <asm/smp_scu.h> |
18 | #include <asm/smp_twd.h> | 17 | #include <asm/smp_twd.h> |
19 | 18 | ||
@@ -144,7 +143,7 @@ static struct resource pmu_resources[] = { | |||
144 | 143 | ||
145 | static struct platform_device pmu_device = { | 144 | static struct platform_device pmu_device = { |
146 | .name = "arm-pmu", | 145 | .name = "arm-pmu", |
147 | .id = ARM_PMU_DEVICE_CPU, | 146 | .id = -1, |
148 | .num_resources = ARRAY_SIZE(pmu_resources), | 147 | .num_resources = ARRAY_SIZE(pmu_resources), |
149 | .resource = pmu_resources, | 148 | .resource = pmu_resources, |
150 | }; | 149 | }; |
diff --git a/arch/arm/plat-iop/pmu.c b/arch/arm/plat-iop/pmu.c index a2024b8685a1..ad9f9744a82d 100644 --- a/arch/arm/plat-iop/pmu.c +++ b/arch/arm/plat-iop/pmu.c | |||
@@ -9,7 +9,6 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
12 | #include <asm/pmu.h> | ||
13 | #include <mach/irqs.h> | 12 | #include <mach/irqs.h> |
14 | 13 | ||
15 | static struct resource pmu_resource = { | 14 | static struct resource pmu_resource = { |
@@ -26,7 +25,7 @@ static struct resource pmu_resource = { | |||
26 | 25 | ||
27 | static struct platform_device pmu_device = { | 26 | static struct platform_device pmu_device = { |
28 | .name = "arm-pmu", | 27 | .name = "arm-pmu", |
29 | .id = ARM_PMU_DEVICE_CPU, | 28 | .id = -1, |
30 | .resource = &pmu_resource, | 29 | .resource = &pmu_resource, |
31 | .num_resources = 1, | 30 | .num_resources = 1, |
32 | }; | 31 | }; |
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index fc49f3dabd76..6ff45d53362c 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <media/s5p_hdmi.h> | 35 | #include <media/s5p_hdmi.h> |
36 | 36 | ||
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #include <asm/pmu.h> | ||
39 | #include <asm/mach/arch.h> | 38 | #include <asm/mach/arch.h> |
40 | #include <asm/mach/map.h> | 39 | #include <asm/mach/map.h> |
41 | #include <asm/mach/irq.h> | 40 | #include <asm/mach/irq.h> |
@@ -1132,7 +1131,7 @@ static struct resource s5p_pmu_resource[] = { | |||
1132 | 1131 | ||
1133 | static struct platform_device s5p_device_pmu = { | 1132 | static struct platform_device s5p_device_pmu = { |
1134 | .name = "arm-pmu", | 1133 | .name = "arm-pmu", |
1135 | .id = ARM_PMU_DEVICE_CPU, | 1134 | .id = -1, |
1136 | .num_resources = ARRAY_SIZE(s5p_pmu_resource), | 1135 | .num_resources = ARRAY_SIZE(s5p_pmu_resource), |
1137 | .resource = s5p_pmu_resource, | 1136 | .resource = s5p_pmu_resource, |
1138 | }; | 1137 | }; |