diff options
Diffstat (limited to 'arch/arm/include/asm/pmu.h')
| -rw-r--r-- | arch/arm/include/asm/pmu.h | 136 |
1 files changed, 86 insertions, 50 deletions
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 8ccea012722..ae1919be8f9 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -12,66 +12,102 @@ #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 +#include <linux/interrupt.h> +#include <linux/perf_event.h> -/** - * reserve_pmu() - reserve the hardware performance counters +/* + * struct arm_pmu_platdata - ARM PMU platform data * - * Reserve the hardware performance counters in the system for exclusive use. - * The platform_device for the system is returned on success, ERR_PTR() - * encoded error on failure. + * @handle_irq: an optional handler which will be called from the + * interrupt and passed the address of the low level handler, + * and can be used to implement any platform specific handling + * before or after calling it. + * @runtime_resume: an optional handler which will be called by the + * runtime PM framework following a call to pm_runtime_get(). + * Note that if pm_runtime_get() is called more than once in + * succession this handler will only be called once. + * @runtime_suspend: an optional handler which will be called by the + * runtime PM framework following a call to pm_runtime_put(). + * Note that if pm_runtime_get() is called more than once in + * succession this handler will only be called following the + * final call to pm_runtime_put() that actually disables the + * hardware. */ -extern struct platform_device * -reserve_pmu(enum arm_pmu_type device); +struct arm_pmu_platdata { + irqreturn_t (*handle_irq)(int irq, void *dev, + irq_handler_t pmu_handler); + int (*runtime_resume)(struct device *dev); + int (*runtime_suspend)(struct device *dev); +}; -/** - * 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 platform_device returned from reserve_pmu() must be passed as - * a cookie. - */ -extern int -release_pmu(struct platform_device *pdev); +#ifdef CONFIG_HW_PERF_EVENTS -/** - * init_pmu() - Initialise the PMU. - * - * Initialise the system ready for PMU enabling. This should typically set the - * IRQ affinity and nothing else. The users (oprofile/perf events etc) will do - * the actual hardware initialisation. - */ -extern int -init_pmu(enum arm_pmu_type device); +/* The events for a given PMU register set. */ +struct pmu_hw_events { + /* + * The events that are active on the PMU for the given index. + */ + struct perf_event **events; + + /* + * A 1 bit for an index indicates that the counter is being used for + * an event. A 0 means that the counter can be used. + */ + unsigned long *used_mask; + + /* + * Hardware lock to serialize accesses to PMU registers. Needed for the + * read/modify/write sequences. + */ + raw_spinlock_t pmu_lock; +}; + +struct arm_pmu { + struct pmu pmu; + cpumask_t active_irqs; + char *name; + irqreturn_t (*handle_irq)(int irq_num, void *dev); + void (*enable)(struct perf_event *event); + void (*disable)(struct perf_event *event); + int (*get_event_idx)(struct pmu_hw_events *hw_events, + struct perf_event *event); + void (*clear_event_idx)(struct pmu_hw_events *hw_events, + struct perf_event *event); + int (*set_event_filter)(struct hw_perf_event *evt, + struct perf_event_attr *attr); + u32 (*read_counter)(struct perf_event *event); + void (*write_counter)(struct perf_event *event, u32 val); + void (*start)(struct arm_pmu *); + void (*stop)(struct arm_pmu *); + void (*reset)(void *); + int (*request_irq)(struct arm_pmu *, irq_handler_t handler); + void (*free_irq)(struct arm_pmu *); + int (*map_event)(struct perf_event *event); + int num_events; + atomic_t active_events; + struct mutex reserve_mutex; + u64 max_period; + struct platform_device *plat_device; + struct pmu_hw_events *(*get_hw_events)(void); +}; + +#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) -#else /* CONFIG_CPU_HAS_PMU */ +extern const struct dev_pm_ops armpmu_dev_pm_ops; -#include <linux/err.h> +int armpmu_register(struct arm_pmu *armpmu, int type); -static inline struct platform_device * -reserve_pmu(enum arm_pmu_type device) -{ - return ERR_PTR(-ENODEV); -} +u64 armpmu_event_update(struct perf_event *event); -static inline int -release_pmu(struct platform_device *pdev) -{ - return -ENODEV; -} +int armpmu_event_set_period(struct perf_event *event); -static inline int -init_pmu(enum arm_pmu_type device) -{ - return -ENODEV; -} +int armpmu_map_event(struct perf_event *event, + const unsigned (*event_map)[PERF_COUNT_HW_MAX], + const unsigned (*cache_map)[PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX], + u32 raw_event_mask); -#endif /* CONFIG_CPU_HAS_PMU */ +#endif /* CONFIG_HW_PERF_EVENTS */ #endif /* __ARM_PMU_H__ */ |
