patch-2.1.23 linux/arch/sparc/ap1000/timer.c
Next file: linux/arch/sparc/ap1000/tnet.c
Previous file: linux/arch/sparc/ap1000/sync.c
Back to the patch index
Back to the overall index
- Lines: 127
- Date:
Sun Jan 26 12:07:06 1997
- Orig file:
v2.1.22/linux/arch/sparc/ap1000/timer.c
- Orig date:
Thu Jan 1 02:00:00 1970
diff -u --recursive --new-file v2.1.22/linux/arch/sparc/ap1000/timer.c linux/arch/sparc/ap1000/timer.c
@@ -0,0 +1,126 @@
+ /*
+ * Copyright 1996 The Australian National University.
+ * Copyright 1996 Fujitsu Laboratories Limited
+ *
+ * This software may be distributed under the terms of the Gnu
+ * Public License version 2 or later
+ */
+/* routines to control the AP1000 timer chip */
+
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <asm/ap1000/apservice.h>
+#include <asm/ap1000/apreg.h>
+#include <asm/irq.h>
+
+#define INIT_TIM1 (781250/HZ)
+#define INIT_TIM0 (781250/(10*HZ))
+
+static unsigned long last_freerun;
+
+unsigned ap_freerun(void)
+{
+ return *((volatile unsigned long *)(MC_FREERUN + 4));
+}
+
+void ap_clear_clock_irq(void)
+{
+ MC_OUT(MC_INTR, AP_CLR_INTR_REQ << MC_INTR_ITIM1_SH);
+ last_freerun = *((unsigned long *)(MC_FREERUN + 4));
+ tnet_check_completion();
+#if 1
+ if ((((unsigned)jiffies) % (HZ/4)) == 0) {
+ msc_timer();
+ ap_xor_led(1);
+ bif_timer();
+ ap_dbg_flush();
+#if 0
+ bif_led_status();
+#endif
+ }
+#endif
+}
+
+
+void ap_gettimeofday(struct timeval *xt)
+{
+ unsigned long d;
+ unsigned v;
+ unsigned long new_freerun;
+
+ /* this is in 80ns units - we only use the low 32 bits
+ as 5mins is plenty for this stuff */
+ d = new_freerun = *((unsigned long *)(MC_FREERUN + 4));
+
+ if (d < last_freerun) {
+ /* wraparound */
+ d += ((~0) - last_freerun);
+ } else {
+ d -= last_freerun;
+ }
+
+ /* convert to microseconds */
+ v = ((d&0xffffff)*10)/125;
+
+ /* only want microseconds/HZ */
+ v = v%(1000000/HZ);
+
+ xt->tv_usec += v;
+
+ last_freerun = new_freerun;
+}
+
+
+static void profile_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ if (prof_buffer && current->pid) {
+ extern int _stext;
+ unsigned long ip = instruction_pointer(regs);
+ ip -= (unsigned long) &_stext;
+ ip >>= prof_shift;
+ if (ip < prof_len)
+ prof_buffer[ip]++;
+ }
+ MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM0_SH);
+}
+
+void ap_profile_init(void)
+{
+ if (prof_shift) {
+ printk("Initialising profiling with prof_shift=%d\n",(int)prof_shift);
+ MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM0_SH);
+ MC_OUT(MC_INTR,AP_CLR_INTR_MASK << MC_INTR_ITIM0_SH);
+ }
+}
+
+void ap_init_timers(void)
+{
+ extern void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+ unsigned flags;
+
+ printk("Initialising ap1000 timer\n");
+
+ save_flags(flags); cli();
+
+ request_irq(APTIM1_IRQ,
+ timer_interrupt,
+ (SA_INTERRUPT | SA_STATIC_ALLOC),
+ "timer", NULL);
+
+ request_irq(APTIM0_IRQ,
+ profile_interrupt,
+ (SA_INTERRUPT | SA_STATIC_ALLOC),
+ "profile", NULL);
+
+ ap_clear_clock_irq();
+
+ MC_OUT(MC_ITIMER0,INIT_TIM0);
+ MC_OUT(MC_ITIMER1,INIT_TIM1);
+ MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM1_SH);
+ MC_OUT(MC_INTR,AP_CLR_INTR_MASK << MC_INTR_ITIM1_SH);
+ MC_OUT(MC_INTR,AP_SET_INTR_MASK << MC_INTR_ITIM0_SH);
+ restore_flags(flags);
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov