.. | .. |
---|
18 | 18 | #include <linux/kernel.h> |
---|
19 | 19 | #include <linux/mm.h> |
---|
20 | 20 | #include <linux/tty.h> |
---|
| 21 | +#include <linux/clocksource.h> |
---|
21 | 22 | #include <linux/console.h> |
---|
22 | 23 | #include <linux/linkage.h> |
---|
23 | 24 | #include <linux/init.h> |
---|
.. | .. |
---|
30 | 31 | #include <asm/bootinfo.h> |
---|
31 | 32 | #include <asm/bootinfo-vme.h> |
---|
32 | 33 | #include <asm/byteorder.h> |
---|
33 | | -#include <asm/pgtable.h> |
---|
34 | 34 | #include <asm/setup.h> |
---|
35 | 35 | #include <asm/irq.h> |
---|
36 | 36 | #include <asm/traps.h> |
---|
.. | .. |
---|
39 | 39 | |
---|
40 | 40 | static void bvme6000_get_model(char *model); |
---|
41 | 41 | extern void bvme6000_sched_init(irq_handler_t handler); |
---|
42 | | -extern u32 bvme6000_gettimeoffset(void); |
---|
43 | 42 | extern int bvme6000_hwclk (int, struct rtc_time *); |
---|
44 | 43 | extern void bvme6000_reset (void); |
---|
45 | 44 | void bvme6000_set_vectors (void); |
---|
.. | .. |
---|
105 | 104 | mach_max_dma_address = 0xffffffff; |
---|
106 | 105 | mach_sched_init = bvme6000_sched_init; |
---|
107 | 106 | mach_init_IRQ = bvme6000_init_IRQ; |
---|
108 | | - arch_gettimeoffset = bvme6000_gettimeoffset; |
---|
109 | 107 | mach_hwclk = bvme6000_hwclk; |
---|
110 | 108 | mach_reset = bvme6000_reset; |
---|
111 | 109 | mach_get_model = bvme6000_get_model; |
---|
.. | .. |
---|
149 | 147 | return IRQ_HANDLED; |
---|
150 | 148 | } |
---|
151 | 149 | |
---|
| 150 | +static u64 bvme6000_read_clk(struct clocksource *cs); |
---|
| 151 | + |
---|
| 152 | +static struct clocksource bvme6000_clk = { |
---|
| 153 | + .name = "rtc", |
---|
| 154 | + .rating = 250, |
---|
| 155 | + .read = bvme6000_read_clk, |
---|
| 156 | + .mask = CLOCKSOURCE_MASK(32), |
---|
| 157 | + .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
---|
| 158 | +}; |
---|
| 159 | + |
---|
| 160 | +static u32 clk_total, clk_offset; |
---|
| 161 | + |
---|
| 162 | +#define RTC_TIMER_CLOCK_FREQ 8000000 |
---|
| 163 | +#define RTC_TIMER_CYCLES (RTC_TIMER_CLOCK_FREQ / HZ) |
---|
| 164 | +#define RTC_TIMER_COUNT ((RTC_TIMER_CYCLES / 2) - 1) |
---|
152 | 165 | |
---|
153 | 166 | static irqreturn_t bvme6000_timer_int (int irq, void *dev_id) |
---|
154 | 167 | { |
---|
.. | .. |
---|
160 | 173 | local_irq_save(flags); |
---|
161 | 174 | msr = rtc->msr & 0xc0; |
---|
162 | 175 | rtc->msr = msr | 0x20; /* Ack the interrupt */ |
---|
| 176 | + clk_total += RTC_TIMER_CYCLES; |
---|
| 177 | + clk_offset = 0; |
---|
163 | 178 | timer_routine(0, NULL); |
---|
164 | 179 | local_irq_restore(flags); |
---|
165 | 180 | |
---|
.. | .. |
---|
182 | 197 | |
---|
183 | 198 | rtc->msr = 0; /* Ensure timer registers accessible */ |
---|
184 | 199 | |
---|
185 | | - if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0, "timer", |
---|
| 200 | + if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, IRQF_TIMER, "timer", |
---|
186 | 201 | timer_routine)) |
---|
187 | 202 | panic ("Couldn't register timer int"); |
---|
188 | 203 | |
---|
189 | 204 | rtc->t1cr_omr = 0x04; /* Mode 2, ext clk */ |
---|
190 | | - rtc->t1msb = 39999 >> 8; |
---|
191 | | - rtc->t1lsb = 39999 & 0xff; |
---|
| 205 | + rtc->t1msb = RTC_TIMER_COUNT >> 8; |
---|
| 206 | + rtc->t1lsb = RTC_TIMER_COUNT & 0xff; |
---|
192 | 207 | rtc->irr_icr1 &= 0xef; /* Route timer 1 to INTR pin */ |
---|
193 | 208 | rtc->msr = 0x40; /* Access int.cntrl, etc */ |
---|
194 | 209 | rtc->pfr_icr0 = 0x80; /* Just timer 1 ints enabled */ |
---|
.. | .. |
---|
200 | 215 | |
---|
201 | 216 | rtc->msr = msr; |
---|
202 | 217 | |
---|
| 218 | + clocksource_register_hz(&bvme6000_clk, RTC_TIMER_CLOCK_FREQ); |
---|
| 219 | + |
---|
203 | 220 | if (request_irq(BVME_IRQ_ABORT, bvme6000_abort_int, 0, |
---|
204 | 221 | "abort", bvme6000_abort_int)) |
---|
205 | 222 | panic ("Couldn't register abort int"); |
---|
206 | 223 | } |
---|
207 | 224 | |
---|
208 | | - |
---|
209 | | -/* This is always executed with interrupts disabled. */ |
---|
210 | 225 | |
---|
211 | 226 | /* |
---|
212 | 227 | * NOTE: Don't accept any readings within 5us of rollover, as |
---|
.. | .. |
---|
215 | 230 | * results... |
---|
216 | 231 | */ |
---|
217 | 232 | |
---|
218 | | -u32 bvme6000_gettimeoffset(void) |
---|
| 233 | +static u64 bvme6000_read_clk(struct clocksource *cs) |
---|
219 | 234 | { |
---|
| 235 | + unsigned long flags; |
---|
220 | 236 | volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; |
---|
221 | 237 | volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE; |
---|
222 | | - unsigned char msr = rtc->msr & 0xc0; |
---|
| 238 | + unsigned char msr, msb; |
---|
223 | 239 | unsigned char t1int, t1op; |
---|
224 | 240 | u32 v = 800000, ov; |
---|
225 | 241 | |
---|
| 242 | + local_irq_save(flags); |
---|
| 243 | + |
---|
| 244 | + msr = rtc->msr & 0xc0; |
---|
226 | 245 | rtc->msr = 0; /* Ensure timer registers accessible */ |
---|
227 | 246 | |
---|
228 | 247 | do { |
---|
.. | .. |
---|
230 | 249 | t1int = rtc->msr & 0x20; |
---|
231 | 250 | t1op = pit->pcdr & 0x04; |
---|
232 | 251 | rtc->t1cr_omr |= 0x40; /* Latch timer1 */ |
---|
233 | | - v = rtc->t1msb << 8; /* Read timer1 */ |
---|
234 | | - v |= rtc->t1lsb; /* Read timer1 */ |
---|
| 252 | + msb = rtc->t1msb; /* Read timer1 */ |
---|
| 253 | + v = (msb << 8) | rtc->t1lsb; /* Read timer1 */ |
---|
235 | 254 | } while (t1int != (rtc->msr & 0x20) || |
---|
236 | 255 | t1op != (pit->pcdr & 0x04) || |
---|
237 | 256 | abs(ov-v) > 80 || |
---|
238 | | - v > 39960); |
---|
| 257 | + v > RTC_TIMER_COUNT - (RTC_TIMER_COUNT / 100)); |
---|
239 | 258 | |
---|
240 | | - v = 39999 - v; |
---|
| 259 | + v = RTC_TIMER_COUNT - v; |
---|
241 | 260 | if (!t1op) /* If in second half cycle.. */ |
---|
242 | | - v += 40000; |
---|
243 | | - v /= 8; /* Convert ticks to microseconds */ |
---|
244 | | - if (t1int) |
---|
245 | | - v += 10000; /* Int pending, + 10ms */ |
---|
| 261 | + v += RTC_TIMER_CYCLES / 2; |
---|
| 262 | + if (msb > 0 && t1int) |
---|
| 263 | + clk_offset = RTC_TIMER_CYCLES; |
---|
246 | 264 | rtc->msr = msr; |
---|
247 | 265 | |
---|
248 | | - return v * 1000; |
---|
| 266 | + v += clk_offset + clk_total; |
---|
| 267 | + |
---|
| 268 | + local_irq_restore(flags); |
---|
| 269 | + |
---|
| 270 | + return v; |
---|
249 | 271 | } |
---|
250 | 272 | |
---|
251 | 273 | /* |
---|