patch-2.1.62 linux/arch/alpha/kernel/time.c
Next file: linux/drivers/block/ide-probe.c
Previous file: linux/Makefile
Back to the patch index
Back to the overall index
- Lines: 111
- Date:
Sat Nov 1 09:53:00 1997
- Orig file:
v2.1.61/linux/arch/alpha/kernel/time.c
- Orig date:
Wed Apr 16 14:14:59 1997
diff -u --recursive --new-file v2.1.61/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
@@ -12,6 +12,10 @@
* precision CMOS clock update
* 1997-01-09 Adrian Sun
* use interval timer if CONFIG_RTC=y
+ * 1997-10-29 John Bowman (bowman@math.ualberta.ca)
+ * fixed tick loss calculation in timer_interrupt
+ * (round system clock to nearest tick instead of truncating)
+ * fixed algorithm in time_init for getting time from CMOS clock
*/
#include <linux/errno.h>
#include <linux/sched.h>
@@ -23,6 +27,7 @@
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
+#include <asm/delay.h>
#include <linux/mc146818rtc.h>
#include <linux/timex.h>
@@ -45,10 +50,11 @@
*/
#define FIX_SHIFT 48
+static unsigned long round_ticks;
+
/* lump static variables together for more efficient access: */
static struct {
__u32 last_time; /* cycle counter last time it got invoked */
- __u32 max_cycles_per_tick; /* more makes us think we lost an interrupt */
unsigned long scaled_ticks_per_cycle; /* ticks/cycle * 2^48 */
long last_rtc_update; /* last time the cmos clock got updated */
} state;
@@ -70,19 +76,15 @@
void timer_interrupt(int irq, void *dev, struct pt_regs * regs)
{
__u32 delta, now;
+ int i, nticks;
now = rpcc();
delta = now - state.last_time;
state.last_time = now;
- if (delta > state.max_cycles_per_tick) {
- int i, missed_ticks;
-
- missed_ticks = ((delta * state.scaled_ticks_per_cycle) >> FIX_SHIFT) - 1;
- for (i = 0; i < missed_ticks; ++i) {
- do_timer(regs);
- }
+ nticks = ((delta * state.scaled_ticks_per_cycle+round_ticks) >> FIX_SHIFT);
+ for (i = 0; i < nticks; ++i) {
+ do_timer(regs);
}
- do_timer(regs);
/*
* If we have an externally synchronized Linux clock, then update
@@ -136,7 +138,6 @@
#endif
void (*irq_handler)(int, void *, struct pt_regs *);
unsigned int year, mon, day, hour, min, sec;
- int i;
/* The Linux interpretation of the CMOS clock register contents:
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
@@ -144,20 +145,23 @@
* Let's hope other operating systems interpret the RTC the same way.
*/
/* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
- } while (sec != CMOS_READ(RTC_SECONDS));
+ /* Wait for rise.... (may take up to 1 second) */
+
+ while(!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
+
+ /* Wait for fall.... */
+
+ while(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+
+ __delay(1000000);
+
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
{
BCD_TO_BIN(sec);
@@ -186,7 +190,7 @@
}
state.last_time = rpcc();
state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / hwrpb->cycle_freq;
- state.max_cycles_per_tick = (2 * hwrpb->cycle_freq) / HZ;
+ round_ticks=(unsigned long) 1 << (FIX_SHIFT-1);
state.last_rtc_update = 0;
#ifdef CONFIG_RTC
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov