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 void init_cf_pit_timer(enum clock_event_mode mode, 46 struct clock_event_device *evt) 47 { 48 switch (mode) { 49 case CLOCK_EVT_MODE_PERIODIC: 50 51 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); 52 __raw_writew(PIT_CYCLES_PER_JIFFY, TA(MCFPIT_PMR)); 53 __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \ 54 MCFPIT_PCSR_OVW | MCFPIT_PCSR_RLD | \ 55 MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR)); 56 break; 57 58 case CLOCK_EVT_MODE_SHUTDOWN: 59 case CLOCK_EVT_MODE_UNUSED: 60 61 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); 62 break; 63 64 case CLOCK_EVT_MODE_ONESHOT: 65 66 __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); 67 __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \ 68 MCFPIT_PCSR_OVW | MCFPIT_PCSR_CLK64, \ 69 TA(MCFPIT_PCSR)); 70 break; 71 72 case CLOCK_EVT_MODE_RESUME: 73 /* Nothing to do here */ 74 break; 75 } 76 } 77 78 /* 79 * Program the next event in oneshot mode 80 * 81 * Delta is given in PIT ticks 82 */ 83 static int cf_pit_next_event(unsigned long delta, 84 struct clock_event_device *evt) 85 { 86 __raw_writew(delta, TA(MCFPIT_PMR)); 87 return 0; 88 } 89 90 struct clock_event_device cf_pit_clockevent = { 91 .name = "pit", 92 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 93 .set_mode = init_cf_pit_timer, 94 .set_next_event = cf_pit_next_event, 95 .shift = 32, 96 .irq = MCF_IRQ_PIT1, 97 }; 98 99 100 101 /***************************************************************************/ 102 103 static irqreturn_t pit_tick(int irq, void *dummy) 104 { 105 struct clock_event_device *evt = &cf_pit_clockevent; 106 u16 pcsr; 107 108 /* Reset the ColdFire timer */ 109 pcsr = __raw_readw(TA(MCFPIT_PCSR)); 110 __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR)); 111 112 pit_cnt += PIT_CYCLES_PER_JIFFY; 113 evt->event_handler(evt); 114 return IRQ_HANDLED; 115 } 116 117 /***************************************************************************/ 118 119 static struct irqaction pit_irq = { 120 .name = "timer", 121 .flags = IRQF_TIMER, 122 .handler = pit_tick, 123 }; 124 125 /***************************************************************************/ 126 127 static cycle_t pit_read_clk(struct clocksource *cs) 128 { 129 unsigned long flags; 130 u32 cycles; 131 u16 pcntr; 132 133 local_irq_save(flags); 134 pcntr = __raw_readw(TA(MCFPIT_PCNTR)); 135 cycles = pit_cnt; 136 local_irq_restore(flags); 137 138 return cycles + PIT_CYCLES_PER_JIFFY - pcntr; 139 } 140 141 /***************************************************************************/ 142 143 static struct clocksource pit_clk = { 144 .name = "pit", 145 .rating = 100, 146 .read = pit_read_clk, 147 .mask = CLOCKSOURCE_MASK(32), 148 }; 149 150 /***************************************************************************/ 151 152 void hw_timer_init(irq_handler_t handler) 153 { 154 cf_pit_clockevent.cpumask = cpumask_of(smp_processor_id()); 155 cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32); 156 cf_pit_clockevent.max_delta_ns = 157 clockevent_delta2ns(0xFFFF, &cf_pit_clockevent); 158 cf_pit_clockevent.min_delta_ns = 159 clockevent_delta2ns(0x3f, &cf_pit_clockevent); 160 clockevents_register_device(&cf_pit_clockevent); 161 162 setup_irq(MCF_IRQ_PIT1, &pit_irq); 163 164 clocksource_register_hz(&pit_clk, FREQ); 165 } 166 167 /***************************************************************************/ 168