diff options
author | Greg Ungerer <gerg@snapgear.com> | 2008-02-01 02:40:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 05:02:03 -0500 |
commit | 8d80c5ee9c1e5bc3b72d69591101c2715a7e7fdd (patch) | |
tree | fcc63bb81d8b3a253fba5a3de0974488994dc35b /arch | |
parent | 36a90f26aa24c58e5279786340beb9f5bea39361 (diff) |
m68knommu: switch ColdFire PIT timer to use GENERIC_TIME
Switch the ColdFire PIT timer to using GENERIC_TIME.
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/m68knommu/platform/coldfire/pit.c | 86 |
1 files changed, 51 insertions, 35 deletions
diff --git a/arch/m68knommu/platform/coldfire/pit.c b/arch/m68knommu/platform/coldfire/pit.c index 173b754d1cda..4290638012e0 100644 --- a/arch/m68knommu/platform/coldfire/pit.c +++ b/arch/m68knommu/platform/coldfire/pit.c | |||
@@ -3,9 +3,10 @@ | |||
3 | /* | 3 | /* |
4 | * pit.c -- Freescale ColdFire PIT timer. Currently this type of | 4 | * pit.c -- Freescale ColdFire PIT timer. Currently this type of |
5 | * hardware timer only exists in the Freescale ColdFire | 5 | * hardware timer only exists in the Freescale ColdFire |
6 | * 5270/5271, 5282 and other CPUs. | 6 | * 5270/5271, 5282 and 5208 CPUs. No doubt newer ColdFire |
7 | * family members will probably use it too. | ||
7 | * | 8 | * |
8 | * Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com) | 9 | * Copyright (C) 1999-2008, Greg Ungerer (gerg@snapgear.com) |
9 | * Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com) | 10 | * Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com) |
10 | */ | 11 | */ |
11 | 12 | ||
@@ -17,6 +18,7 @@ | |||
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
19 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | #include <linux/clocksource.h> | ||
20 | #include <asm/machdep.h> | 22 | #include <asm/machdep.h> |
21 | #include <asm/io.h> | 23 | #include <asm/io.h> |
22 | #include <asm/coldfire.h> | 24 | #include <asm/coldfire.h> |
@@ -28,70 +30,84 @@ | |||
28 | /* | 30 | /* |
29 | * By default use timer1 as the system clock timer. | 31 | * By default use timer1 as the system clock timer. |
30 | */ | 32 | */ |
33 | #define FREQ ((MCF_CLK / 2) / 64) | ||
31 | #define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a)) | 34 | #define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a)) |
35 | #define INTC0 (MCF_IPSBAR + MCFICM_INTC0) | ||
36 | |||
37 | static u32 pit_cycles_per_jiffy; | ||
38 | static u32 pit_cnt; | ||
32 | 39 | ||
33 | /***************************************************************************/ | 40 | /***************************************************************************/ |
34 | 41 | ||
35 | static irqreturn_t hw_tick(int irq, void *dummy) | 42 | static irqreturn_t pit_tick(int irq, void *dummy) |
36 | { | 43 | { |
37 | unsigned short pcsr; | 44 | u16 pcsr; |
38 | 45 | ||
39 | /* Reset the ColdFire timer */ | 46 | /* Reset the ColdFire timer */ |
40 | pcsr = __raw_readw(TA(MCFPIT_PCSR)); | 47 | pcsr = __raw_readw(TA(MCFPIT_PCSR)); |
41 | __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR)); | 48 | __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR)); |
42 | 49 | ||
50 | pit_cnt += pit_cycles_per_jiffy; | ||
43 | return arch_timer_interrupt(irq, dummy); | 51 | return arch_timer_interrupt(irq, dummy); |
44 | } | 52 | } |
45 | 53 | ||
46 | /***************************************************************************/ | 54 | /***************************************************************************/ |
47 | 55 | ||
48 | static struct irqaction coldfire_pit_irq = { | 56 | static struct irqaction pit_irq = { |
49 | .name = "timer", | 57 | .name = "timer", |
50 | .flags = IRQF_DISABLED | IRQF_TIMER, | 58 | .flags = IRQF_DISABLED | IRQF_TIMER, |
51 | .handler = hw_tick, | 59 | .handler = pit_tick, |
52 | }; | 60 | }; |
53 | 61 | ||
54 | void hw_timer_init(void) | 62 | /***************************************************************************/ |
63 | |||
64 | static cycle_t pit_read_clk(void) | ||
55 | { | 65 | { |
56 | volatile unsigned char *icrp; | 66 | unsigned long flags; |
57 | volatile unsigned long *imrp; | 67 | u32 cycles; |
68 | u16 pcntr; | ||
58 | 69 | ||
59 | setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &coldfire_pit_irq); | 70 | local_irq_save(flags); |
71 | pcntr = __raw_readw(TA(MCFPIT_PCNTR)); | ||
72 | cycles = pit_cnt; | ||
73 | local_irq_restore(flags); | ||
60 | 74 | ||
61 | icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 + | 75 | return cycles + pit_cycles_per_jiffy - pcntr; |
62 | MCFINTC_ICR0 + MCFINT_PIT1); | 76 | } |
63 | *icrp = ICR_INTRCONF; | ||
64 | 77 | ||
65 | imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR); | 78 | /***************************************************************************/ |
66 | *imrp &= ~MCFPIT_IMR_IBIT; | ||
67 | 79 | ||
68 | /* Set up PIT timer 1 as poll clock */ | 80 | static struct clocksource pit_clk = { |
69 | __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); | 81 | .name = "pit", |
70 | __raw_writew(((MCF_CLK / 2) / 64) / HZ, TA(MCFPIT_PMR)); | 82 | .rating = 250, |
71 | __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW | | 83 | .read = pit_read_clk, |
72 | MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR)); | 84 | .shift = 20, |
73 | } | 85 | .mask = CLOCKSOURCE_MASK(32), |
86 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
87 | }; | ||
74 | 88 | ||
75 | /***************************************************************************/ | 89 | /***************************************************************************/ |
76 | 90 | ||
77 | unsigned long hw_timer_offset(void) | 91 | void hw_timer_init(void) |
78 | { | 92 | { |
79 | volatile unsigned long *ipr; | 93 | u32 imr; |
80 | unsigned long pmr, pcntr, offset; | ||
81 | 94 | ||
82 | ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR); | 95 | setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq); |
83 | 96 | ||
84 | pmr = __raw_readw(TA(MCFPIT_PMR)); | 97 | __raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1); |
85 | pcntr = __raw_readw(TA(MCFPIT_PCNTR)); | 98 | imr = __raw_readl(INTC0 + MCFPIT_IMR); |
99 | imr &= ~MCFPIT_IMR_IBIT; | ||
100 | __raw_writel(imr, INTC0 + MCFPIT_IMR); | ||
101 | |||
102 | /* Set up PIT timer 1 as poll clock */ | ||
103 | pit_cycles_per_jiffy = FREQ / HZ; | ||
104 | __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); | ||
105 | __raw_writew(pit_cycles_per_jiffy, TA(MCFPIT_PMR)); | ||
106 | __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW | | ||
107 | MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR)); | ||
86 | 108 | ||
87 | /* | 109 | pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift); |
88 | * If we are still in the first half of the upcount and a | 110 | clocksource_register(&pit_clk); |
89 | * timer interrupt is pending, then add on a ticks worth of time. | ||
90 | */ | ||
91 | offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr; | ||
92 | if ((offset < (1000000 / HZ / 2)) && (*ipr & MCFPIT_IMR_IBIT)) | ||
93 | offset += 1000000 / HZ; | ||
94 | return offset; | ||
95 | } | 111 | } |
96 | 112 | ||
97 | /***************************************************************************/ | 113 | /***************************************************************************/ |