original comment: +Wilson03172004,marked due to this pci host does not support MWI
[linux-2.4.git] / arch / mips / baget / time.c
1 /*
2  * time.c: Baget/MIPS specific time handling details
3  *
4  * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
5  */
6
7 #include <linux/errno.h>
8 #include <linux/init.h>
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
11 #include <linux/param.h>
12 #include <linux/string.h>
13 #include <linux/mm.h>
14 #include <linux/interrupt.h>
15 #include <linux/timex.h>
16 #include <linux/spinlock.h>
17
18 #include <asm/bootinfo.h>
19 #include <asm/io.h>
20 #include <asm/irq.h>
21 #include <asm/ptrace.h>
22 #include <asm/system.h>
23
24 #include <asm/baget/baget.h>
25
26 extern rwlock_t xtime_lock;
27
28 /*
29  *  To have precision clock, we need to fix available clock frequency
30  */
31 #define FREQ_NOM  79125  /* Baget frequency ratio */
32 #define FREQ_DEN  10000
33
34 static inline int timer_intr_valid(void)
35 {
36         static unsigned long long ticks, valid_ticks;
37
38         if (ticks++ * FREQ_DEN >= valid_ticks * FREQ_NOM) {
39                 /*
40                  *  We need no overflow checks,
41                  *  due baget unable to work 3000 years...
42                  *  At least without reboot...
43                  */
44                 valid_ticks++;
45                 return 1;
46         }
47         return 0;
48 }
49
50 void static timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
51 {
52         if (timer_intr_valid()) {
53                 sti();
54                 do_timer(regs);
55         }
56 }
57
58 static void __init timer_enable(void)
59 {
60         unsigned char ss0cr0 = vic_inb(VIC_SS0CR0);
61         ss0cr0 &= ~VIC_SS0CR0_TIMER_FREQ_MASK;
62         ss0cr0 |= VIC_SS0CR0_TIMER_FREQ_1000HZ;
63         vic_outb(ss0cr0, VIC_SS0CR0);
64
65         vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE|
66                  VIC_INT_LOW|VIC_INT_ENABLE, VIC_LINT2);
67 }
68
69 static struct irqaction timer_irq  =
70 { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
71
72 void __init time_init(void)
73 {
74         if (setup_baget_irq(BAGET_VIC_TIMER_IRQ, &timer_irq) < 0)
75                 printk("time_init: unable request irq for system timer\n");
76         timer_enable();
77         /* We don't call sti() here, because it is too early for baget */
78 }
79
80 void do_gettimeofday(struct timeval *tv)
81 {
82         unsigned long flags;
83
84         read_lock_irqsave (&xtime_lock, flags);
85         *tv = xtime;
86         read_unlock_irqrestore (&xtime_lock, flags);
87 }
88
89 void do_settimeofday(struct timeval *tv)
90 {
91         write_lock_irq (&xtime_lock);
92         xtime = *tv;
93         time_adjust = 0;                /* stop active adjtime() */
94         time_status |= STA_UNSYNC;
95         time_maxerror = NTP_PHASE_LIMIT;
96         time_esterror = NTP_PHASE_LIMIT;
97         write_unlock_irq (&xtime_lock);
98 }