]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/arm/kernel/pmu.c
arm: msm: add oprofile pmu support
[net-next-2.6.git] / arch / arm / kernel / pmu.c
CommitLineData
0f4f0672
JI
1/*
2 * linux/arch/arm/kernel/pmu.c
3 *
4 * Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/cpumask.h>
13#include <linux/err.h>
14#include <linux/interrupt.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17
18#include <asm/pmu.h>
19
20/*
21 * Define the IRQs for the system. We could use something like a platform
22 * device but that seems fairly heavyweight for this. Also, the performance
23 * counters can't be removed or hotplugged.
24 *
25 * Ordering is important: init_pmu() will use the ordering to set the affinity
26 * to the corresponding core. e.g. the first interrupt will go to cpu 0, the
27 * second goes to cpu 1 etc.
28 */
29static const int irqs[] = {
30#if defined(CONFIG_ARCH_OMAP2)
31 3,
32#elif defined(CONFIG_ARCH_BCMRING)
33 IRQ_PMUIRQ,
34#elif defined(CONFIG_MACH_REALVIEW_EB)
35 IRQ_EB11MP_PMU_CPU0,
36 IRQ_EB11MP_PMU_CPU1,
37 IRQ_EB11MP_PMU_CPU2,
38 IRQ_EB11MP_PMU_CPU3,
39#elif defined(CONFIG_ARCH_OMAP3)
40 INT_34XX_BENCH_MPU_EMUL,
41#elif defined(CONFIG_ARCH_IOP32X)
42 IRQ_IOP32X_CORE_PMU,
43#elif defined(CONFIG_ARCH_IOP33X)
44 IRQ_IOP33X_CORE_PMU,
45#elif defined(CONFIG_ARCH_PXA)
46 IRQ_PMU,
ee3c454b
DW
47#elif defined(CONFIG_ARCH_MSM_ARM11)
48 INT_ARM11_PMU,
0f4f0672
JI
49#endif
50};
51
52static const struct pmu_irqs pmu_irqs = {
53 .irqs = irqs,
54 .num_irqs = ARRAY_SIZE(irqs),
55};
56
57static volatile long pmu_lock;
58
59const struct pmu_irqs *
60reserve_pmu(void)
61{
62 return test_and_set_bit_lock(0, &pmu_lock) ? ERR_PTR(-EBUSY) :
63 &pmu_irqs;
64}
65EXPORT_SYMBOL_GPL(reserve_pmu);
66
67int
68release_pmu(const struct pmu_irqs *irqs)
69{
70 if (WARN_ON(irqs != &pmu_irqs))
71 return -EINVAL;
72 clear_bit_unlock(0, &pmu_lock);
73 return 0;
74}
75EXPORT_SYMBOL_GPL(release_pmu);
76
77static int
78set_irq_affinity(int irq,
79 unsigned int cpu)
80{
81#ifdef CONFIG_SMP
82 int err = irq_set_affinity(irq, cpumask_of(cpu));
83 if (err)
84 pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
85 irq, cpu);
86 return err;
87#else
88 return 0;
89#endif
90}
91
92int
93init_pmu(void)
94{
95 int i, err = 0;
96
97 for (i = 0; i < pmu_irqs.num_irqs; ++i) {
98 err = set_irq_affinity(pmu_irqs.irqs[i], i);
99 if (err)
100 break;
101 }
102
103 return err;
104}
105EXPORT_SYMBOL_GPL(init_pmu);