From: Zwane Mwaikambo <zwane@arm.linux.org.uk>

The incorrect mask was being used when writing back to PMNC write-only-zero
bits as well as only ticking the CCNT every 64 processor cycles.  Tested on
IOP331 and PXA270, i'm still looking for XScale1 users...

Signed-off-by: Luca Rossato <l.rossato@tiscali.it>
Signed-off-by: Zwane Mwaikambo <zwane@arm.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/arm/oprofile/op_model_xscale.c |   21 +++++++++++++++------
 1 files changed, 15 insertions(+), 6 deletions(-)

diff -puN arch/arm/oprofile/op_model_xscale.c~oprofile-xscale-fixes-for-pxa270-xscale2 arch/arm/oprofile/op_model_xscale.c
--- 25/arch/arm/oprofile/op_model_xscale.c~oprofile-xscale-fixes-for-pxa270-xscale2	2004-08-07 22:12:30.025443600 -0700
+++ 25-akpm/arch/arm/oprofile/op_model_xscale.c	2004-08-07 22:12:30.028443144 -0700
@@ -30,6 +30,7 @@
 #define PMN_RESET	0x002	/* Reset event counters */
 #define	CCNT_RESET	0x004	/* Reset clock counter */
 #define	PMU_RESET	(CCNT_RESET | PMN_RESET)
+#define PMU_CNT64	0x008	/* Make CCNT count every 64th cycle */
 
 /* TODO do runtime detection */
 #ifdef CONFIG_ARCH_IOP310
@@ -125,12 +126,15 @@ static struct pmu_type *pmu;
 
 static void write_pmnc(u32 val)
 {
-	/* upper 4bits and 7, 11 are write-as-0 */
-	val &= 0xffff77f;
-	if (pmu->id == PMU_XSC1)
+	if (pmu->id == PMU_XSC1) {
+		/* upper 4bits and 7, 11 are write-as-0 */
+		val &= 0xffff77f;
 		__asm__ __volatile__ ("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
-	else
+	} else {
+		/* bits 4-23 are write-as-0, 24-31 are write ignored */
+		val &= 0xf;
 		__asm__ __volatile__ ("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
+	}
 }
 
 static u32 read_pmnc(void)
@@ -139,8 +143,11 @@ static u32 read_pmnc(void)
 
 	if (pmu->id == PMU_XSC1)
 		__asm__ __volatile__ ("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
-	else
+	else {
 		__asm__ __volatile__ ("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
+		/* bits 1-2 and 4-23 are read-unpredictable */
+		val &= 0xff000009;
+	}
 
 	return val;
 }
@@ -386,8 +393,10 @@ static int xscale_pmu_start(void)
 
 	if (pmu->id == PMU_XSC1)
 		pmnc |= pmu->int_enable;
-	else
+	else {
 		__asm__ __volatile__ ("mcr p14, 0, %0, c4, c1, 0" : : "r" (pmu->int_enable));
+		pmnc &= ~PMU_CNT64;
+	}
 
 	pmnc |= PMU_ENABLE;
 	write_pmnc(pmnc);
_