11 #include <linux/string.h>
12 #include <linux/perf_event.h>
14 #include <asm/cputable.h>
22 #define PM_THRMULT_MSKS 0x40000
23 #define PM_THRESH_SH 12
24 #define PM_THRESH_MSK 0x3f
27 #define PM_PMCSEL_MSK 0x7f
41 static int mpc7450_classify_event(
u32 event)
81 static int mpc7450_threshold_use(
u32 event)
89 if (sel == 0x1e || sel == 0x1f)
91 if (sel == 0x28 || sel == 0x2b)
99 if (sel == 0
xc || sel == 0xd)
139 { 0x00844002, 0x00111001 },
140 { 0x00844008, 0x00111004 },
141 { 0x00800020, 0x00100010 },
142 { 0x00840080, 0x00110040 },
143 { 0x00000200, 0x00000100 },
144 { 0x00000800, 0x00000400 }
148 { 0x00000000, 0x00000000 },
149 { 0x00800000, 0x00100000 },
150 { 0x00040000, 0x00010000 },
151 { 0x00004000, 0x00001000 },
154 static int mpc7450_get_constraint(
u64 event,
unsigned long *maskp,
161 class = mpc7450_classify_event(event);
166 mask = pmcbits[pmc - 1][0];
167 value = pmcbits[pmc - 1][1];
169 mask = classbits[
class][0];
170 value = classbits[
class][1];
173 tuse = mpc7450_threshold_use(event);
177 value |= thresh << 24;
190 static const unsigned int event_alternatives[][
MAX_ALT] = {
192 { 0x418, 0x50f, 0x60f },
212 static int find_alternative(
u32 event)
216 for (i = 0; i <
ARRAY_SIZE(event_alternatives); ++
i) {
217 if (event < event_alternatives[i][0])
219 for (j = 0; j <
MAX_ALT && event_alternatives[
i][
j]; ++
j)
220 if (event == event_alternatives[i][j])
226 static int mpc7450_get_alternatives(
u64 event,
unsigned int flags,
u64 alt[])
233 i = find_alternative((
u32)event);
236 ae = event_alternatives[
i][
j];
237 if (ae && ae != (
u32)event)
249 0x3f, 0x0f, 0x0b, 0x03, 0
253 static const int pmcsel_shift[
N_COUNTER] = {
257 0x7f, 0x3f, 0x1f, 0x1f, 0x1f, 0x3f
263 static int mpc7450_compute_mmcr(
u64 event[],
int n_ev,
264 unsigned int hwc[],
unsigned long mmcr[])
268 int i,
j,
class, tuse;
269 u32 pmc_inuse = 0, pmc_avail;
270 u32 mmcr0 = 0, mmcr1 = 0, mmcr2 = 0;
279 for (i = 0; i < n_ev; ++
i) {
280 class = mpc7450_classify_event(event[i]);
283 j = n_classevent[
class]++;
284 event_index[
class][
j] =
i;
288 for (
class = N_CLASSES - 1;
class >= 0; --
class) {
289 for (i = 0; i < n_classevent[
class]; ++
i) {
290 ev =
event[event_index[
class][
i]];
293 if (pmc_inuse & (1 << (pmc - 1)))
297 pmc_avail = classmap[
class] & ~pmc_inuse;
300 pmc =
ffs(pmc_avail);
302 pmc_inuse |= 1 << (pmc - 1);
304 tuse = mpc7450_threshold_use(ev);
307 mmcr0 |= thresh << 16;
311 ev &= pmcsel_mask[pmc - 1];
312 ev <<= pmcsel_shift[pmc - 1];
317 hwc[event_index[
class][
i]] = pmc - 1;
322 mmcr0 |= MMCR0_PMC1CE;
323 if (pmc_inuse & 0x3e)
324 mmcr0 |= MMCR0_PMCnCE;
337 static void mpc7450_disable_pmc(
unsigned int pmc,
unsigned long mmcr[])
340 mmcr[0] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]);
342 mmcr[1] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]);
345 static int mpc7450_generic_events[] = {
353 #define C(x) PERF_COUNT_HW_CACHE_##x
360 static int mpc7450_cache_events[
C(
MAX)][
C(
OP_MAX)][
C(RESULT_MAX)] = {
364 [
C(OP_PREFETCH)] = { 0, 0 },
369 [
C(OP_PREFETCH)] = { 0x634, 0 },
374 [
C(OP_PREFETCH)] = { 0, 0 },
379 [
C(OP_PREFETCH)] = { -1, -1 },
384 [
C(OP_PREFETCH)] = { -1, -1 },
389 [
C(OP_PREFETCH)] = { -1, -1 },
394 [
C(OP_PREFETCH)] = { -1, -1 },
399 .name =
"MPC7450 family",
402 .add_fields = 0x00111555ul,
403 .test_adder = 0x00301000ul,
404 .compute_mmcr = mpc7450_compute_mmcr,
405 .get_constraint = mpc7450_get_constraint,
406 .get_alternatives = mpc7450_get_alternatives,
407 .disable_pmc = mpc7450_disable_pmc,
408 .n_generic =
ARRAY_SIZE(mpc7450_generic_events),
409 .generic_events = mpc7450_generic_events,
410 .cache_events = &mpc7450_cache_events,
413 static int __init init_mpc7450_pmu(
void)