aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68knommu/platform/coldfire/pit.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68knommu/platform/coldfire/pit.c')
-rw-r--r--arch/m68knommu/platform/coldfire/pit.c91
1 files changed, 78 insertions, 13 deletions
diff --git a/arch/m68knommu/platform/coldfire/pit.c b/arch/m68knommu/platform/coldfire/pit.c
index 4290638012e0..c5b916700b22 100644
--- a/arch/m68knommu/platform/coldfire/pit.c
+++ b/arch/m68knommu/platform/coldfire/pit.c
@@ -18,7 +18,7 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/irq.h> 20#include <linux/irq.h>
21#include <linux/clocksource.h> 21#include <linux/clockchips.h>
22#include <asm/machdep.h> 22#include <asm/machdep.h>
23#include <asm/io.h> 23#include <asm/io.h>
24#include <asm/coldfire.h> 24#include <asm/coldfire.h>
@@ -33,22 +33,86 @@
33#define FREQ ((MCF_CLK / 2) / 64) 33#define FREQ ((MCF_CLK / 2) / 64)
34#define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a)) 34#define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a))
35#define INTC0 (MCF_IPSBAR + MCFICM_INTC0) 35#define INTC0 (MCF_IPSBAR + MCFICM_INTC0)
36#define PIT_CYCLES_PER_JIFFY (FREQ / HZ)
36 37
37static u32 pit_cycles_per_jiffy;
38static u32 pit_cnt; 38static u32 pit_cnt;
39 39
40/*
41 * Initialize the PIT timer.
42 *
43 * This is also called after resume to bring the PIT into operation again.
44 */
45
46static void init_cf_pit_timer(enum clock_event_mode mode,
47 struct clock_event_device *evt)
48{
49 switch (mode) {
50 case CLOCK_EVT_MODE_PERIODIC:
51
52 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
53 __raw_writew(PIT_CYCLES_PER_JIFFY, TA(MCFPIT_PMR));
54 __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
55 MCFPIT_PCSR_OVW | MCFPIT_PCSR_RLD | \
56 MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
57 break;
58
59 case CLOCK_EVT_MODE_SHUTDOWN:
60 case CLOCK_EVT_MODE_UNUSED:
61
62 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
63 break;
64
65 case CLOCK_EVT_MODE_ONESHOT:
66
67 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
68 __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
69 MCFPIT_PCSR_OVW | MCFPIT_PCSR_CLK64, \
70 TA(MCFPIT_PCSR));
71 break;
72
73 case CLOCK_EVT_MODE_RESUME:
74 /* Nothing to do here */
75 break;
76 }
77}
78
79/*
80 * Program the next event in oneshot mode
81 *
82 * Delta is given in PIT ticks
83 */
84static int cf_pit_next_event(unsigned long delta,
85 struct clock_event_device *evt)
86{
87 __raw_writew(delta, TA(MCFPIT_PMR));
88 return 0;
89}
90
91struct clock_event_device cf_pit_clockevent = {
92 .name = "pit",
93 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
94 .set_mode = init_cf_pit_timer,
95 .set_next_event = cf_pit_next_event,
96 .shift = 32,
97 .irq = MCFINT_VECBASE + MCFINT_PIT1,
98};
99
100
101
40/***************************************************************************/ 102/***************************************************************************/
41 103
42static irqreturn_t pit_tick(int irq, void *dummy) 104static irqreturn_t pit_tick(int irq, void *dummy)
43{ 105{
106 struct clock_event_device *evt = &cf_pit_clockevent;
44 u16 pcsr; 107 u16 pcsr;
45 108
46 /* Reset the ColdFire timer */ 109 /* Reset the ColdFire timer */
47 pcsr = __raw_readw(TA(MCFPIT_PCSR)); 110 pcsr = __raw_readw(TA(MCFPIT_PCSR));
48 __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR)); 111 __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
49 112
50 pit_cnt += pit_cycles_per_jiffy; 113 pit_cnt += PIT_CYCLES_PER_JIFFY;
51 return arch_timer_interrupt(irq, dummy); 114 evt->event_handler(evt);
115 return IRQ_HANDLED;
52} 116}
53 117
54/***************************************************************************/ 118/***************************************************************************/
@@ -72,14 +136,14 @@ static cycle_t pit_read_clk(void)
72 cycles = pit_cnt; 136 cycles = pit_cnt;
73 local_irq_restore(flags); 137 local_irq_restore(flags);
74 138
75 return cycles + pit_cycles_per_jiffy - pcntr; 139 return cycles + PIT_CYCLES_PER_JIFFY - pcntr;
76} 140}
77 141
78/***************************************************************************/ 142/***************************************************************************/
79 143
80static struct clocksource pit_clk = { 144static struct clocksource pit_clk = {
81 .name = "pit", 145 .name = "pit",
82 .rating = 250, 146 .rating = 100,
83 .read = pit_read_clk, 147 .read = pit_read_clk,
84 .shift = 20, 148 .shift = 20,
85 .mask = CLOCKSOURCE_MASK(32), 149 .mask = CLOCKSOURCE_MASK(32),
@@ -92,6 +156,14 @@ void hw_timer_init(void)
92{ 156{
93 u32 imr; 157 u32 imr;
94 158
159 cf_pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
160 cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32);
161 cf_pit_clockevent.max_delta_ns =
162 clockevent_delta2ns(0xFFFF, &cf_pit_clockevent);
163 cf_pit_clockevent.min_delta_ns =
164 clockevent_delta2ns(0x3f, &cf_pit_clockevent);
165 clockevents_register_device(&cf_pit_clockevent);
166
95 setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq); 167 setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq);
96 168
97 __raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1); 169 __raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1);
@@ -99,13 +171,6 @@ void hw_timer_init(void)
99 imr &= ~MCFPIT_IMR_IBIT; 171 imr &= ~MCFPIT_IMR_IBIT;
100 __raw_writel(imr, INTC0 + MCFPIT_IMR); 172 __raw_writel(imr, INTC0 + MCFPIT_IMR);
101 173
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));
108
109 pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift); 174 pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift);
110 clocksource_register(&pit_clk); 175 clocksource_register(&pit_clk);
111} 176}