From 0b7ac8e479f311f8ef15fbea3f849dded9f3ccd9 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 26 Jun 2006 10:33:10 +1000 Subject: [PATCH] [PATCH] m68knommu: read/write register access for ColdFire core timer Modify the m68knommu/ColdFire core timer code to use register offsets with raw_read/raw_write access, instead of a mapped struct. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- arch/m68knommu/platform/5307/timers.c | 49 +++++++++++++-------------- include/asm-m68knommu/mcftimer.h | 30 +++++++--------- 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c index ef49596aa09c..83b8b89dfa09 100644 --- a/arch/m68knommu/platform/5307/timers.c +++ b/arch/m68knommu/platform/5307/timers.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,11 @@ /***************************************************************************/ +/* + * By default use timer1 as the system clock timer. + */ +#define TA(a) (MCF_MBAR + MCFTIMER_BASE1 + (a)) + /* * Default the timer and vector to use for ColdFire. Some ColdFire * CPU's and some boards may want different. Their sub-architecture @@ -32,8 +38,6 @@ unsigned int mcf_timervector = 29; unsigned int mcf_profilevector = 31; unsigned int mcf_timerlevel = 5; -static volatile struct mcftimer *mcf_timerp; - /* * These provide the underlying interrupt vector support. * Unfortunately it is a little different on each ColdFire. @@ -46,20 +50,17 @@ extern int mcf_timerirqpending(int timer); void coldfire_tick(void) { /* Reset the ColdFire timer */ - mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; + __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER)); } /***************************************************************************/ void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) { - /* Set up an internal TIMER as poll clock */ - mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1); - mcf_timerp->tmr = MCFTIMER_TMR_DISABLE; - - mcf_timerp->trr = (unsigned short) ((MCF_BUSCLK / 16) / HZ); - mcf_timerp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR)); + __raw_writew(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR)); + __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR)); request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL); mcf_settimericr(1, mcf_timerlevel); @@ -75,13 +76,8 @@ unsigned long coldfire_timer_offset(void) { unsigned long trr, tcn, offset; - /* - * The change to pointer and de-reference is to force the compiler - * to read the registers with a single 16bit access. Otherwise it - * does some crazy 8bit read combining. - */ - tcn = *(&mcf_timerp->tcn); - trr = *(&mcf_timerp->trr); + tcn = __raw_readw(TA(MCFTIMER_TCN)); + trr = __raw_readw(TA(MCFTIMER_TRR)); offset = (tcn * (1000000 / HZ)) / trr; /* Check if we just wrapped the counters and maybe missed a tick */ @@ -94,22 +90,24 @@ unsigned long coldfire_timer_offset(void) #ifdef CONFIG_HIGHPROFILE /***************************************************************************/ +/* + * By default use timer2 as the profiler clock timer. + */ +#define PA(a) (MCF_MBAR + MCFTIMER_BASE2 + (a)) + /* * Choose a reasonably fast profile timer. Make it an odd value to * try and get good coverage of kernal operations. */ #define PROFILEHZ 1013 -static volatile struct mcftimer *mcf_proftp; - /* * Use the other timer to provide high accuracy profiling info. */ - void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) { /* Reset ColdFire timer2 */ - mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; + __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER)); if (current->pid) profile_tick(CPU_PROFILING, regs); } @@ -121,12 +119,11 @@ void coldfire_profile_init(void) printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ); /* Set up TIMER 2 as high speed profile clock */ - mcf_proftp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE2); - mcf_proftp->tmr = MCFTIMER_TMR_DISABLE; + __raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR)); - mcf_proftp->trr = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); - mcf_proftp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + __raw_writew(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); + __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR)); request_irq(mcf_profilevector, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL); diff --git a/include/asm-m68knommu/mcftimer.h b/include/asm-m68knommu/mcftimer.h index 68bf33ac10d1..6f4d796e03db 100644 --- a/include/asm-m68knommu/mcftimer.h +++ b/include/asm-m68knommu/mcftimer.h @@ -3,7 +3,7 @@ /* * mcftimer.h -- ColdFire internal TIMER support defines. * - * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com) + * (C) Copyright 1999-2006, Greg Ungerer * (C) Copyright 2000, Lineo Inc. (www.lineo.com) */ @@ -27,6 +27,11 @@ #elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) #define MCFTIMER_BASE1 0x140 /* Base address of TIMER1 */ #define MCFTIMER_BASE2 0x180 /* Base address of TIMER2 */ +#elif defined(CONFIG_M532x) +#define MCFTIMER_BASE1 0xfc070000 /* Base address of TIMER1 */ +#define MCFTIMER_BASE2 0xfc074000 /* Base address of TIMER2 */ +#define MCFTIMER_BASE3 0xfc078000 /* Base address of TIMER3 */ +#define MCFTIMER_BASE4 0xfc07c000 /* Base address of TIMER4 */ #endif @@ -34,23 +39,14 @@ * Define the TIMER register set addresses. */ #define MCFTIMER_TMR 0x00 /* Timer Mode reg (r/w) */ -#define MCFTIMER_TRR 0x02 /* Timer Reference (r/w) */ -#define MCFTIMER_TCR 0x04 /* Timer Capture reg (r/w) */ -#define MCFTIMER_TCN 0x06 /* Timer Counter reg (r/w) */ +#define MCFTIMER_TRR 0x04 /* Timer Reference (r/w) */ +#define MCFTIMER_TCR 0x08 /* Timer Capture reg (r/w) */ +#define MCFTIMER_TCN 0x0C /* Timer Counter reg (r/w) */ +#if defined(CONFIG_M532x) +#define MCFTIMER_TER 0x03 /* Timer Event reg (r/w) */ +#else #define MCFTIMER_TER 0x11 /* Timer Event reg (r/w) */ - -struct mcftimer { - unsigned short tmr; /* Timer Mode reg (r/w) */ - unsigned short reserved1; - unsigned short trr; /* Timer Reference (r/w) */ - unsigned short reserved2; - unsigned short tcr; /* Timer Capture reg (r/w) */ - unsigned short reserved3; - unsigned short tcn; /* Timer Counter reg (r/w) */ - unsigned short reserved4; - unsigned char reserved5; - unsigned char ter; /* Timer Event reg (r/w) */ -} __attribute__((packed)); +#endif /* * Bit definitions for the Timer Mode Register (TMR).