aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/m68knommu/platform/coldfire/pit.c86
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
37static u32 pit_cycles_per_jiffy;
38static u32 pit_cnt;
32 39
33/***************************************************************************/ 40/***************************************************************************/
34 41
35static irqreturn_t hw_tick(int irq, void *dummy) 42static 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
48static struct irqaction coldfire_pit_irq = { 56static 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
54void hw_timer_init(void) 62/***************************************************************************/
63
64static 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 */ 80static 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
77unsigned long hw_timer_offset(void) 91void 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/***************************************************************************/