* better
[mascara-docs.git] / i386 / linux-2.3.21 / arch / sparc / ap1000 / timer.c
blob567d240676e97ad07aa2671294254149adc0a1dd
1 /*
2 * Copyright 1996 The Australian National University.
3 * Copyright 1996 Fujitsu Laboratories Limited
4 *
5 * This software may be distributed under the terms of the Gnu
6 * Public License version 2 or later
7 */
8 /* routines to control the AP1000 timer chip */
10 #include <linux/time.h>
11 #include <linux/sched.h>
12 #include <linux/interrupt.h>
13 #include <linux/mm.h>
14 #include <linux/malloc.h>
15 #include <asm/ap1000/apservice.h>
16 #include <asm/ap1000/apreg.h>
17 #include <asm/irq.h>
19 #define INIT_TIM1 (781250/HZ)
20 #define INIT_TIM0 (781250/(10*HZ))
22 static unsigned long last_freerun;
24 unsigned ap_freerun(void)
26 return *((volatile unsigned long *)(MC_FREERUN + 4));
29 void ap_clear_clock_irq(void)
31 MC_OUT(MC_INTR, AP_CLR_INTR_REQ << MC_INTR_ITIM1_SH);
32 last_freerun = *((unsigned long *)(MC_FREERUN + 4));
33 tnet_check_completion();
34 #if 1
35 if ((((unsigned)jiffies) % (HZ/4)) == 0) {
36 msc_timer();
37 ap_xor_led(1);
38 bif_timer();
39 ap_dbg_flush();
40 #if 0
41 bif_led_status();
42 #endif
44 #endif
48 void ap_gettimeofday(struct timeval *xt)
50 unsigned long d;
51 unsigned v;
52 unsigned long new_freerun;
54 /* this is in 80ns units - we only use the low 32 bits
55 as 5mins is plenty for this stuff */
56 d = new_freerun = *((unsigned long *)(MC_FREERUN + 4));
58 if (d < last_freerun) {
59 /* wraparound */
60 d += ((~0) - last_freerun);
61 } else {
62 d -= last_freerun;
65 /* convert to microseconds */
66 v = ((d&0xffffff)*10)/125;
68 /* only want microseconds/HZ */
69 v = v%(1000000/HZ);
71 xt->tv_usec += v;
73 last_freerun = new_freerun;
76 static void profile_interrupt(int irq, void *dev_id, struct pt_regs * regs)
78 if (prof_buffer && current->pid) {
79 extern int _stext;
80 unsigned long ip = instruction_pointer(regs);
81 ip -= (unsigned long) &_stext;
82 ip >>= prof_shift;
83 if (ip < prof_len)
84 prof_buffer[ip]++;
86 MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM0_SH);
89 void ap_profile_init(void)
91 if (prof_shift) {
92 printk("Initialising profiling with prof_shift=%d\n",(int)prof_shift);
93 MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM0_SH);
94 MC_OUT(MC_INTR,AP_CLR_INTR_MASK << MC_INTR_ITIM0_SH);
98 void ap_init_timers(void)
100 extern void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs);
101 unsigned flags;
103 printk("Initialising ap1000 timer\n");
105 save_flags(flags); cli();
107 request_irq(APTIM1_IRQ,
108 timer_interrupt,
109 (SA_INTERRUPT | SA_STATIC_ALLOC),
110 "timer", NULL);
112 request_irq(APTIM0_IRQ,
113 profile_interrupt,
114 (SA_INTERRUPT | SA_STATIC_ALLOC),
115 "profile", NULL);
117 ap_clear_clock_irq();
119 MC_OUT(MC_ITIMER0,INIT_TIM0);
120 MC_OUT(MC_ITIMER1,INIT_TIM1);
121 MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM1_SH);
122 MC_OUT(MC_INTR,AP_CLR_INTR_MASK << MC_INTR_ITIM1_SH);
123 MC_OUT(MC_INTR,AP_SET_INTR_MASK << MC_INTR_ITIM0_SH);
124 restore_flags(flags);