Skip to content

Commit 6d0efeb

Browse files
aff-tarbebarino
authored andcommitted
soc: qcom: Separate kryo l2 accessors from PMU driver
The driver provides kernel level API for other drivers to access the MSM8996 L2 cache registers. Separating the L2 access code from the PMU driver and making it public to allow other drivers use it. The accesses must be separated with a single spinlock, maintained in this driver. Signed-off-by: Ilia Lin <[email protected]> Signed-off-by: Loic Poulain <[email protected]> Link: https://lore.kernel.org/r/[email protected] Acked-by: Will Deacon <[email protected]> Signed-off-by: Stephen Boyd <[email protected]>
1 parent dbb988b commit 6d0efeb

File tree

6 files changed

+99
-66
lines changed

6 files changed

+99
-66
lines changed

drivers/perf/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ config FSL_IMX8_DDR_PMU
8282
config QCOM_L2_PMU
8383
bool "Qualcomm Technologies L2-cache PMU"
8484
depends on ARCH_QCOM && ARM64 && ACPI
85+
select QCOM_KRYO_L2_ACCESSORS
8586
help
8687
Provides support for the L2 cache performance monitor unit (PMU)
8788
in Qualcomm Technologies processors.

drivers/perf/qcom_l2_pmu.c

Lines changed: 24 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <asm/barrier.h>
2424
#include <asm/local64.h>
2525
#include <asm/sysreg.h>
26+
#include <soc/qcom/kryo-l2-accessors.h>
2627

2728
#define MAX_L2_CTRS 9
2829

@@ -79,8 +80,6 @@
7980
#define L2_COUNTER_RELOAD BIT_ULL(31)
8081
#define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63)
8182

82-
#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
83-
#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7)
8483

8584
#define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE)
8685

@@ -99,48 +98,7 @@
9998
#define L2_EVENT_STREX 0x421
10099
#define L2_EVENT_CLREX 0x422
101100

102-
static DEFINE_RAW_SPINLOCK(l2_access_lock);
103101

104-
/**
105-
* set_l2_indirect_reg: write value to an L2 register
106-
* @reg: Address of L2 register.
107-
* @value: Value to be written to register.
108-
*
109-
* Use architecturally required barriers for ordering between system register
110-
* accesses
111-
*/
112-
static void set_l2_indirect_reg(u64 reg, u64 val)
113-
{
114-
unsigned long flags;
115-
116-
raw_spin_lock_irqsave(&l2_access_lock, flags);
117-
write_sysreg_s(reg, L2CPUSRSELR_EL1);
118-
isb();
119-
write_sysreg_s(val, L2CPUSRDR_EL1);
120-
isb();
121-
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
122-
}
123-
124-
/**
125-
* get_l2_indirect_reg: read an L2 register value
126-
* @reg: Address of L2 register.
127-
*
128-
* Use architecturally required barriers for ordering between system register
129-
* accesses
130-
*/
131-
static u64 get_l2_indirect_reg(u64 reg)
132-
{
133-
u64 val;
134-
unsigned long flags;
135-
136-
raw_spin_lock_irqsave(&l2_access_lock, flags);
137-
write_sysreg_s(reg, L2CPUSRSELR_EL1);
138-
isb();
139-
val = read_sysreg_s(L2CPUSRDR_EL1);
140-
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
141-
142-
return val;
143-
}
144102

145103
struct cluster_pmu;
146104

@@ -211,75 +169,75 @@ static inline struct cluster_pmu *get_cluster_pmu(
211169
static void cluster_pmu_reset(void)
212170
{
213171
/* Reset all counters */
214-
set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
215-
set_l2_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
216-
set_l2_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
217-
set_l2_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
172+
kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
173+
kryo_l2_set_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask);
174+
kryo_l2_set_indirect_reg(L2PMINTENCLR, l2_counter_present_mask);
175+
kryo_l2_set_indirect_reg(L2PMOVSCLR, l2_counter_present_mask);
218176
}
219177

220178
static inline void cluster_pmu_enable(void)
221179
{
222-
set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
180+
kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE);
223181
}
224182

225183
static inline void cluster_pmu_disable(void)
226184
{
227-
set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
185+
kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE);
228186
}
229187

230188
static inline void cluster_pmu_counter_set_value(u32 idx, u64 value)
231189
{
232190
if (idx == l2_cycle_ctr_idx)
233-
set_l2_indirect_reg(L2PMCCNTR, value);
191+
kryo_l2_set_indirect_reg(L2PMCCNTR, value);
234192
else
235-
set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
193+
kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value);
236194
}
237195

238196
static inline u64 cluster_pmu_counter_get_value(u32 idx)
239197
{
240198
u64 value;
241199

242200
if (idx == l2_cycle_ctr_idx)
243-
value = get_l2_indirect_reg(L2PMCCNTR);
201+
value = kryo_l2_get_indirect_reg(L2PMCCNTR);
244202
else
245-
value = get_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx));
203+
value = kryo_l2_get_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx));
246204

247205
return value;
248206
}
249207

250208
static inline void cluster_pmu_counter_enable(u32 idx)
251209
{
252-
set_l2_indirect_reg(L2PMCNTENSET, idx_to_reg_bit(idx));
210+
kryo_l2_set_indirect_reg(L2PMCNTENSET, idx_to_reg_bit(idx));
253211
}
254212

255213
static inline void cluster_pmu_counter_disable(u32 idx)
256214
{
257-
set_l2_indirect_reg(L2PMCNTENCLR, idx_to_reg_bit(idx));
215+
kryo_l2_set_indirect_reg(L2PMCNTENCLR, idx_to_reg_bit(idx));
258216
}
259217

260218
static inline void cluster_pmu_counter_enable_interrupt(u32 idx)
261219
{
262-
set_l2_indirect_reg(L2PMINTENSET, idx_to_reg_bit(idx));
220+
kryo_l2_set_indirect_reg(L2PMINTENSET, idx_to_reg_bit(idx));
263221
}
264222

265223
static inline void cluster_pmu_counter_disable_interrupt(u32 idx)
266224
{
267-
set_l2_indirect_reg(L2PMINTENCLR, idx_to_reg_bit(idx));
225+
kryo_l2_set_indirect_reg(L2PMINTENCLR, idx_to_reg_bit(idx));
268226
}
269227

270228
static inline void cluster_pmu_set_evccntcr(u32 val)
271229
{
272-
set_l2_indirect_reg(L2PMCCNTCR, val);
230+
kryo_l2_set_indirect_reg(L2PMCCNTCR, val);
273231
}
274232

275233
static inline void cluster_pmu_set_evcntcr(u32 ctr, u32 val)
276234
{
277-
set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTCR, ctr), val);
235+
kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTCR, ctr), val);
278236
}
279237

280238
static inline void cluster_pmu_set_evtyper(u32 ctr, u32 val)
281239
{
282-
set_l2_indirect_reg(reg_idx(IA_L2PMXEVTYPER, ctr), val);
240+
kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVTYPER, ctr), val);
283241
}
284242

285243
static void cluster_pmu_set_resr(struct cluster_pmu *cluster,
@@ -295,11 +253,11 @@ static void cluster_pmu_set_resr(struct cluster_pmu *cluster,
295253

296254
spin_lock_irqsave(&cluster->pmu_lock, flags);
297255

298-
resr_val = get_l2_indirect_reg(L2PMRESR);
256+
resr_val = kryo_l2_get_indirect_reg(L2PMRESR);
299257
resr_val &= ~(L2PMRESR_GROUP_MASK << shift);
300258
resr_val |= field;
301259
resr_val |= L2PMRESR_EN;
302-
set_l2_indirect_reg(L2PMRESR, resr_val);
260+
kryo_l2_set_indirect_reg(L2PMRESR, resr_val);
303261

304262
spin_unlock_irqrestore(&cluster->pmu_lock, flags);
305263
}
@@ -315,14 +273,14 @@ static inline void cluster_pmu_set_evfilter_sys_mode(u32 ctr)
315273
L2PMXEVFILTER_ORGFILTER_IDINDEP |
316274
L2PMXEVFILTER_ORGFILTER_ALL;
317275

318-
set_l2_indirect_reg(reg_idx(IA_L2PMXEVFILTER, ctr), val);
276+
kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVFILTER, ctr), val);
319277
}
320278

321279
static inline u32 cluster_pmu_getreset_ovsr(void)
322280
{
323-
u32 result = get_l2_indirect_reg(L2PMOVSSET);
281+
u32 result = kryo_l2_get_indirect_reg(L2PMOVSSET);
324282

325-
set_l2_indirect_reg(L2PMOVSCLR, result);
283+
kryo_l2_set_indirect_reg(L2PMOVSCLR, result);
326284
return result;
327285
}
328286

@@ -767,7 +725,7 @@ static int get_num_counters(void)
767725
{
768726
int val;
769727

770-
val = get_l2_indirect_reg(L2PMCR);
728+
val = kryo_l2_get_indirect_reg(L2PMCR);
771729

772730
/*
773731
* Read number of counters from L2PMCR and add 1

drivers/soc/qcom/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ config QCOM_LLCC
5353
SDM845. This provides interfaces to clients that use the LLCC.
5454
Say yes here to enable LLCC slice driver.
5555

56+
config QCOM_KRYO_L2_ACCESSORS
57+
bool
58+
depends on ARCH_QCOM && ARM64 || COMPILE_TEST
59+
5660
config QCOM_MDT_LOADER
5761
tristate
5862
select QCOM_SCM

drivers/soc/qcom/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ obj-$(CONFIG_QCOM_APR) += apr.o
2424
obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o
2525
obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
2626
obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
27+
obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) += kryo-l2-accessors.o

drivers/soc/qcom/kryo-l2-accessors.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
4+
*/
5+
6+
#include <linux/spinlock.h>
7+
#include <asm/barrier.h>
8+
#include <asm/sysreg.h>
9+
#include <soc/qcom/kryo-l2-accessors.h>
10+
11+
#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6)
12+
#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7)
13+
14+
static DEFINE_RAW_SPINLOCK(l2_access_lock);
15+
16+
/**
17+
* kryo_l2_set_indirect_reg() - write value to an L2 register
18+
* @reg: Address of L2 register.
19+
* @value: Value to be written to register.
20+
*
21+
* Use architecturally required barriers for ordering between system register
22+
* accesses, and system registers with respect to device memory
23+
*/
24+
void kryo_l2_set_indirect_reg(u64 reg, u64 val)
25+
{
26+
unsigned long flags;
27+
28+
raw_spin_lock_irqsave(&l2_access_lock, flags);
29+
write_sysreg_s(reg, L2CPUSRSELR_EL1);
30+
isb();
31+
write_sysreg_s(val, L2CPUSRDR_EL1);
32+
isb();
33+
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
34+
}
35+
EXPORT_SYMBOL(kryo_l2_set_indirect_reg);
36+
37+
/**
38+
* kryo_l2_get_indirect_reg() - read an L2 register value
39+
* @reg: Address of L2 register.
40+
*
41+
* Use architecturally required barriers for ordering between system register
42+
* accesses, and system registers with respect to device memory
43+
*/
44+
u64 kryo_l2_get_indirect_reg(u64 reg)
45+
{
46+
u64 val;
47+
unsigned long flags;
48+
49+
raw_spin_lock_irqsave(&l2_access_lock, flags);
50+
write_sysreg_s(reg, L2CPUSRSELR_EL1);
51+
isb();
52+
val = read_sysreg_s(L2CPUSRDR_EL1);
53+
raw_spin_unlock_irqrestore(&l2_access_lock, flags);
54+
55+
return val;
56+
}
57+
EXPORT_SYMBOL(kryo_l2_get_indirect_reg);

include/soc/qcom/kryo-l2-accessors.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
4+
*/
5+
6+
#ifndef __SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H
7+
#define __SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H
8+
9+
void kryo_l2_set_indirect_reg(u64 reg, u64 val);
10+
u64 kryo_l2_get_indirect_reg(u64 reg);
11+
12+
#endif

0 commit comments

Comments
 (0)