patch-2.4.22 linux-2.4.22/arch/ia64/sn/kernel/sn2/timer.c
Next file: linux-2.4.22/arch/ia64/sn/kernel/sn_asm.S
Previous file: linux-2.4.22/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
Back to the patch index
Back to the overall index
- Lines: 101
- Date:
2003-08-25 04:44:39.000000000 -0700
- Orig file:
linux-2.4.21/arch/ia64/sn/kernel/sn2/timer.c
- Orig date:
1969-12-31 16:00:00.000000000 -0800
diff -urN linux-2.4.21/arch/ia64/sn/kernel/sn2/timer.c linux-2.4.22/arch/ia64/sn/kernel/sn2/timer.c
@@ -0,0 +1,100 @@
+/*
+ * linux/arch/ia64/sn/kernel/sn2/timer.c
+ *
+ * Copyright (C) 2003 Silicon Graphics, Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+
+#include <asm/hw_irq.h>
+#include <asm/system.h>
+
+#include <asm/sn/leds.h>
+#include <asm/sn/clksupport.h>
+
+
+extern unsigned long sn_rtc_cycles_per_second;
+static volatile unsigned long last_wall_rtc;
+
+/**
+ * gettimeoffset - number of usecs elapsed since &xtime was last updated
+ *
+ * This function is used by do_gettimeofday() to determine the number
+ * of usecs that have elapsed since the last update to &xtime. On SN
+ * this is accomplished using the RTC built in to each Hub chip; each
+ * is guaranteed to be synchronized by the PROM, so a local read will
+ * suffice (GET_RTC_COUNTER() does this for us). A snapshot of the RTC
+ * value is taken every time wall_jiffies is updated by the
+ * update_wall_time_hook (sn2_update_wall_time) which means we don't
+ * have to adjust for lost jiffies ticks or anything like that.
+ */
+extern unsigned long wall_jiffies; /* from kernel/timer.c */
+
+static volatile long rtc_offset;
+static long rtc_cycles_per_usec;
+static long rtc_per_timer_tick;
+
+unsigned long
+sn_gettimeoffset(void)
+{
+ long current_rtc, elapsed_rtc, old, new_offset;
+
+ do {
+ old = rtc_offset;
+ current_rtc = GET_RTC_COUNTER();
+
+ /*
+ * Need to address wrapping here!
+ */
+ elapsed_rtc = (long)(current_rtc - last_wall_rtc);
+
+ /*
+ * This case is non lethal as the max() will take care of it.
+ */
+#if 0
+ if (elapsed_rtc < 0) {
+ printk(KERN_ERR "sn_gettimeoffset(): time goes "
+ "backwards!\n current_rtc 0x%016lx, "
+ "last_wall_rtc 0x%016lx, elapsed %08lx, "
+ "offset %li\n", current_rtc, last_wall_rtc,
+ elapsed_rtc, max(elapsed_rtc, rtc_offset)/
+ rtc_cycles_per_usec);
+ }
+#endif
+
+ new_offset = max(elapsed_rtc, old);
+ } while (cmpxchg(&rtc_offset, old, new_offset) != old);
+
+ return new_offset / rtc_cycles_per_usec;
+}
+
+
+void sn2_update_wall_time(void)
+{
+ rtc_offset -= min(rtc_offset, rtc_per_timer_tick);
+ last_wall_rtc = GET_RTC_COUNTER();
+}
+
+
+void sn2_reset_wall_time(void)
+{
+ rtc_offset = 0;
+ last_wall_rtc = GET_RTC_COUNTER();
+}
+
+
+void __init
+sn_timer_init(void)
+{
+ rtc_per_timer_tick = sn_rtc_cycles_per_second / HZ;
+ rtc_cycles_per_usec = sn_rtc_cycles_per_second / 1000000;
+
+ last_wall_rtc = GET_RTC_COUNTER();
+ update_wall_time_hook = sn2_update_wall_time;
+ reset_wall_time_hook = sn2_reset_wall_time;
+ gettimeoffset = sn_gettimeoffset;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)