e53c446d10e4d9cd2343293b82f0017756a23f58
[deliverable/linux.git] / arch / m68knommu / platform / 5307 / pit.c
1 /***************************************************************************/
2
3 /*
4 * pit.c -- Freescale ColdFire PIT timer. Currently this type of
5 * hardware timer only exists in the Freescale ColdFire
6 * 5270/5271, 5282 and other CPUs.
7 *
8 * Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com)
9 * Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
10 */
11
12 /***************************************************************************/
13
14 #include <linux/kernel.h>
15 #include <linux/sched.h>
16 #include <linux/param.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/irq.h>
20 #include <asm/io.h>
21 #include <asm/coldfire.h>
22 #include <asm/mcfpit.h>
23 #include <asm/mcfsim.h>
24
25 /***************************************************************************/
26
27 /*
28 * By default use timer1 as the system clock timer.
29 */
30 #define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a))
31
32 /***************************************************************************/
33
34 void coldfire_pit_tick(void)
35 {
36 unsigned short pcsr;
37
38 /* Reset the ColdFire timer */
39 pcsr = __raw_readw(TA(MCFPIT_PCSR));
40 __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
41 }
42
43 /***************************************************************************/
44
45 static struct irqaction coldfire_pit_irq = {
46 .name = "timer",
47 .flags = IRQF_DISABLED | IRQF_TIMER,
48 };
49
50 void coldfire_pit_init(irq_handler_t handler)
51 {
52 volatile unsigned char *icrp;
53 volatile unsigned long *imrp;
54
55 coldfire_pit_irq.handler = handler;
56 setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &coldfire_pit_irq);
57
58 icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +
59 MCFINTC_ICR0 + MCFINT_PIT1);
60 *icrp = ICR_INTRCONF;
61
62 imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
63 *imrp &= ~MCFPIT_IMR_IBIT;
64
65 /* Set up PIT timer 1 as poll clock */
66 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
67 __raw_writew(((MCF_CLK / 2) / 64) / HZ, TA(MCFPIT_PMR));
68 __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
69 MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
70 }
71
72 /***************************************************************************/
73
74 unsigned long coldfire_pit_offset(void)
75 {
76 volatile unsigned long *ipr;
77 unsigned long pmr, pcntr, offset;
78
79 ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
80
81 pmr = __raw_readw(TA(MCFPIT_PMR));
82 pcntr = __raw_readw(TA(MCFPIT_PCNTR));
83
84 /*
85 * If we are still in the first half of the upcount and a
86 * timer interupt is pending, then add on a ticks worth of time.
87 */
88 offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr;
89 if ((offset < (1000000 / HZ / 2)) && (*ipr & MCFPIT_IMR_IBIT))
90 offset += 1000000 / HZ;
91 return offset;
92 }
93
94 /***************************************************************************/
This page took 0.041757 seconds and 5 git commands to generate.