RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / arch / arm / mach-ns9xxx / time.c
blobb97d0c54a388163fc72090992d89c9233edbc7af
1 /*
2 * arch/arm/mach-ns9xxx/time.c
4 * Copyright (C) 2006 by Digi International Inc.
5 * All rights reserved.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
11 #include <linux/jiffies.h>
12 #include <linux/interrupt.h>
13 #include <linux/irq.h>
14 #include <asm/arch-ns9xxx/regs-sys.h>
15 #include <asm/arch-ns9xxx/clock.h>
16 #include <asm/arch-ns9xxx/irqs.h>
17 #include <asm/arch/system.h>
18 #include "generic.h"
20 #define TIMERCLOCKSELECT 64
22 static u32 usecs_per_tick;
24 static irqreturn_t
25 ns9xxx_timer_interrupt(int irq, void *dev_id)
27 write_seqlock(&xtime_lock);
28 timer_tick();
29 write_sequnlock(&xtime_lock);
31 return IRQ_HANDLED;
34 static unsigned long ns9xxx_timer_gettimeoffset(void)
36 /* return the microseconds which have passed since the last interrupt
37 * was _serviced_. That is, if an interrupt is pending or the counter
38 * reloads, return one period more. */
40 u32 counter1 = SYS_TR(0);
41 int pending = SYS_ISR & (1 << IRQ_TIMER0);
42 u32 counter2 = SYS_TR(0);
43 u32 elapsed;
45 if (pending || counter2 > counter1)
46 elapsed = 2 * SYS_TRC(0) - counter2;
47 else
48 elapsed = SYS_TRC(0) - counter1;
50 return (elapsed * usecs_per_tick) >> 16;
54 static struct irqaction ns9xxx_timer_irq = {
55 .name = "NS9xxx Timer Tick",
56 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
57 .handler = ns9xxx_timer_interrupt,
60 static void __init ns9xxx_timer_init(void)
62 int tc;
64 usecs_per_tick =
65 SH_DIV(1000000 * TIMERCLOCKSELECT, ns9xxx_cpuclock(), 16);
67 /* disable timer */
68 if ((tc = SYS_TC(0)) & SYS_TCx_TEN)
69 SYS_TC(0) = tc & ~SYS_TCx_TEN;
71 SYS_TRC(0) = SH_DIV(ns9xxx_cpuclock(), (TIMERCLOCKSELECT * HZ), 0);
73 REGSET(tc, SYS_TCx, TEN, EN);
74 REGSET(tc, SYS_TCx, TLCS, DIV64); /* This must match TIMERCLOCKSELECT */
75 REGSET(tc, SYS_TCx, INTS, EN);
76 REGSET(tc, SYS_TCx, UDS, DOWN);
77 REGSET(tc, SYS_TCx, TDBG, STOP);
78 REGSET(tc, SYS_TCx, TSZ, 32);
79 REGSET(tc, SYS_TCx, REN, EN);
80 SYS_TC(0) = tc;
82 setup_irq(IRQ_TIMER0, &ns9xxx_timer_irq);
85 struct sys_timer ns9xxx_timer = {
86 .init = ns9xxx_timer_init,
87 .offset = ns9xxx_timer_gettimeoffset,