patch-2.4.9 linux/include/asm-arm/arch-sa1100/time.h

Next file: linux/include/asm-arm/arch-sa1100/uncompress.h
Previous file: linux/include/asm-arm/arch-sa1100/system.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.8/linux/include/asm-arm/arch-sa1100/time.h linux/include/asm-arm/arch-sa1100/time.h
@@ -5,11 +5,47 @@
  * Twiddles  (C) 1999 	Hugo Fiennes <hugo@empeg.com>
  * 
  * 2000/03/29 (C) Nicolas Pitre <nico@cam.org>
- *	Rewritten: big cleanup, much simpler, better HZ acuracy.
+ *	Rewritten: big cleanup, much simpler, better HZ accuracy.
  *
  */
 
 
+#define RTC_DEF_DIVIDER		32768 - 1
+#define RTC_DEF_TRIM            0
+
+static unsigned long __init sa1100_get_rtc_time(void)
+{
+	/*
+	 * According to the manual we should be able to let RTTR be zero
+	 * and then a default diviser for a 32.768KHz clock is used.
+	 * Apparently this doesn't work, at least for my SA1110 rev 5.
+	 * If the clock divider is uninitialized then reset it to the
+	 * default value to get the 1Hz clock.
+	 */
+	if (RTTR == 0) {
+		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+		printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n");
+		/* The current RTC value probably doesn't make sense either */
+		RCNR = 0;
+		return 0;
+	}
+	return RCNR;
+}
+
+static int sa1100_set_rtc(void)
+{
+	unsigned long current_time = xtime.tv_sec;
+
+	if (RTSR & RTSR_ALE) {
+		/* make sure not to forward the clock over an alarm */
+		unsigned long alarm = RTAR;
+		if (current_time >= alarm && alarm >= RCNR)
+			return -ERESTARTSYS;
+	}
+	RCNR = current_time;
+	return 0;
+}
+
 /* IRQs are disabled before entering here from do_gettimeofday() */
 static unsigned long sa1100_gettimeoffset (void)
 {
@@ -27,7 +63,6 @@
 	return usec;
 }
 
-
 static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	long flags;
@@ -41,6 +76,7 @@
 	 */
 	do {
 		do_leds();
+		do_set_rtc();
 		save_flags_cli( flags );
 		do_timer(regs);
 		OSSR = OSSR_M0;  /* Clear match on timer 0 */
@@ -49,10 +85,11 @@
 	} while( (signed long)(next_match - OSCR) <= 0 );
 }
 
-
-extern inline void setup_timer (void)
+static inline void setup_timer (void)
 {
 	gettimeoffset = sa1100_gettimeoffset;
+	set_rtc = sa1100_set_rtc;
+	xtime.tv_sec = sa1100_get_rtc_time();
 	timer_irq.handler = sa1100_timer_interrupt;
 	OSMR0 = 0;		/* set initial match at 0 */
 	OSSR = 0xf;		/* clear status on all timers */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)