Commit b828f960 authored by Mark Rutland's avatar Mark Rutland Committed by Russell King

ARM: 8611/1: l2x0: add PMU support

The L2C-220 (AKA L220) and L2C-310 (AKA PL310) cache controllers feature
a Performance Monitoring Unit (PMU), which can be useful for tuning
and/or debugging. This hardware is always present and the relevant
registers are accessible to non-secure accesses. Thus, no special
firmware interface is necessary.

This patch adds support for the PMU, plugging into the usual perf
infrastructure. The overflow interrupt is not always available (e.g. on
RealView PBX A9 it is not wired up at all), and the hardware counters
saturate, so the driver does not make use of this. Instead, the driver
periodically polls and reset counters as required to avoid losing
events due to saturation.
Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Acked-by: default avatarPawel Moll <pawel.moll@arm.com>
Tested-by: default avatarKim Phillips <kim.phillips@arm.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 8e02676f
...@@ -87,6 +87,15 @@ ...@@ -87,6 +87,15 @@
#define L310_CACHE_ID_RTL_R3P2 0x08 #define L310_CACHE_ID_RTL_R3P2 0x08
#define L310_CACHE_ID_RTL_R3P3 0x09 #define L310_CACHE_ID_RTL_R3P3 0x09
#define L2X0_EVENT_CNT_CTRL_ENABLE BIT(0)
#define L2X0_EVENT_CNT_CFG_SRC_SHIFT 2
#define L2X0_EVENT_CNT_CFG_SRC_MASK 0xf
#define L2X0_EVENT_CNT_CFG_SRC_DISABLED 0
#define L2X0_EVENT_CNT_CFG_INT_DISABLED 0
#define L2X0_EVENT_CNT_CFG_INT_INCR 1
#define L2X0_EVENT_CNT_CFG_INT_OVERFLOW 2
/* L2C auxiliary control register - bits common to L2C-210/220/310 */ /* L2C auxiliary control register - bits common to L2C-210/220/310 */
#define L2C_AUX_CTRL_WAY_SIZE_SHIFT 17 #define L2C_AUX_CTRL_WAY_SIZE_SHIFT 17
#define L2C_AUX_CTRL_WAY_SIZE_MASK (7 << 17) #define L2C_AUX_CTRL_WAY_SIZE_MASK (7 << 17)
...@@ -157,6 +166,16 @@ static inline int l2x0_of_init(u32 aux_val, u32 aux_mask) ...@@ -157,6 +166,16 @@ static inline int l2x0_of_init(u32 aux_val, u32 aux_mask)
} }
#endif #endif
#ifdef CONFIG_CACHE_L2X0_PMU
void l2x0_pmu_register(void __iomem *base, u32 part);
void l2x0_pmu_suspend(void);
void l2x0_pmu_resume(void);
#else
static inline void l2x0_pmu_register(void __iomem *base, u32 part) {}
static inline void l2x0_pmu_suspend(void) {}
static inline void l2x0_pmu_resume(void) {}
#endif
struct l2x0_regs { struct l2x0_regs {
unsigned long phy_base; unsigned long phy_base;
unsigned long aux_ctrl; unsigned long aux_ctrl;
......
...@@ -920,6 +920,13 @@ config CACHE_L2X0 ...@@ -920,6 +920,13 @@ config CACHE_L2X0
help help
This option enables the L2x0 PrimeCell. This option enables the L2x0 PrimeCell.
config CACHE_L2X0_PMU
bool "L2x0 performance monitor support" if CACHE_L2X0
depends on PERF_EVENTS
help
This option enables support for the performance monitoring features
of the L220 and PL310 outer cache controllers.
if CACHE_L2X0 if CACHE_L2X0
config PL310_ERRATA_588369 config PL310_ERRATA_588369
......
...@@ -103,6 +103,7 @@ AFLAGS_proc-v7.o :=-Wa,-march=armv7-a ...@@ -103,6 +103,7 @@ AFLAGS_proc-v7.o :=-Wa,-march=armv7-a
obj-$(CONFIG_OUTER_CACHE) += l2c-common.o obj-$(CONFIG_OUTER_CACHE) += l2c-common.o
obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o l2c-l2x0-resume.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o l2c-l2x0-resume.o
obj-$(CONFIG_CACHE_L2X0_PMU) += cache-l2x0-pmu.o
obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o
obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o
obj-$(CONFIG_CACHE_UNIPHIER) += cache-uniphier.o obj-$(CONFIG_CACHE_UNIPHIER) += cache-uniphier.o
This diff is collapsed.
...@@ -142,6 +142,8 @@ static void l2c_disable(void) ...@@ -142,6 +142,8 @@ static void l2c_disable(void)
{ {
void __iomem *base = l2x0_base; void __iomem *base = l2x0_base;
l2x0_pmu_suspend();
outer_cache.flush_all(); outer_cache.flush_all();
l2c_write_sec(0, base, L2X0_CTRL); l2c_write_sec(0, base, L2X0_CTRL);
dsb(st); dsb(st);
...@@ -159,6 +161,8 @@ static void l2c_resume(void) ...@@ -159,6 +161,8 @@ static void l2c_resume(void)
/* Do not touch the controller if already enabled. */ /* Do not touch the controller if already enabled. */
if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN))
l2c_enable(base, l2x0_data->num_lock); l2c_enable(base, l2x0_data->num_lock);
l2x0_pmu_resume();
} }
/* /*
...@@ -891,6 +895,8 @@ static int __init __l2c_init(const struct l2c_init_data *data, ...@@ -891,6 +895,8 @@ static int __init __l2c_init(const struct l2c_init_data *data,
pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n",
data->type, cache_id, aux); data->type, cache_id, aux);
l2x0_pmu_register(l2x0_base, cache_id);
return 0; return 0;
} }
......
...@@ -86,6 +86,7 @@ enum cpuhp_state { ...@@ -86,6 +86,7 @@ enum cpuhp_state {
CPUHP_AP_PERF_S390_SF_ONLINE, CPUHP_AP_PERF_S390_SF_ONLINE,
CPUHP_AP_PERF_ARM_CCI_ONLINE, CPUHP_AP_PERF_ARM_CCI_ONLINE,
CPUHP_AP_PERF_ARM_CCN_ONLINE, CPUHP_AP_PERF_ARM_CCN_ONLINE,
CPUHP_AP_PERF_ARM_L2X0_ONLINE,
CPUHP_AP_WORKQUEUE_ONLINE, CPUHP_AP_WORKQUEUE_ONLINE,
CPUHP_AP_RCUTREE_ONLINE, CPUHP_AP_RCUTREE_ONLINE,
CPUHP_AP_NOTIFY_ONLINE, CPUHP_AP_NOTIFY_ONLINE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment