Blame src/perfctr-2.6.x/linux/drivers/perfctr/ppc.c

Packit Service a1973e
/* $Id: ppc.c,v 1.3.2.22 2009/06/11 12:33:51 mikpe Exp $
Packit Service a1973e
 * PPC32 performance-monitoring counters driver.
Packit Service a1973e
 *
Packit Service a1973e
 * Copyright (C) 2004-2009  Mikael Pettersson
Packit Service a1973e
 */
Packit Service a1973e
#include <linux/version.h>
Packit Service a1973e
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
Packit Service a1973e
#include <linux/config.h>
Packit Service a1973e
#endif
Packit Service a1973e
#define __NO_VERSION__
Packit Service a1973e
#include <linux/module.h>
Packit Service a1973e
#include <linux/init.h>
Packit Service a1973e
#include <linux/sched.h>
Packit Service a1973e
#include <linux/fs.h>
Packit Service a1973e
#include <linux/perfctr.h>
Packit Service a1973e
#include <asm/prom.h>
Packit Service a1973e
#include <asm/time.h>		/* tb_ticks_per_jiffy, get_tbl() */
Packit Service a1973e
Packit Service a1973e
#include "compat.h"
Packit Service a1973e
#include "ppc_compat.h"
Packit Service a1973e
#include "ppc_tests.h"
Packit Service a1973e
Packit Service a1973e
/* Support for lazy evntsel and perfctr SPR updates. */
Packit Service a1973e
struct per_cpu_cache {	/* roughly a subset of perfctr_cpu_state */
Packit Service a1973e
	union {
Packit Service a1973e
		unsigned int id;	/* cache owner id */
Packit Service a1973e
	} k1;
Packit Service a1973e
	/* Physically indexed cache of the MMCRs. */
Packit Service a1973e
	unsigned int ppc_mmcr[3];
Packit Service a1973e
} ____cacheline_aligned;
Packit Service a1973e
static struct per_cpu_cache per_cpu_cache[NR_CPUS] __cacheline_aligned;
Packit Service a1973e
#define __get_cpu_cache(cpu) (&per_cpu_cache[cpu])
Packit Service a1973e
#define get_cpu_cache()	(&per_cpu_cache[smp_processor_id()])
Packit Service a1973e
Packit Service a1973e
/* Structure for counter snapshots, as 32-bit values. */
Packit Service a1973e
struct perfctr_low_ctrs {
Packit Service a1973e
	unsigned int tsc;
Packit Service a1973e
	unsigned int pmc[6];
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
enum pm_type {
Packit Service a1973e
	PM_NONE,
Packit Service a1973e
	PM_604,
Packit Service a1973e
	PM_604e,
Packit Service a1973e
	PM_750,	/* XXX: Minor event set diffs between IBM and Moto. */
Packit Service a1973e
	PM_7400,
Packit Service a1973e
	PM_7450,
Packit Service a1973e
};
Packit Service a1973e
static enum pm_type pm_type;
Packit Service a1973e
Packit Service a1973e
/* Bits users shouldn't set in control.ppc.mmcr0:
Packit Service a1973e
 * - PMC1SEL/PMC2SEL because event selectors are in control.evntsel[]
Packit Service a1973e
 */
Packit Service a1973e
#define MMCR0_RESERVED		(MMCR0_PMC1SEL | MMCR0_PMC2SEL)
Packit Service a1973e
Packit Service a1973e
static unsigned int new_id(void)
Packit Service a1973e
{
Packit Service a1973e
	static DEFINE_SPINLOCK(lock);
Packit Service a1973e
	static unsigned int counter;
Packit Service a1973e
	int id;
Packit Service a1973e
Packit Service a1973e
	spin_lock(&lock);
Packit Service a1973e
	id = ++counter;
Packit Service a1973e
	spin_unlock(&lock);
Packit Service a1973e
	return id;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
#ifndef CONFIG_PERFCTR_INTERRUPT_SUPPORT
Packit Service a1973e
#define perfctr_cstatus_has_ictrs(cstatus)	0
Packit Service a1973e
#endif
Packit Service a1973e
Packit Service a1973e
#if defined(CONFIG_SMP) && defined(CONFIG_PERFCTR_INTERRUPT_SUPPORT)
Packit Service a1973e
Packit Service a1973e
static inline void
Packit Service a1973e
set_isuspend_cpu(struct perfctr_cpu_state *state, int cpu)
Packit Service a1973e
{
Packit Service a1973e
	state->k1.isuspend_cpu = cpu;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static inline int
Packit Service a1973e
is_isuspend_cpu(const struct perfctr_cpu_state *state, int cpu)
Packit Service a1973e
{
Packit Service a1973e
	return state->k1.isuspend_cpu == cpu;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	state->k1.isuspend_cpu = NR_CPUS;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
#else
Packit Service a1973e
static inline void set_isuspend_cpu(struct perfctr_cpu_state *state, int cpu) { }
Packit Service a1973e
static inline int is_isuspend_cpu(const struct perfctr_cpu_state *state, int cpu) { return 1; }
Packit Service a1973e
static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state) { }
Packit Service a1973e
#endif
Packit Service a1973e
Packit Service a1973e
/* The ppc driver internally uses cstatus & (1<<30) to record that
Packit Service a1973e
   a context has an asynchronously changing MMCR0. */
Packit Service a1973e
static inline unsigned int perfctr_cstatus_set_mmcr0_quirk(unsigned int cstatus)
Packit Service a1973e
{
Packit Service a1973e
	return cstatus | (1 << 30);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static inline int perfctr_cstatus_has_mmcr0_quirk(unsigned int cstatus)
Packit Service a1973e
{
Packit Service a1973e
	return cstatus & (1 << 30);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/****************************************************************
Packit Service a1973e
 *								*
Packit Service a1973e
 * Driver procedures.						*
Packit Service a1973e
 *								*
Packit Service a1973e
 ****************************************************************/
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * The PowerPC 604/750/74xx family.
Packit Service a1973e
 *
Packit Service a1973e
 * Common features
Packit Service a1973e
 * ---------------
Packit Service a1973e
 * - Per counter event selection data in subfields of control registers.
Packit Service a1973e
 *   MMCR0 contains both global control and PMC1/PMC2 event selectors.
Packit Service a1973e
 * - Overflow interrupt support is present in all processors, but an
Packit Service a1973e
 *   erratum makes it difficult to use in 750/7400/7410 processors.
Packit Service a1973e
 * - There is no concept of per-counter qualifiers:
Packit Service a1973e
 *   - User-mode/supervisor-mode restrictions are global.
Packit Service a1973e
 *   - Two groups of counters, PMC1 and PMC2-PMC<highest>. Each group
Packit Service a1973e
 *     has a single overflow interrupt/event enable/disable flag.
Packit Service a1973e
 * - The instructions used to read (mfspr) and write (mtspr) the control
Packit Service a1973e
 *   and counter registers (SPRs) only support hardcoded register numbers.
Packit Service a1973e
 *   There is no support for accessing an SPR via a runtime value.
Packit Service a1973e
 * - Each counter supports its own unique set of events. However, events
Packit Service a1973e
 *   0-1 are common for PMC1-PMC4, and events 2-4 are common for PMC1-PMC4.
Packit Service a1973e
 * - There is no separate high-resolution core clock counter.
Packit Service a1973e
 *   The time-base counter is available, but it typically runs an order of
Packit Service a1973e
 *   magnitude slower than the core clock.
Packit Service a1973e
 *   Any performance counter can be programmed to count core clocks, but
Packit Service a1973e
 *   doing this (a) reserves one PMC, and (b) needs indirect accesses
Packit Service a1973e
 *   since the SPR number in general isn't known at compile-time.
Packit Service a1973e
 *
Packit Service a1973e
 * 604
Packit Service a1973e
 * ---
Packit Service a1973e
 * 604 has MMCR0, PMC1, PMC2, SIA, and SDA.
Packit Service a1973e
 *
Packit Service a1973e
 * MMCR0[THRESHOLD] is not automatically multiplied.
Packit Service a1973e
 *
Packit Service a1973e
 * On the 604, software must always reset MMCR0[ENINT] after
Packit Service a1973e
 * taking a PMI. This is not the case for the 604e.
Packit Service a1973e
 *
Packit Service a1973e
 * 604e
Packit Service a1973e
 * ----
Packit Service a1973e
 * 604e adds MMCR1, PMC3, and PMC4.
Packit Service a1973e
 * Bus-to-core multiplier is available via HID1[PLL_CFG].
Packit Service a1973e
 *
Packit Service a1973e
 * MMCR0[THRESHOLD] is automatically multiplied by 4.
Packit Service a1973e
 *
Packit Service a1973e
 * When the 604e vectors to the PMI handler, it automatically
Packit Service a1973e
 * clears any pending PMIs. Unlike the 604, the 604e does not
Packit Service a1973e
 * require MMCR0[ENINT] to be cleared (and possibly reset)
Packit Service a1973e
 * before external interrupts can be re-enabled.
Packit Service a1973e
 *
Packit Service a1973e
 * 750
Packit Service a1973e
 * ---
Packit Service a1973e
 * 750 adds user-readable MMCRn/PMCn/SIA registers, and removes SDA.
Packit Service a1973e
 *
Packit Service a1973e
 * MMCR0[THRESHOLD] is not automatically multiplied.
Packit Service a1973e
 *
Packit Service a1973e
 * Motorola MPC750UM.pdf, page C-78, states: "The performance monitor
Packit Service a1973e
 * of the MPC755 functions the same as that of the MPC750, (...), except
Packit Service a1973e
 * that for both the MPC750 and MPC755, no combination of the thermal
Packit Service a1973e
 * assist unit, the decrementer register, and the performance monitor
Packit Service a1973e
 * can be used at any one time. If exceptions for any two of these
Packit Service a1973e
 * functional blocks are enabled together, multiple exceptions caused
Packit Service a1973e
 * by any of these three blocks cause unpredictable results."
Packit Service a1973e
 *
Packit Service a1973e
 * IBM 750CXe_Err_DD2X.pdf, Erratum #13, states that a PMI which
Packit Service a1973e
 * occurs immediately after a delayed decrementer exception can
Packit Service a1973e
 * corrupt SRR0, causing the processor to hang. It also states that
Packit Service a1973e
 * PMIs via TB bit transitions can be used to simulate the decrementer.
Packit Service a1973e
 *
Packit Service a1973e
 * 750FX adds dual-PLL support and programmable core frequency switching.
Packit Service a1973e
 *
Packit Service a1973e
 * 750FX DD2.3 fixed the DEC/PMI SRR0 corruption erratum.
Packit Service a1973e
 *
Packit Service a1973e
 * 74xx
Packit Service a1973e
 * ----
Packit Service a1973e
 * 7400 adds MMCR2 and BAMR.
Packit Service a1973e
 *
Packit Service a1973e
 * MMCR0[THRESHOLD] is multiplied by 2 or 32, as specified
Packit Service a1973e
 * by MMCR2[THRESHMULT].
Packit Service a1973e
 *
Packit Service a1973e
 * 74xx changes the semantics of several MMCR0 control bits,
Packit Service a1973e
 * compared to 604/750.
Packit Service a1973e
 *
Packit Service a1973e
 * PPC7410 Erratum No. 10: Like the MPC750 TAU/DECR/PMI erratum.
Packit Service a1973e
 * Erratum No. 14 marks TAU as unsupported in 7410, but this leaves
Packit Service a1973e
 * perfmon and decrementer interrupts as being mutually exclusive.
Packit Service a1973e
 * Affects PPC7410 1.0-1.2 (PVR 0x800C1100-0x800C1102). 1.3 and up
Packit Service a1973e
 * (PVR 0x800C1103 up) are Ok.
Packit Service a1973e
 *
Packit Service a1973e
 * 7450 adds PMC5 and PMC6.
Packit Service a1973e
 *
Packit Service a1973e
 * 7455/7445 V3.3 (PVR 80010303) and later use the 7457 PLL table,
Packit Service a1973e
 * earlier revisions use the 7450 PLL table
Packit Service a1973e
 */
Packit Service a1973e
Packit Service a1973e
static inline unsigned int read_pmc(unsigned int pmc)
Packit Service a1973e
{
Packit Service a1973e
	switch (pmc) {
Packit Service a1973e
	default: /* impossible, but silences gcc warning */
Packit Service a1973e
	case 0:
Packit Service a1973e
		return mfspr(SPRN_PMC1);
Packit Service a1973e
	case 1:
Packit Service a1973e
		return mfspr(SPRN_PMC2);
Packit Service a1973e
	case 2:
Packit Service a1973e
		return mfspr(SPRN_PMC3);
Packit Service a1973e
	case 3:
Packit Service a1973e
		return mfspr(SPRN_PMC4);
Packit Service a1973e
	case 4:
Packit Service a1973e
		return mfspr(SPRN_PMC5);
Packit Service a1973e
	case 5:
Packit Service a1973e
		return mfspr(SPRN_PMC6);
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void ppc_read_counters(struct perfctr_cpu_state *state,
Packit Service a1973e
			      struct perfctr_low_ctrs *ctrs)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int cstatus, nrctrs, i;
Packit Service a1973e
Packit Service a1973e
	cstatus = state->cstatus;
Packit Service a1973e
	if (perfctr_cstatus_has_tsc(cstatus))
Packit Service a1973e
		ctrs->tsc = get_tbl();
Packit Service a1973e
	nrctrs = perfctr_cstatus_nractrs(cstatus);
Packit Service a1973e
	for(i = 0; i < nrctrs; ++i) {
Packit Service a1973e
		unsigned int pmc = state->pmc[i].map;
Packit Service a1973e
		ctrs->pmc[i] = read_pmc(pmc);
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static unsigned int pmc_max_event(unsigned int pmc)
Packit Service a1973e
{
Packit Service a1973e
	switch (pmc) {
Packit Service a1973e
	default: /* impossible, but silences gcc warning */
Packit Service a1973e
	case 0:
Packit Service a1973e
		return 127;
Packit Service a1973e
	case 1:
Packit Service a1973e
		return 63;
Packit Service a1973e
	case 2:
Packit Service a1973e
		return 31;
Packit Service a1973e
	case 3:
Packit Service a1973e
		return 31;
Packit Service a1973e
	case 4:
Packit Service a1973e
		return 31;
Packit Service a1973e
	case 5:
Packit Service a1973e
		return 63;
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static unsigned int get_nr_pmcs(void)
Packit Service a1973e
{
Packit Service a1973e
	switch (pm_type) {
Packit Service a1973e
	case PM_7450:
Packit Service a1973e
		return 6;
Packit Service a1973e
	case PM_7400:
Packit Service a1973e
	case PM_750:
Packit Service a1973e
	case PM_604e:
Packit Service a1973e
		return 4;
Packit Service a1973e
	case PM_604:
Packit Service a1973e
		return 2;
Packit Service a1973e
	default: /* PM_NONE, but silences gcc warning */
Packit Service a1973e
		return 0;
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int ppc_check_control(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int i, nractrs, nrctrs, pmc_mask, pmi_mask, pmc;
Packit Service a1973e
	unsigned int nr_pmcs, evntsel[6];
Packit Service a1973e
Packit Service a1973e
	nr_pmcs = get_nr_pmcs();
Packit Service a1973e
	nractrs = state->control.nractrs;
Packit Service a1973e
	nrctrs = nractrs + state->control.nrictrs;
Packit Service a1973e
	if (nrctrs < nractrs || nrctrs > nr_pmcs)
Packit Service a1973e
		return -EINVAL;
Packit Service a1973e
Packit Service a1973e
	pmc_mask = 0;
Packit Service a1973e
	pmi_mask = 0;
Packit Service a1973e
	memset(evntsel, 0, sizeof evntsel);
Packit Service a1973e
	for(i = 0; i < nrctrs; ++i) {
Packit Service a1973e
		pmc = state->control.pmc_map[i];
Packit Service a1973e
		state->pmc[i].map = pmc;
Packit Service a1973e
		if (pmc >= nr_pmcs || (pmc_mask & (1<
Packit Service a1973e
			return -EINVAL;
Packit Service a1973e
		pmc_mask |= (1<
Packit Service a1973e
Packit Service a1973e
		if (i >= nractrs)
Packit Service a1973e
			pmi_mask |= (1<
Packit Service a1973e
Packit Service a1973e
		evntsel[pmc] = state->control.evntsel[i];
Packit Service a1973e
		if (evntsel[pmc] > pmc_max_event(pmc))
Packit Service a1973e
			return -EINVAL;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/* XXX: temporary limitation */
Packit Service a1973e
	if ((pmi_mask & ~1) && (pmi_mask & ~1) != (pmc_mask & ~1))
Packit Service a1973e
		return -EINVAL;
Packit Service a1973e
Packit Service a1973e
	switch (pm_type) {
Packit Service a1973e
	case PM_7450:
Packit Service a1973e
	case PM_7400:
Packit Service a1973e
		if (state->control.ppc.mmcr2 & MMCR2_RESERVED)
Packit Service a1973e
			return -EINVAL;
Packit Service a1973e
		state->ppc_mmcr[2] = state->control.ppc.mmcr2;
Packit Service a1973e
		break;
Packit Service a1973e
	default:
Packit Service a1973e
		if (state->control.ppc.mmcr2)
Packit Service a1973e
			return -EINVAL;
Packit Service a1973e
		state->ppc_mmcr[2] = 0;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/* We do not yet handle TBEE as the only exception cause,
Packit Service a1973e
	   so PMXE requires at least one interrupt-mode counter. */
Packit Service a1973e
	if ((state->control.ppc.mmcr0 & MMCR0_PMXE) && !state->control.nrictrs)
Packit Service a1973e
		return -EINVAL;
Packit Service a1973e
	if (state->control.ppc.mmcr0 & MMCR0_RESERVED)
Packit Service a1973e
		return -EINVAL;
Packit Service a1973e
	state->ppc_mmcr[0] = (state->control.ppc.mmcr0
Packit Service a1973e
			      | (evntsel[0] << (31-25))
Packit Service a1973e
			      | (evntsel[1] << (31-31)));
Packit Service a1973e
Packit Service a1973e
	state->ppc_mmcr[1] = ((  evntsel[2] << (31-4))
Packit Service a1973e
			      | (evntsel[3] << (31-9))
Packit Service a1973e
			      | (evntsel[4] << (31-14))
Packit Service a1973e
			      | (evntsel[5] << (31-20)));
Packit Service a1973e
Packit Service a1973e
	state->k1.id = new_id();
Packit Service a1973e
Packit Service a1973e
	/*
Packit Service a1973e
	 * MMCR0[FC] and MMCR0[TRIGGER] may change on 74xx if FCECE or
Packit Service a1973e
	 * TRIGGER is set. At suspends we must read MMCR0 back into
Packit Service a1973e
	 * the state and the cache and then freeze the counters, and
Packit Service a1973e
	 * at resumes we must unfreeze the counters and reload MMCR0.
Packit Service a1973e
	 */
Packit Service a1973e
	switch (pm_type) {
Packit Service a1973e
	case PM_7450:
Packit Service a1973e
	case PM_7400:
Packit Service a1973e
		if (state->ppc_mmcr[0] & (MMCR0_FCECE | MMCR0_TRIGGER))
Packit Service a1973e
			state->cstatus = perfctr_cstatus_set_mmcr0_quirk(state->cstatus);
Packit Service a1973e
	default:
Packit Service a1973e
		;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
	/* The MMCR0 handling for FCECE and TRIGGER is also needed for PMXE. */
Packit Service a1973e
	if (state->ppc_mmcr[0] & (MMCR0_PMXE | MMCR0_FCECE | MMCR0_TRIGGER))
Packit Service a1973e
		state->cstatus = perfctr_cstatus_set_mmcr0_quirk(state->cstatus);
Packit Service a1973e
Packit Service a1973e
	return 0;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
#ifdef CONFIG_PERFCTR_INTERRUPT_SUPPORT
Packit Service a1973e
/* PRE: perfctr_cstatus_has_ictrs(state->cstatus) != 0 */
Packit Service a1973e
/* PRE: counters frozen */
Packit Service a1973e
static void ppc_isuspend(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	struct per_cpu_cache *cache;
Packit Service a1973e
	unsigned int cstatus, nrctrs, i;
Packit Service a1973e
	int cpu;
Packit Service a1973e
Packit Service a1973e
	cpu = smp_processor_id();
Packit Service a1973e
	set_isuspend_cpu(state, cpu); /* early to limit cpu's live range */
Packit Service a1973e
	cache = __get_cpu_cache(cpu);
Packit Service a1973e
	cstatus = state->cstatus;
Packit Service a1973e
	nrctrs = perfctr_cstatus_nrctrs(cstatus);
Packit Service a1973e
	for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i) {
Packit Service a1973e
		unsigned int pmc = state->pmc[i].map;
Packit Service a1973e
		unsigned int now = read_pmc(pmc);
Packit Service a1973e
		state->pmc[i].sum += now - state->pmc[i].start;
Packit Service a1973e
		state->pmc[i].start = now;
Packit Service a1973e
	}
Packit Service a1973e
	/* cache->k1.id is still == state->k1.id */
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void ppc_iresume(const struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	struct per_cpu_cache *cache;
Packit Service a1973e
	unsigned int cstatus, nrctrs, i;
Packit Service a1973e
	int cpu;
Packit Service a1973e
	unsigned int pmc[6];
Packit Service a1973e
Packit Service a1973e
	cpu = smp_processor_id();
Packit Service a1973e
	cache = __get_cpu_cache(cpu);
Packit Service a1973e
	if (cache->k1.id == state->k1.id) {
Packit Service a1973e
		/* Clearing cache->k1.id to force write_control()
Packit Service a1973e
		   to unfreeze MMCR0 would be done here, but it
Packit Service a1973e
		   is subsumed by resume()'s MMCR0 reload logic. */
Packit Service a1973e
		if (is_isuspend_cpu(state, cpu))
Packit Service a1973e
			return; /* skip reload of PMCs */
Packit Service a1973e
	}
Packit Service a1973e
	/*
Packit Service a1973e
	 * The CPU state wasn't ours.
Packit Service a1973e
	 *
Packit Service a1973e
	 * The counters must be frozen before being reinitialised,
Packit Service a1973e
	 * to prevent unexpected increments and missed overflows.
Packit Service a1973e
	 *
Packit Service a1973e
	 * All unused counters must be reset to a non-overflow state.
Packit Service a1973e
	 */
Packit Service a1973e
	if (!(cache->ppc_mmcr[0] & MMCR0_FC)) {
Packit Service a1973e
		cache->ppc_mmcr[0] |= MMCR0_FC;
Packit Service a1973e
		mtspr(SPRN_MMCR0, cache->ppc_mmcr[0]);
Packit Service a1973e
	}
Packit Service a1973e
	memset(&pmc[0], 0, sizeof pmc);
Packit Service a1973e
	cstatus = state->cstatus;
Packit Service a1973e
	nrctrs = perfctr_cstatus_nrctrs(cstatus);
Packit Service a1973e
	for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i)
Packit Service a1973e
		pmc[state->pmc[i].map] = state->pmc[i].start;
Packit Service a1973e
Packit Service a1973e
	switch (pm_type) {
Packit Service a1973e
	case PM_7450:
Packit Service a1973e
		mtspr(SPRN_PMC6, pmc[6-1]);
Packit Service a1973e
		mtspr(SPRN_PMC5, pmc[5-1]);
Packit Service a1973e
	case PM_7400:
Packit Service a1973e
	case PM_750:
Packit Service a1973e
	case PM_604e:
Packit Service a1973e
		mtspr(SPRN_PMC4, pmc[4-1]);
Packit Service a1973e
		mtspr(SPRN_PMC3, pmc[3-1]);
Packit Service a1973e
	case PM_604:
Packit Service a1973e
		mtspr(SPRN_PMC2, pmc[2-1]);
Packit Service a1973e
		mtspr(SPRN_PMC1, pmc[1-1]);
Packit Service a1973e
	case PM_NONE:
Packit Service a1973e
		;
Packit Service a1973e
	}
Packit Service a1973e
	/* cache->k1.id remains != state->k1.id */
Packit Service a1973e
}
Packit Service a1973e
#endif
Packit Service a1973e
Packit Service a1973e
static void ppc_write_control(const struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	struct per_cpu_cache *cache;
Packit Service a1973e
	unsigned int value;
Packit Service a1973e
Packit Service a1973e
	cache = get_cpu_cache();
Packit Service a1973e
	if (cache->k1.id == state->k1.id)
Packit Service a1973e
		return;
Packit Service a1973e
	/*
Packit Service a1973e
	 * Order matters here: update threshmult and event
Packit Service a1973e
	 * selectors before updating global control, which
Packit Service a1973e
	 * potentially enables PMIs.
Packit Service a1973e
	 *
Packit Service a1973e
	 * Since mtspr doesn't accept a runtime value for the
Packit Service a1973e
	 * SPR number, unroll the loop so each mtspr targets
Packit Service a1973e
	 * a constant SPR.
Packit Service a1973e
	 *
Packit Service a1973e
	 * For processors without MMCR2, we ensure that the
Packit Service a1973e
	 * cache and the state indicate the same value for it,
Packit Service a1973e
	 * preventing any actual mtspr to it. Ditto for MMCR1.
Packit Service a1973e
	 */
Packit Service a1973e
	value = state->ppc_mmcr[2];
Packit Service a1973e
	if (value != cache->ppc_mmcr[2]) {
Packit Service a1973e
		cache->ppc_mmcr[2] = value;
Packit Service a1973e
		mtspr(SPRN_MMCR2, value);
Packit Service a1973e
	}
Packit Service a1973e
	value = state->ppc_mmcr[1];
Packit Service a1973e
	if (value != cache->ppc_mmcr[1]) {
Packit Service a1973e
		cache->ppc_mmcr[1] = value;
Packit Service a1973e
		mtspr(SPRN_MMCR1, value);
Packit Service a1973e
	}
Packit Service a1973e
	value = state->ppc_mmcr[0];
Packit Service a1973e
	if (value != cache->ppc_mmcr[0]) {
Packit Service a1973e
		cache->ppc_mmcr[0] = value;
Packit Service a1973e
		mtspr(SPRN_MMCR0, value);
Packit Service a1973e
	}
Packit Service a1973e
	cache->k1.id = state->k1.id;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void ppc_clear_counters(void)
Packit Service a1973e
{
Packit Service a1973e
	switch (pm_type) {
Packit Service a1973e
	case PM_7450:
Packit Service a1973e
	case PM_7400:
Packit Service a1973e
		mtspr(SPRN_MMCR2, 0);
Packit Service a1973e
		mtspr(SPRN_BAMR, 0);
Packit Service a1973e
	case PM_750:
Packit Service a1973e
	case PM_604e:
Packit Service a1973e
		mtspr(SPRN_MMCR1, 0);
Packit Service a1973e
	case PM_604:
Packit Service a1973e
		mtspr(SPRN_MMCR0, 0);
Packit Service a1973e
	case PM_NONE:
Packit Service a1973e
		;
Packit Service a1973e
	}
Packit Service a1973e
	switch (pm_type) {
Packit Service a1973e
	case PM_7450:
Packit Service a1973e
		mtspr(SPRN_PMC6, 0);
Packit Service a1973e
		mtspr(SPRN_PMC5, 0);
Packit Service a1973e
	case PM_7400:
Packit Service a1973e
	case PM_750:
Packit Service a1973e
	case PM_604e:
Packit Service a1973e
		mtspr(SPRN_PMC4, 0);
Packit Service a1973e
		mtspr(SPRN_PMC3, 0);
Packit Service a1973e
	case PM_604:
Packit Service a1973e
		mtspr(SPRN_PMC2, 0);
Packit Service a1973e
		mtspr(SPRN_PMC1, 0);
Packit Service a1973e
	case PM_NONE:
Packit Service a1973e
		;
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Driver methods, internal and exported.
Packit Service a1973e
 */
Packit Service a1973e
Packit Service a1973e
static void perfctr_cpu_write_control(const struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	return ppc_write_control(state);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void perfctr_cpu_read_counters(struct perfctr_cpu_state *state,
Packit Service a1973e
				      struct perfctr_low_ctrs *ctrs)
Packit Service a1973e
{
Packit Service a1973e
	return ppc_read_counters(state, ctrs);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
#ifdef CONFIG_PERFCTR_INTERRUPT_SUPPORT
Packit Service a1973e
static void perfctr_cpu_isuspend(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	return ppc_isuspend(state);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void perfctr_cpu_iresume(const struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	return ppc_iresume(state);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* Call perfctr_cpu_ireload() just before perfctr_cpu_resume() to
Packit Service a1973e
   bypass internal caching and force a reload if the I-mode PMCs. */
Packit Service a1973e
void perfctr_cpu_ireload(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	state->ppc_mmcr[0] |= MMCR0_PMXE;
Packit Service a1973e
#ifdef CONFIG_SMP
Packit Service a1973e
	clear_isuspend_cpu(state);
Packit Service a1973e
#else
Packit Service a1973e
	get_cpu_cache()->k1.id = 0;
Packit Service a1973e
#endif
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* PRE: the counters have been suspended and sampled by perfctr_cpu_suspend() */
Packit Service a1973e
unsigned int perfctr_cpu_identify_overflow(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int cstatus, nrctrs, pmc, pmc_mask;
Packit Service a1973e
Packit Service a1973e
	cstatus = state->cstatus;
Packit Service a1973e
	pmc = perfctr_cstatus_nractrs(cstatus);
Packit Service a1973e
	nrctrs = perfctr_cstatus_nrctrs(cstatus);
Packit Service a1973e
Packit Service a1973e
	for(pmc_mask = 0; pmc < nrctrs; ++pmc) {
Packit Service a1973e
		if ((int)state->pmc[pmc].start < 0) { /* PPC-specific */
Packit Service a1973e
			/* XXX: "+=" to correct for overshots */
Packit Service a1973e
			state->pmc[pmc].start = state->control.ireset[pmc];
Packit Service a1973e
			pmc_mask |= (1 << pmc);
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
	if (!pmc_mask && (state->ppc_mmcr[0] & MMCR0_TBEE))
Packit Service a1973e
		pmc_mask = (1<<8); /* fake TB bit flip indicator */
Packit Service a1973e
	return pmc_mask;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static inline int check_ireset(const struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int nrctrs, i;
Packit Service a1973e
Packit Service a1973e
	i = state->control.nractrs;
Packit Service a1973e
	nrctrs = i + state->control.nrictrs;
Packit Service a1973e
	for(; i < nrctrs; ++i)
Packit Service a1973e
		if (state->control.ireset[i] < 0)	/* PPC-specific */
Packit Service a1973e
			return -EINVAL;
Packit Service a1973e
	return 0;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static inline void setup_imode_start_values(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int cstatus, nrctrs, i;
Packit Service a1973e
Packit Service a1973e
	cstatus = state->cstatus;
Packit Service a1973e
	nrctrs = perfctr_cstatus_nrctrs(cstatus);
Packit Service a1973e
	for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i)
Packit Service a1973e
		state->pmc[i].start = state->control.ireset[i];
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
#else	/* CONFIG_PERFCTR_INTERRUPT_SUPPORT */
Packit Service a1973e
static inline void perfctr_cpu_isuspend(struct perfctr_cpu_state *state) { }
Packit Service a1973e
static inline void perfctr_cpu_iresume(const struct perfctr_cpu_state *state) { }
Packit Service a1973e
static inline int check_ireset(const struct perfctr_cpu_state *state) { return 0; }
Packit Service a1973e
static inline void setup_imode_start_values(struct perfctr_cpu_state *state) { }
Packit Service a1973e
#endif	/* CONFIG_PERFCTR_INTERRUPT_SUPPORT */
Packit Service a1973e
Packit Service a1973e
static int check_control(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	return ppc_check_control(state);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int perfctr_cpu_update_control(struct perfctr_cpu_state *state, cpumask_t *cpumask)
Packit Service a1973e
{
Packit Service a1973e
	int err;
Packit Service a1973e
Packit Service a1973e
	clear_isuspend_cpu(state);
Packit Service a1973e
	state->cstatus = 0;
Packit Service a1973e
Packit Service a1973e
	/* disallow i-mode counters if we cannot catch the interrupts */
Packit Service a1973e
	if (!(perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
Packit Service a1973e
	    && state->control.nrictrs)
Packit Service a1973e
		return -EPERM;
Packit Service a1973e
Packit Service a1973e
	err = check_ireset(state);
Packit Service a1973e
	if (err < 0)
Packit Service a1973e
		return err;
Packit Service a1973e
	err = check_control(state); /* may initialise state->cstatus */
Packit Service a1973e
	if (err < 0)
Packit Service a1973e
		return err;
Packit Service a1973e
	state->cstatus |= perfctr_mk_cstatus(state->control.tsc_on,
Packit Service a1973e
					     state->control.nractrs,
Packit Service a1973e
					     state->control.nrictrs);
Packit Service a1973e
	setup_imode_start_values(state);
Packit Service a1973e
	return 0;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void perfctr_cpu_suspend(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int i, cstatus, nractrs;
Packit Service a1973e
	struct perfctr_low_ctrs now;
Packit Service a1973e
Packit Service a1973e
	if (perfctr_cstatus_has_mmcr0_quirk(state->cstatus)) {
Packit Service a1973e
		unsigned int mmcr0 = mfspr(SPRN_MMCR0);
Packit Service a1973e
		mtspr(SPRN_MMCR0, mmcr0 | MMCR0_FC);
Packit Service a1973e
		get_cpu_cache()->ppc_mmcr[0] = mmcr0 | MMCR0_FC;
Packit Service a1973e
		state->ppc_mmcr[0] = mmcr0;
Packit Service a1973e
	}
Packit Service a1973e
	if (perfctr_cstatus_has_ictrs(state->cstatus))
Packit Service a1973e
		perfctr_cpu_isuspend(state);
Packit Service a1973e
	perfctr_cpu_read_counters(state, &now;;
Packit Service a1973e
	cstatus = state->cstatus;
Packit Service a1973e
	if (perfctr_cstatus_has_tsc(cstatus))
Packit Service a1973e
		state->tsc_sum += now.tsc - state->tsc_start;
Packit Service a1973e
	nractrs = perfctr_cstatus_nractrs(cstatus);
Packit Service a1973e
	for(i = 0; i < nractrs; ++i)
Packit Service a1973e
		state->pmc[i].sum += now.pmc[i] - state->pmc[i].start;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void perfctr_cpu_resume(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	if (perfctr_cstatus_has_ictrs(state->cstatus))
Packit Service a1973e
	    perfctr_cpu_iresume(state);
Packit Service a1973e
	if (perfctr_cstatus_has_mmcr0_quirk(state->cstatus))
Packit Service a1973e
		get_cpu_cache()->k1.id = 0; /* force reload of MMCR0 */
Packit Service a1973e
	perfctr_cpu_write_control(state);
Packit Service a1973e
	//perfctr_cpu_read_counters(state, &state->start);
Packit Service a1973e
	{
Packit Service a1973e
		struct perfctr_low_ctrs now;
Packit Service a1973e
		unsigned int i, cstatus, nrctrs;
Packit Service a1973e
		perfctr_cpu_read_counters(state, &now;;
Packit Service a1973e
		cstatus = state->cstatus;
Packit Service a1973e
		if (perfctr_cstatus_has_tsc(cstatus))
Packit Service a1973e
			state->tsc_start = now.tsc;
Packit Service a1973e
		nrctrs = perfctr_cstatus_nractrs(cstatus);
Packit Service a1973e
		for(i = 0; i < nrctrs; ++i)
Packit Service a1973e
			state->pmc[i].start = now.pmc[i];
Packit Service a1973e
	}
Packit Service a1973e
	/* XXX: if (SMP && start.tsc == now.tsc) ++now.tsc; */
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void perfctr_cpu_sample(struct perfctr_cpu_state *state)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int i, cstatus, nractrs;
Packit Service a1973e
	struct perfctr_low_ctrs now;
Packit Service a1973e
Packit Service a1973e
	perfctr_cpu_read_counters(state, &now;;
Packit Service a1973e
	cstatus = state->cstatus;
Packit Service a1973e
	if (perfctr_cstatus_has_tsc(cstatus)) {
Packit Service a1973e
		state->tsc_sum += now.tsc - state->tsc_start;
Packit Service a1973e
		state->tsc_start = now.tsc;
Packit Service a1973e
	}
Packit Service a1973e
	nractrs = perfctr_cstatus_nractrs(cstatus);
Packit Service a1973e
	for(i = 0; i < nractrs; ++i) {
Packit Service a1973e
		state->pmc[i].sum += now.pmc[i] - state->pmc[i].start;
Packit Service a1973e
		state->pmc[i].start = now.pmc[i];
Packit Service a1973e
	}
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void perfctr_cpu_clear_counters(void)
Packit Service a1973e
{
Packit Service a1973e
	struct per_cpu_cache *cache;
Packit Service a1973e
Packit Service a1973e
	cache = get_cpu_cache();
Packit Service a1973e
	memset(cache, 0, sizeof *cache);
Packit Service a1973e
	cache->k1.id = -1;
Packit Service a1973e
Packit Service a1973e
	ppc_clear_counters();
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/****************************************************************
Packit Service a1973e
 *								*
Packit Service a1973e
 * Processor detection and initialisation procedures.		*
Packit Service a1973e
 *								*
Packit Service a1973e
 ****************************************************************/
Packit Service a1973e
Packit Service a1973e
/* Derive CPU core frequency from TB frequency and PLL_CFG. */
Packit Service a1973e
Packit Service a1973e
enum pll_type {
Packit Service a1973e
	PLL_NONE,	/* for e.g. 604 which has no HID1[PLL_CFG] */
Packit Service a1973e
	PLL_604e,
Packit Service a1973e
	PLL_750,
Packit Service a1973e
	PLL_750FX,
Packit Service a1973e
	PLL_7400,
Packit Service a1973e
	PLL_7450,
Packit Service a1973e
	PLL_7457,
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
/* These are the known bus-to-core ratios, indexed by PLL_CFG.
Packit Service a1973e
   Multiplied by 2 since half-multiplier steps are present. */
Packit Service a1973e
Packit Service a1973e
static unsigned char cfg_ratio_604e[16] __initdata = { // *2
Packit Service a1973e
	2, 2, 14, 2, 4, 13, 5, 9,
Packit Service a1973e
	6, 11, 8, 10, 3, 12, 7, 0
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
static unsigned char cfg_ratio_750[16] __initdata = { // *2
Packit Service a1973e
	5, 15, 14, 2, 4, 13, 20, 9, // 0b0110 is 18 if L1_TSTCLK=0, but that is abnormal
Packit Service a1973e
	6, 11, 8, 10, 16, 12, 7, 0
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
static unsigned char cfg_ratio_750FX[32] __initdata = { // *2
Packit Service a1973e
	0, 0, 2, 2, 4, 5, 6, 7,
Packit Service a1973e
	8, 9, 10, 11, 12, 13, 14, 15,
Packit Service a1973e
	16, 17, 18, 19, 20, 22, 24, 26,
Packit Service a1973e
	28, 30, 32, 34, 36, 38, 40, 0
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
static unsigned char cfg_ratio_7400[16] __initdata = { // *2
Packit Service a1973e
	18, 15, 14, 2, 4, 13, 5, 9,
Packit Service a1973e
	6, 11, 8, 10, 16, 12, 7, 0
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
static unsigned char cfg_ratio_7450[32] __initdata = { // *2
Packit Service a1973e
	1, 0, 15, 30, 14, 0, 2, 0,
Packit Service a1973e
	4, 0, 13, 26, 5, 0, 9, 18,
Packit Service a1973e
	6, 0, 11, 22, 8, 20, 10, 24,
Packit Service a1973e
	16, 28, 12, 32, 7, 0, 0, 0
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
static unsigned char cfg_ratio_7457[32] __initdata = { // *2
Packit Service a1973e
	23, 34, 15, 30, 14, 36, 2, 40,
Packit Service a1973e
	4, 42, 13, 26, 17, 48, 19, 18,
Packit Service a1973e
	6, 21, 11, 22, 8, 20, 10, 24,
Packit Service a1973e
	16, 28, 12, 32, 27, 56, 0, 25
Packit Service a1973e
};
Packit Service a1973e
Packit Service a1973e
static unsigned int __init pll_tb_to_core(enum pll_type pll_type)
Packit Service a1973e
{
Packit Service a1973e
	unsigned char *cfg_ratio;
Packit Service a1973e
	unsigned int shift = 28, mask = 0xF, hid1, pll_cfg, ratio;
Packit Service a1973e
Packit Service a1973e
	switch (pll_type) {
Packit Service a1973e
	case PLL_604e:
Packit Service a1973e
		cfg_ratio = cfg_ratio_604e;
Packit Service a1973e
		break;
Packit Service a1973e
	case PLL_750:
Packit Service a1973e
		cfg_ratio = cfg_ratio_750;
Packit Service a1973e
		break;
Packit Service a1973e
	case PLL_750FX:
Packit Service a1973e
		cfg_ratio = cfg_ratio_750FX;
Packit Service a1973e
		hid1 = mfspr(SPRN_HID1);
Packit Service a1973e
		switch ((hid1 >> 16) & 0x3) { /* HID1[PI0,PS] */
Packit Service a1973e
		case 0:		/* PLL0 with external config */
Packit Service a1973e
			shift = 31-4;	/* access HID1[PCE] */
Packit Service a1973e
			break;
Packit Service a1973e
		case 2:		/* PLL0 with internal config */
Packit Service a1973e
			shift = 31-20;	/* access HID1[PC0] */
Packit Service a1973e
			break;
Packit Service a1973e
		case 1: case 3:	/* PLL1 */
Packit Service a1973e
			shift = 31-28;	/* access HID1[PC1] */
Packit Service a1973e
			break;
Packit Service a1973e
		}
Packit Service a1973e
		mask = 0x1F;
Packit Service a1973e
		break;
Packit Service a1973e
	case PLL_7400:
Packit Service a1973e
		cfg_ratio = cfg_ratio_7400;
Packit Service a1973e
		break;
Packit Service a1973e
	case PLL_7450:
Packit Service a1973e
		cfg_ratio = cfg_ratio_7450;
Packit Service a1973e
		shift = 12;
Packit Service a1973e
		mask = 0x1F;
Packit Service a1973e
		break;
Packit Service a1973e
	case PLL_7457:
Packit Service a1973e
		cfg_ratio = cfg_ratio_7457;
Packit Service a1973e
		shift = 12;
Packit Service a1973e
		mask = 0x1F;
Packit Service a1973e
		break;
Packit Service a1973e
	default:
Packit Service a1973e
		return 0;
Packit Service a1973e
	}
Packit Service a1973e
	hid1 = mfspr(SPRN_HID1);
Packit Service a1973e
	pll_cfg = (hid1 >> shift) & mask;
Packit Service a1973e
	ratio = cfg_ratio[pll_cfg];
Packit Service a1973e
	if (!ratio)
Packit Service a1973e
		printk(KERN_WARNING "perfctr: unknown PLL_CFG 0x%x\n", pll_cfg);
Packit Service a1973e
	return (4/2) * ratio;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/* Extract core and timebase frequencies from Open Firmware. */
Packit Service a1973e
Packit Service a1973e
#ifdef CONFIG_PPC_OF
Packit Service a1973e
Packit Service a1973e
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
Packit Service a1973e
static inline struct device_node *perfctr_of_find_node_by_type(struct device_node *from, const char *type)
Packit Service a1973e
{
Packit Service a1973e
	return of_find_node_by_type(from, type);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static inline void perfctr_of_node_put(struct device_node *node)
Packit Service a1973e
{
Packit Service a1973e
	of_node_put(node);
Packit Service a1973e
}
Packit Service a1973e
#else
Packit Service a1973e
#define of_get_property(a, b, c)	get_property((a), (b), (c))
Packit Service a1973e
static inline struct device_node *perfctr_of_find_node_by_type(struct device_node *from, const char *type)
Packit Service a1973e
{
Packit Service a1973e
	return find_type_devices(type);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static inline void perfctr_of_node_put(struct device_node *node) { }
Packit Service a1973e
#endif
Packit Service a1973e
Packit Service a1973e
static unsigned int __init of_core_khz(void)
Packit Service a1973e
{
Packit Service a1973e
	struct device_node *cpu;
Packit Service a1973e
	unsigned int *fp, core;
Packit Service a1973e
Packit Service a1973e
	cpu = perfctr_of_find_node_by_type(NULL, "cpu");
Packit Service a1973e
	if (!cpu)
Packit Service a1973e
		return 0;
Packit Service a1973e
	fp = (unsigned int*)of_get_property(cpu, "clock-frequency", NULL);
Packit Service a1973e
	core = 0;
Packit Service a1973e
	if (fp)
Packit Service a1973e
		core = *fp;
Packit Service a1973e
	perfctr_of_node_put(cpu);
Packit Service a1973e
	return core / 1000;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static unsigned int __init of_bus_khz(void)
Packit Service a1973e
{
Packit Service a1973e
	struct device_node *cpu;
Packit Service a1973e
	unsigned int *fp, bus;
Packit Service a1973e
Packit Service a1973e
	cpu = perfctr_of_find_node_by_type(NULL, "cpu");
Packit Service a1973e
	if (!cpu)
Packit Service a1973e
		return 0;
Packit Service a1973e
	fp = (unsigned int*)of_get_property(cpu, "bus-frequency", NULL);
Packit Service a1973e
	bus = 0;
Packit Service a1973e
	if (!fp || !(bus = *fp)) {
Packit Service a1973e
		fp = (unsigned int*)of_get_property(cpu, "config-bus-frequency", NULL);
Packit Service a1973e
		if (fp)
Packit Service a1973e
			bus = *fp;
Packit Service a1973e
	}
Packit Service a1973e
	perfctr_of_node_put(cpu);
Packit Service a1973e
	return bus / 1000;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static unsigned int __init of_bus_to_core_x2(void)
Packit Service a1973e
{
Packit Service a1973e
	struct device_node *cpu;
Packit Service a1973e
	unsigned int *fp, ratio;
Packit Service a1973e
Packit Service a1973e
	cpu = perfctr_of_find_node_by_type(NULL, "cpu");
Packit Service a1973e
	if (!cpu)
Packit Service a1973e
		return 0;
Packit Service a1973e
	fp = (unsigned int*)of_get_property(cpu, "processor-to-bus-ratio*2", NULL);
Packit Service a1973e
	ratio = 0;
Packit Service a1973e
	if (fp)
Packit Service a1973e
		ratio = *fp;
Packit Service a1973e
	perfctr_of_node_put(cpu);
Packit Service a1973e
	return ratio;
Packit Service a1973e
}
Packit Service a1973e
#else
Packit Service a1973e
static inline unsigned int of_core_khz(void) { return 0; }
Packit Service a1973e
static inline unsigned int of_bus_khz(void) { return 0; }
Packit Service a1973e
static inline unsigned int of_bus_to_core_x2(void) { return 0; }
Packit Service a1973e
#endif
Packit Service a1973e
Packit Service a1973e
static unsigned int __init detect_tb_khz(unsigned int bus_khz, unsigned int tb_to_bus)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int tb_khz, bus_tb_khz, diff;
Packit Service a1973e
Packit Service a1973e
	tb_khz = tb_ticks_per_jiffy * (HZ/10) / (1000/10);
Packit Service a1973e
	if (bus_khz && tb_to_bus) {
Packit Service a1973e
		bus_tb_khz = bus_khz / tb_to_bus;
Packit Service a1973e
		if (bus_tb_khz > tb_khz)
Packit Service a1973e
			diff = bus_tb_khz - tb_khz;
Packit Service a1973e
		else
Packit Service a1973e
			diff = tb_khz - bus_tb_khz;
Packit Service a1973e
		if (diff >= bus_tb_khz/20) {
Packit Service a1973e
			printk(KERN_WARNING "perfctr: timebase frequency %u kHz seems"
Packit Service a1973e
			       " out of range, using %u kHz (bus/%u) instead\n",
Packit Service a1973e
			       tb_khz, bus_tb_khz, tb_to_bus);
Packit Service a1973e
			return bus_tb_khz;
Packit Service a1973e
		}
Packit Service a1973e
	}
Packit Service a1973e
	return tb_khz;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static unsigned int __init detect_tb_to_core(enum pll_type pll_type, unsigned int tb_to_bus)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int tb_to_core;
Packit Service a1973e
	unsigned int bus_to_core_x2;
Packit Service a1973e
Packit Service a1973e
	tb_to_core = pll_tb_to_core(pll_type);
Packit Service a1973e
	if (tb_to_core)
Packit Service a1973e
		return tb_to_core;
Packit Service a1973e
	if (tb_to_bus) {
Packit Service a1973e
		bus_to_core_x2 = of_bus_to_core_x2();
Packit Service a1973e
		if (bus_to_core_x2)
Packit Service a1973e
			return (tb_to_bus * bus_to_core_x2) / 2;
Packit Service a1973e
	}
Packit Service a1973e
	return 0;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static unsigned int __init detect_core_khz(unsigned int tb_khz, unsigned int tb_to_core)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int core_khz;
Packit Service a1973e
Packit Service a1973e
	if (tb_to_core) {
Packit Service a1973e
		perfctr_info.tsc_to_cpu_mult = tb_to_core;
Packit Service a1973e
		return tb_khz * tb_to_core;
Packit Service a1973e
	}
Packit Service a1973e
	core_khz = of_core_khz();
Packit Service a1973e
	perfctr_info.tsc_to_cpu_mult = core_khz / tb_khz;
Packit Service a1973e
	return core_khz;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/*
Packit Service a1973e
 * Detect the timebase and core clock frequencies.
Packit Service a1973e
 *
Packit Service a1973e
 * Known issues:
Packit Service a1973e
 * 1. The OF timebase-frequency property is sometimes way off, and
Packit Service a1973e
 *    similarly the ppc32 kernel's tb_ticks_per_jiffy variable.
Packit Service a1973e
 *    (Observed on a 7447A-based laptop.)
Packit Service a1973e
 *    Workaround: Compute the TB frequency from the bus frequency
Packit Service a1973e
 *    and the TB-to-bus ratio.
Packit Service a1973e
 * 2. The OF clock-frequency property is sometimes wrong.
Packit Service a1973e
 *    (Observed on a Beige G3 with a 7455 upgrade processor.)
Packit Service a1973e
 *    Workaround: Compute the core frequency from the TB frequency
Packit Service a1973e
 *    and the TB-to-core ratio.
Packit Service a1973e
 * 3. The PLL_CFG details may be unknown.
Packit Service a1973e
 */
Packit Service a1973e
static unsigned int __init detect_cpu_khz(enum pll_type pll_type, unsigned int tb_to_bus)
Packit Service a1973e
{
Packit Service a1973e
	unsigned int bus_khz;
Packit Service a1973e
	unsigned int tb_khz;
Packit Service a1973e
	unsigned int tb_to_core;
Packit Service a1973e
	unsigned int core_khz;
Packit Service a1973e
Packit Service a1973e
	bus_khz = of_bus_khz();
Packit Service a1973e
	tb_khz = detect_tb_khz(bus_khz, tb_to_bus);
Packit Service a1973e
	tb_to_core = detect_tb_to_core(pll_type, tb_to_bus);
Packit Service a1973e
	core_khz = detect_core_khz(tb_khz, tb_to_core);
Packit Service a1973e
	if (!core_khz)
Packit Service a1973e
		printk(KERN_WARNING "perfctr: unable to determine CPU speed\n");
Packit Service a1973e
	return core_khz;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int __init known_init(void)
Packit Service a1973e
{
Packit Service a1973e
	static char known_name[] __initdata = "PowerPC 60x/7xx/74xx";
Packit Service a1973e
	unsigned int features;
Packit Service a1973e
	enum pll_type pll_type;
Packit Service a1973e
	unsigned int pvr;
Packit Service a1973e
	int have_mmcr1;
Packit Service a1973e
	unsigned int tb_to_bus;
Packit Service a1973e
Packit Service a1973e
	tb_to_bus = 4; /* default, overridden below if necessary */
Packit Service a1973e
	features = PERFCTR_FEATURE_RDTSC | PERFCTR_FEATURE_RDPMC;
Packit Service a1973e
	have_mmcr1 = 1;
Packit Service a1973e
	pvr = mfspr(SPRN_PVR);
Packit Service a1973e
	switch (PVR_VER(pvr)) {
Packit Service a1973e
	case 0x0004: /* 604 */
Packit Service a1973e
		pm_type = PM_604;
Packit Service a1973e
		pll_type = PLL_NONE;
Packit Service a1973e
		features = PERFCTR_FEATURE_RDTSC;
Packit Service a1973e
		have_mmcr1 = 0;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x0009: /* 604e;  */
Packit Service a1973e
	case 0x000A: /* 604ev */
Packit Service a1973e
		pm_type = PM_604e;
Packit Service a1973e
		pll_type = PLL_604e;
Packit Service a1973e
		features = PERFCTR_FEATURE_RDTSC;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x0008: /* 750/740 */
Packit Service a1973e
		pm_type = PM_750;
Packit Service a1973e
		pll_type = PLL_750;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x7000: case 0x7001: /* IBM750FX */
Packit Service a1973e
		if ((pvr & 0xFF0F) >= 0x0203)
Packit Service a1973e
			features |= PERFCTR_FEATURE_PCINT;
Packit Service a1973e
		pm_type = PM_750;
Packit Service a1973e
		pll_type = PLL_750FX;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x7002: /* IBM750GX */
Packit Service a1973e
		features |= PERFCTR_FEATURE_PCINT;
Packit Service a1973e
		pm_type = PM_750;
Packit Service a1973e
		pll_type = PLL_750FX;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x000C: /* 7400 */
Packit Service a1973e
		pm_type = PM_7400;
Packit Service a1973e
		pll_type = PLL_7400;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x800C: /* 7410 */
Packit Service a1973e
		if ((pvr & 0xFFFF) >= 0x1103)
Packit Service a1973e
			features |= PERFCTR_FEATURE_PCINT;
Packit Service a1973e
		pm_type = PM_7400;
Packit Service a1973e
		pll_type = PLL_7400;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x8000: /* 7451/7441 */
Packit Service a1973e
		features |= PERFCTR_FEATURE_PCINT;
Packit Service a1973e
		pm_type = PM_7450;
Packit Service a1973e
		pll_type = PLL_7450;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x8001: /* 7455/7445 */
Packit Service a1973e
		features |= PERFCTR_FEATURE_PCINT;
Packit Service a1973e
		pm_type = PM_7450;
Packit Service a1973e
		pll_type = ((pvr & 0xFFFF) < 0x0303) ? PLL_7450 : PLL_7457;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x8002: /* 7457/7447 */
Packit Service a1973e
	case 0x8003: /* 7447A */
Packit Service a1973e
		features |= PERFCTR_FEATURE_PCINT;
Packit Service a1973e
		pm_type = PM_7450;
Packit Service a1973e
		pll_type = PLL_7457;
Packit Service a1973e
		break;
Packit Service a1973e
	case 0x8004: /* 7448 */
Packit Service a1973e
		features |= PERFCTR_FEATURE_PCINT;
Packit Service a1973e
		pm_type = PM_7450;
Packit Service a1973e
		pll_type = PLL_NONE; /* known to differ from 7447A, no details yet */
Packit Service a1973e
		break;
Packit Service a1973e
	default:
Packit Service a1973e
		return -ENODEV;
Packit Service a1973e
	}
Packit Service a1973e
	perfctr_info.cpu_features = features;
Packit Service a1973e
	perfctr_info.cpu_type = 0; /* user-space should inspect PVR */
Packit Service a1973e
	perfctr_cpu_name = known_name;
Packit Service a1973e
	perfctr_info.cpu_khz = detect_cpu_khz(pll_type, tb_to_bus);
Packit Service a1973e
	perfctr_ppc_init_tests(have_mmcr1);
Packit Service a1973e
	return 0;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static int __init unknown_init(void)
Packit Service a1973e
{
Packit Service a1973e
	static char unknown_name[] __initdata = "Generic PowerPC with TB";
Packit Service a1973e
	unsigned int khz;
Packit Service a1973e
Packit Service a1973e
	khz = detect_cpu_khz(PLL_NONE, 0);
Packit Service a1973e
	if (!khz)
Packit Service a1973e
		return -ENODEV;
Packit Service a1973e
	perfctr_info.cpu_features = PERFCTR_FEATURE_RDTSC;
Packit Service a1973e
	perfctr_info.cpu_type = 0;
Packit Service a1973e
	perfctr_cpu_name = unknown_name;
Packit Service a1973e
	perfctr_info.cpu_khz = khz;
Packit Service a1973e
	pm_type = PM_NONE;
Packit Service a1973e
	return 0;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void perfctr_cpu_clear_one(void *ignore)
Packit Service a1973e
{
Packit Service a1973e
	/* PREEMPT note: when called via on_each_cpu(),
Packit Service a1973e
	   this is in IRQ context with preemption disabled. */
Packit Service a1973e
	perfctr_cpu_clear_counters();
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
static void perfctr_cpu_reset(void)
Packit Service a1973e
{
Packit Service a1973e
	on_each_cpu(perfctr_cpu_clear_one, NULL, 1);
Packit Service a1973e
	perfctr_cpu_set_ihandler(NULL);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int __init perfctr_cpu_init(void)
Packit Service a1973e
{
Packit Service a1973e
	int err;
Packit Service a1973e
Packit Service a1973e
	perfctr_info.cpu_features = 0;
Packit Service a1973e
Packit Service a1973e
	err = known_init();
Packit Service a1973e
	if (err) {
Packit Service a1973e
		err = unknown_init();
Packit Service a1973e
		if (err)
Packit Service a1973e
			goto out;
Packit Service a1973e
	}
Packit Service a1973e
Packit Service a1973e
 out:
Packit Service a1973e
	return err;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void __exit perfctr_cpu_exit(void)
Packit Service a1973e
{
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
/****************************************************************
Packit Service a1973e
 *								*
Packit Service a1973e
 * Hardware reservation.					*
Packit Service a1973e
 *								*
Packit Service a1973e
 ****************************************************************/
Packit Service a1973e
Packit Service a1973e
static DEFINE_MUTEX(mutex);
Packit Service a1973e
static const char *current_service = 0;
Packit Service a1973e
Packit Service a1973e
const char *perfctr_cpu_reserve(const char *service)
Packit Service a1973e
{
Packit Service a1973e
	const char *ret;
Packit Service a1973e
Packit Service a1973e
	mutex_lock(&mutex);
Packit Service a1973e
	ret = current_service;
Packit Service a1973e
	if (ret)
Packit Service a1973e
		goto out_unlock;
Packit Service a1973e
	ret = "unknown driver (oprofile?)";
Packit Service a1973e
	if (perfctr_reserve_pmc_hardware() < 0)
Packit Service a1973e
		goto out_unlock;
Packit Service a1973e
	current_service = service;
Packit Service a1973e
	__module_get(THIS_MODULE);
Packit Service a1973e
	perfctr_cpu_reset();
Packit Service a1973e
	ret = NULL;
Packit Service a1973e
 out_unlock:
Packit Service a1973e
	mutex_unlock(&mutex);
Packit Service a1973e
	return ret;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
void perfctr_cpu_release(const char *service)
Packit Service a1973e
{
Packit Service a1973e
	mutex_lock(&mutex);
Packit Service a1973e
	if (service != current_service) {
Packit Service a1973e
		printk(KERN_ERR "%s: attempt by %s to release while reserved by %s\n",
Packit Service a1973e
		       __FUNCTION__, service, current_service);
Packit Service a1973e
	} else {
Packit Service a1973e
		/* power down the counters */
Packit Service a1973e
		perfctr_cpu_reset();
Packit Service a1973e
		current_service = 0;
Packit Service a1973e
		perfctr_release_pmc_hardware();
Packit Service a1973e
		module_put(THIS_MODULE);
Packit Service a1973e
	}
Packit Service a1973e
	mutex_unlock(&mutex);
Packit Service a1973e
}