diff options
| author | Greg Ungerer <gerg@snapgear.com> | 2006-06-25 20:33:10 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 20:43:33 -0400 |
| commit | 0b7ac8e479f311f8ef15fbea3f849dded9f3ccd9 (patch) | |
| tree | d84b81667b7db390d704137b40903e5079f05e53 | |
| parent | c88b36e2c828c78c51e90002351f9d9068b75dec (diff) | |
[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 <gerg@uclinux.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | arch/m68knommu/platform/5307/timers.c | 49 | ||||
| -rw-r--r-- | 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 @@ | |||
| 14 | #include <linux/param.h> | 14 | #include <linux/param.h> |
| 15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <asm/io.h> | ||
| 17 | #include <asm/irq.h> | 18 | #include <asm/irq.h> |
| 18 | #include <asm/traps.h> | 19 | #include <asm/traps.h> |
| 19 | #include <asm/machdep.h> | 20 | #include <asm/machdep.h> |
| @@ -24,6 +25,11 @@ | |||
| 24 | /***************************************************************************/ | 25 | /***************************************************************************/ |
| 25 | 26 | ||
| 26 | /* | 27 | /* |
| 28 | * By default use timer1 as the system clock timer. | ||
| 29 | */ | ||
| 30 | #define TA(a) (MCF_MBAR + MCFTIMER_BASE1 + (a)) | ||
| 31 | |||
| 32 | /* | ||
| 27 | * Default the timer and vector to use for ColdFire. Some ColdFire | 33 | * Default the timer and vector to use for ColdFire. Some ColdFire |
| 28 | * CPU's and some boards may want different. Their sub-architecture | 34 | * CPU's and some boards may want different. Their sub-architecture |
| 29 | * startup code (in config.c) can change these if they want. | 35 | * startup code (in config.c) can change these if they want. |
| @@ -32,8 +38,6 @@ unsigned int mcf_timervector = 29; | |||
| 32 | unsigned int mcf_profilevector = 31; | 38 | unsigned int mcf_profilevector = 31; |
| 33 | unsigned int mcf_timerlevel = 5; | 39 | unsigned int mcf_timerlevel = 5; |
| 34 | 40 | ||
| 35 | static volatile struct mcftimer *mcf_timerp; | ||
| 36 | |||
| 37 | /* | 41 | /* |
| 38 | * These provide the underlying interrupt vector support. | 42 | * These provide the underlying interrupt vector support. |
| 39 | * Unfortunately it is a little different on each ColdFire. | 43 | * Unfortunately it is a little different on each ColdFire. |
| @@ -46,20 +50,17 @@ extern int mcf_timerirqpending(int timer); | |||
| 46 | void coldfire_tick(void) | 50 | void coldfire_tick(void) |
| 47 | { | 51 | { |
| 48 | /* Reset the ColdFire timer */ | 52 | /* Reset the ColdFire timer */ |
| 49 | mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; | 53 | __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER)); |
| 50 | } | 54 | } |
| 51 | 55 | ||
| 52 | /***************************************************************************/ | 56 | /***************************************************************************/ |
| 53 | 57 | ||
| 54 | void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) | 58 | void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) |
| 55 | { | 59 | { |
| 56 | /* Set up an internal TIMER as poll clock */ | 60 | __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR)); |
| 57 | mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1); | 61 | __raw_writew(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR)); |
| 58 | mcf_timerp->tmr = MCFTIMER_TMR_DISABLE; | 62 | __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | |
| 59 | 63 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR)); | |
| 60 | mcf_timerp->trr = (unsigned short) ((MCF_BUSCLK / 16) / HZ); | ||
| 61 | mcf_timerp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | | ||
| 62 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; | ||
| 63 | 64 | ||
| 64 | request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL); | 65 | request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL); |
| 65 | mcf_settimericr(1, mcf_timerlevel); | 66 | mcf_settimericr(1, mcf_timerlevel); |
| @@ -75,13 +76,8 @@ unsigned long coldfire_timer_offset(void) | |||
| 75 | { | 76 | { |
| 76 | unsigned long trr, tcn, offset; | 77 | unsigned long trr, tcn, offset; |
| 77 | 78 | ||
| 78 | /* | 79 | tcn = __raw_readw(TA(MCFTIMER_TCN)); |
| 79 | * The change to pointer and de-reference is to force the compiler | 80 | trr = __raw_readw(TA(MCFTIMER_TRR)); |
| 80 | * to read the registers with a single 16bit access. Otherwise it | ||
| 81 | * does some crazy 8bit read combining. | ||
| 82 | */ | ||
| 83 | tcn = *(&mcf_timerp->tcn); | ||
| 84 | trr = *(&mcf_timerp->trr); | ||
| 85 | offset = (tcn * (1000000 / HZ)) / trr; | 81 | offset = (tcn * (1000000 / HZ)) / trr; |
| 86 | 82 | ||
| 87 | /* Check if we just wrapped the counters and maybe missed a tick */ | 83 | /* Check if we just wrapped the counters and maybe missed a tick */ |
| @@ -95,21 +91,23 @@ unsigned long coldfire_timer_offset(void) | |||
| 95 | /***************************************************************************/ | 91 | /***************************************************************************/ |
| 96 | 92 | ||
| 97 | /* | 93 | /* |
| 94 | * By default use timer2 as the profiler clock timer. | ||
| 95 | */ | ||
| 96 | #define PA(a) (MCF_MBAR + MCFTIMER_BASE2 + (a)) | ||
| 97 | |||
| 98 | /* | ||
| 98 | * Choose a reasonably fast profile timer. Make it an odd value to | 99 | * Choose a reasonably fast profile timer. Make it an odd value to |
| 99 | * try and get good coverage of kernal operations. | 100 | * try and get good coverage of kernal operations. |
| 100 | */ | 101 | */ |
| 101 | #define PROFILEHZ 1013 | 102 | #define PROFILEHZ 1013 |
| 102 | 103 | ||
| 103 | static volatile struct mcftimer *mcf_proftp; | ||
| 104 | |||
| 105 | /* | 104 | /* |
| 106 | * Use the other timer to provide high accuracy profiling info. | 105 | * Use the other timer to provide high accuracy profiling info. |
| 107 | */ | 106 | */ |
| 108 | |||
| 109 | void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) | 107 | void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) |
| 110 | { | 108 | { |
| 111 | /* Reset ColdFire timer2 */ | 109 | /* Reset ColdFire timer2 */ |
| 112 | mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; | 110 | __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER)); |
| 113 | if (current->pid) | 111 | if (current->pid) |
| 114 | profile_tick(CPU_PROFILING, regs); | 112 | profile_tick(CPU_PROFILING, regs); |
| 115 | } | 113 | } |
| @@ -121,12 +119,11 @@ void coldfire_profile_init(void) | |||
| 121 | printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ); | 119 | printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ); |
| 122 | 120 | ||
| 123 | /* Set up TIMER 2 as high speed profile clock */ | 121 | /* Set up TIMER 2 as high speed profile clock */ |
| 124 | mcf_proftp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE2); | 122 | __raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR)); |
| 125 | mcf_proftp->tmr = MCFTIMER_TMR_DISABLE; | ||
| 126 | 123 | ||
| 127 | mcf_proftp->trr = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); | 124 | __raw_writew(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); |
| 128 | mcf_proftp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | | 125 | __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | |
| 129 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; | 126 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR)); |
| 130 | 127 | ||
| 131 | request_irq(mcf_profilevector, coldfire_profile_tick, | 128 | request_irq(mcf_profilevector, coldfire_profile_tick, |
| 132 | (SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL); | 129 | (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 @@ | |||
| 3 | /* | 3 | /* |
| 4 | * mcftimer.h -- ColdFire internal TIMER support defines. | 4 | * mcftimer.h -- ColdFire internal TIMER support defines. |
| 5 | * | 5 | * |
| 6 | * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com) | 6 | * (C) Copyright 1999-2006, Greg Ungerer <gerg@snapgear.com> |
| 7 | * (C) Copyright 2000, Lineo Inc. (www.lineo.com) | 7 | * (C) Copyright 2000, Lineo Inc. (www.lineo.com) |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| @@ -27,6 +27,11 @@ | |||
| 27 | #elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) | 27 | #elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) |
| 28 | #define MCFTIMER_BASE1 0x140 /* Base address of TIMER1 */ | 28 | #define MCFTIMER_BASE1 0x140 /* Base address of TIMER1 */ |
| 29 | #define MCFTIMER_BASE2 0x180 /* Base address of TIMER2 */ | 29 | #define MCFTIMER_BASE2 0x180 /* Base address of TIMER2 */ |
| 30 | #elif defined(CONFIG_M532x) | ||
| 31 | #define MCFTIMER_BASE1 0xfc070000 /* Base address of TIMER1 */ | ||
| 32 | #define MCFTIMER_BASE2 0xfc074000 /* Base address of TIMER2 */ | ||
| 33 | #define MCFTIMER_BASE3 0xfc078000 /* Base address of TIMER3 */ | ||
| 34 | #define MCFTIMER_BASE4 0xfc07c000 /* Base address of TIMER4 */ | ||
| 30 | #endif | 35 | #endif |
| 31 | 36 | ||
| 32 | 37 | ||
| @@ -34,23 +39,14 @@ | |||
| 34 | * Define the TIMER register set addresses. | 39 | * Define the TIMER register set addresses. |
| 35 | */ | 40 | */ |
| 36 | #define MCFTIMER_TMR 0x00 /* Timer Mode reg (r/w) */ | 41 | #define MCFTIMER_TMR 0x00 /* Timer Mode reg (r/w) */ |
| 37 | #define MCFTIMER_TRR 0x02 /* Timer Reference (r/w) */ | 42 | #define MCFTIMER_TRR 0x04 /* Timer Reference (r/w) */ |
| 38 | #define MCFTIMER_TCR 0x04 /* Timer Capture reg (r/w) */ | 43 | #define MCFTIMER_TCR 0x08 /* Timer Capture reg (r/w) */ |
| 39 | #define MCFTIMER_TCN 0x06 /* Timer Counter reg (r/w) */ | 44 | #define MCFTIMER_TCN 0x0C /* Timer Counter reg (r/w) */ |
| 45 | #if defined(CONFIG_M532x) | ||
| 46 | #define MCFTIMER_TER 0x03 /* Timer Event reg (r/w) */ | ||
| 47 | #else | ||
| 40 | #define MCFTIMER_TER 0x11 /* Timer Event reg (r/w) */ | 48 | #define MCFTIMER_TER 0x11 /* Timer Event reg (r/w) */ |
| 41 | 49 | #endif | |
| 42 | struct mcftimer { | ||
| 43 | unsigned short tmr; /* Timer Mode reg (r/w) */ | ||
| 44 | unsigned short reserved1; | ||
| 45 | unsigned short trr; /* Timer Reference (r/w) */ | ||
| 46 | unsigned short reserved2; | ||
| 47 | unsigned short tcr; /* Timer Capture reg (r/w) */ | ||
| 48 | unsigned short reserved3; | ||
| 49 | unsigned short tcn; /* Timer Counter reg (r/w) */ | ||
| 50 | unsigned short reserved4; | ||
| 51 | unsigned char reserved5; | ||
| 52 | unsigned char ter; /* Timer Event reg (r/w) */ | ||
| 53 | } __attribute__((packed)); | ||
| 54 | 50 | ||
| 55 | /* | 51 | /* |
| 56 | * Bit definitions for the Timer Mode Register (TMR). | 52 | * Bit definitions for the Timer Mode Register (TMR). |
