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 5208 CPUs. No doubt newer ColdFire 7 * family members will probably use it too. 8 * 9 * Copyright (C) 1999-2008, Greg Ungerer (gerg@snapgear.com) 10 * Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com) 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 <linux/irq.h> 21 #include <linux/clockchips.h> 22 #include <asm/machdep.h> 23 #include <asm/io.h> 24 #include <asm/coldfire.h> 25 #include <asm/mcfpit.h> 26 #include <asm/mcfsim.h> 27 28 /***************************************************************************/ 29 30 /* 31 * By default use timer1 as the system clock timer. 32 */ 33 #define FREQ ((MCF_CLK / 2) / 64) 34 #define TA(a) (MCFPIT_BASE1 + (a)) 35 #define PIT_CYCLES_PER_JIFFY (FREQ / HZ) 36 37 static u32 pit_cnt; 38 39 /* 40 * Initialize the PIT timer. 41 * 42 * This is also called after resume to bring the PIT into operation again. 43 */ 44 45 static int cf_pit_set_periodic(struct clock_event_device *evt) 46 { 47 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); 48 __raw_writew(PIT_CYCLES_PER_JIFFY, TA(MCFPIT_PMR)); 49 __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | 50 MCFPIT_PCSR_OVW | MCFPIT_PCSR_RLD | 51 MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR)); 52 return 0; 53 } 54 55 static int cf_pit_set_oneshot(struct clock_event_device *evt) 56 { 57 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); 58 __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | 59 MCFPIT_PCSR_OVW | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR)); 60 return 0; 61 } 62 63 static int cf_pit_shutdown(struct clock_event_device *evt) 64 { 65 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); 66 return 0; 67 } 68 69 /* 70 * Program the next event in oneshot mode 71 * 72 * Delta is given in PIT ticks 73 */ 74 static int cf_pit_next_event(unsigned long delta, 75 struct clock_event_device *evt) 76 { 77 __raw_writew(delta, TA(MCFPIT_PMR)); 78 return 0; 79 } 80 81 struct clock_event_device cf_pit_clockevent = { 82 .name = "pit", 83 .features = CLOCK_EVT_FEAT_PERIODIC | 84 CLOCK_EVT_FEAT_ONESHOT, 85 .set_state_shutdown = cf_pit_shutdown, 86 .set_state_periodic = cf_pit_set_periodic, 87 .set_state_oneshot = cf_pit_set_oneshot, 88 .set_next_event = cf_pit_next_event, 89 .shift = 32, 90 .irq = MCF_IRQ_PIT1, 91 }; 92 93 94 95 /***************************************************************************/ 96 97 static irqreturn_t pit_tick(int irq, void *dummy) 98 { 99 struct clock_event_device *evt = &cf_pit_clockevent; 100 u16 pcsr; 101 102 /* Reset the ColdFire timer */ 103 pcsr = __raw_readw(TA(MCFPIT_PCSR)); 104 __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR)); 105 106 pit_cnt += PIT_CYCLES_PER_JIFFY; 107 evt->event_handler(evt); 108 return IRQ_HANDLED; 109 } 110 111 /***************************************************************************/ 112 113 static struct irqaction pit_irq = { 114 .name = "timer", 115 .flags = IRQF_TIMER, 116 .handler = pit_tick, 117 }; 118 119 /***************************************************************************/ 120 121 static cycle_t pit_read_clk(struct clocksource *cs) 122 { 123 unsigned long flags; 124 u32 cycles; 125 u16 pcntr; 126 127 local_irq_save(flags); 128 pcntr = __raw_readw(TA(MCFPIT_PCNTR)); 129 cycles = pit_cnt; 130 local_irq_restore(flags); 131 132 return cycles + PIT_CYCLES_PER_JIFFY - pcntr; 133 } 134 135 /***************************************************************************/ 136 137 static struct clocksource pit_clk = { 138 .name = "pit", 139 .rating = 100, 140 .read = pit_read_clk, 141 .mask = CLOCKSOURCE_MASK(32), 142 }; 143 144 /***************************************************************************/ 145 146 void hw_timer_init(irq_handler_t handler) 147 { 148 cf_pit_clockevent.cpumask = cpumask_of(smp_processor_id()); 149 cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32); 150 cf_pit_clockevent.max_delta_ns = 151 clockevent_delta2ns(0xFFFF, &cf_pit_clockevent); 152 cf_pit_clockevent.min_delta_ns = 153 clockevent_delta2ns(0x3f, &cf_pit_clockevent); 154 clockevents_register_device(&cf_pit_clockevent); 155 156 setup_irq(MCF_IRQ_PIT1, &pit_irq); 157 158 clocksource_register_hz(&pit_clk, FREQ); 159 } 160 161 /***************************************************************************/ 162