]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - arch/m68knommu/platform/5307/pit.c
Merge git://git.infradead.org/mtd-2.6
[linux-2.6.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-2006, Greg Ungerer (gerg@snapgear.com)
9  *      Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
10  *
11  */
12
13 /***************************************************************************/
14
15 #include <linux/kernel.h>
16 #include <linux/sched.h>
17 #include <linux/param.h>
18 #include <linux/init.h>
19 #include <linux/interrupt.h>
20 #include <asm/io.h>
21 #include <asm/irq.h>
22 #include <asm/coldfire.h>
23 #include <asm/mcfpit.h>
24 #include <asm/mcfsim.h>
25
26 /***************************************************************************/
27
28 /*
29  *      By default use timer1 as the system clock timer.
30  */
31 #define TA(a)   (MCF_IPSBAR + MCFPIT_BASE1 + (a))
32
33 /***************************************************************************/
34
35 void coldfire_pit_tick(void)
36 {
37         unsigned short pcsr;
38
39         /* Reset the ColdFire timer */
40         pcsr = __raw_readw(TA(MCFPIT_PCSR));
41         __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
42 }
43
44 /***************************************************************************/
45
46 void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
47 {
48         volatile unsigned char *icrp;
49         volatile unsigned long *imrp;
50
51         request_irq(MCFINT_VECBASE + MCFINT_PIT1, handler, IRQF_DISABLED,
52                 "ColdFire Timer", NULL);
53
54         icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +
55                 MCFINTC_ICR0 + MCFINT_PIT1);
56         *icrp = ICR_INTRCONF;
57
58         imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
59         *imrp &= ~MCFPIT_IMR_IBIT;
60
61         /* Set up PIT timer 1 as poll clock */
62         __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
63         __raw_writew(((MCF_CLK / 2) / 64) / HZ, TA(MCFPIT_PMR));
64         __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
65                 MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
66 }
67
68 /***************************************************************************/
69
70 unsigned long coldfire_pit_offset(void)
71 {
72         volatile unsigned long *ipr;
73         unsigned long pmr, pcntr, offset;
74
75         ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
76
77         pmr = __raw_readw(TA(MCFPIT_PMR));
78         pcntr = __raw_readw(TA(MCFPIT_PCNTR));
79
80         /*
81          * If we are still in the first half of the upcount and a
82          * timer interupt is pending, then add on a ticks worth of time.
83          */
84         offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr;
85         if ((offset < (1000000 / HZ / 2)) && (*ipr & MCFPIT_IMR_IBIT))
86                 offset += 1000000 / HZ;
87         return offset;  
88 }
89
90 /***************************************************************************/