[patch 2.6.20-rc2] ARM: AT91: clocksource for at91rm9200

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Define a clocksource for the at91rm9200, switching it to use GENERIC_TIME.
(No clockevent support; this is against 2.6.20-rc code.)

Also, slightly streamline reads of the 32KHz counter; if we hit the update
window, we can now use 3 reads not 4.

Signed-off-by: David Brownell <[email protected]>

---
We've been asked to forward stuff to LKML not ARM or RT lists, so ...

 arch/arm/mach-at91rm9200/Kconfig           |    1 
 arch/arm/mach-at91rm9200/at91rm9200_time.c |   47 ++++++++++++++++-------------
 2 files changed, 28 insertions(+), 20 deletions(-)

NOTE: at91sam926x chips need other solutions.  The sam9263 will have two
RTTs; one could work like this 32K timer and the other can be the system's
battery-backed RTC.  Otherwise the best bet may be the counter/timer module,
currently not usable from mainstream Linux patchsets.  If the board doesn't 
need one module for external interfacing, two 16-bit timers can chain to be
a clocksource (I have example code) and the third could issue clockevents
with the same precision (base is multi-MHz vs 32K).

Index: at91/arch/arm/mach-at91rm9200/Kconfig
===================================================================
--- at91.orig/arch/arm/mach-at91rm9200/Kconfig	2006-12-26 12:15:56.000000000 -0800
+++ at91/arch/arm/mach-at91rm9200/Kconfig	2006-12-26 12:16:04.000000000 -0800
@@ -7,6 +7,7 @@ choice
 
 config ARCH_AT91RM9200
 	bool "AT91RM9200"
+	select GENERIC_TIME
 
 config ARCH_AT91SAM9260
 	bool "AT91SAM9260"
Index: at91/arch/arm/mach-at91rm9200/at91rm9200_time.c
===================================================================
--- at91.orig/arch/arm/mach-at91rm9200/at91rm9200_time.c	2006-12-26 12:07:36.000000000 -0800
+++ at91/arch/arm/mach-at91rm9200/at91rm9200_time.c	2006-12-26 12:16:04.000000000 -0800
@@ -25,6 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/time.h>
+#include <linux/clocksource.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -38,33 +39,22 @@ static unsigned long last_crtr;
  * The ST_CRTR is updated asynchronously to the master clock.  It is therefore
  *  necessary to read it twice (with the same value) to ensure accuracy.
  */
-static inline unsigned long read_CRTR(void) {
+static inline unsigned long read_CRTR(void)
+{
 	unsigned long x1, x2;
 
-	do {
-		x1 = at91_sys_read(AT91_ST_CRTR);
+	x1 = at91_sys_read(AT91_ST_CRTR);
+	for (;;) {
 		x2 = at91_sys_read(AT91_ST_CRTR);
-	} while (x1 != x2);
+		if (x1 == x2)
+			break;
+		x1 = x2;
+	};
 
 	return x1;
 }
 
 /*
- * Returns number of microseconds since last timer interrupt.  Note that interrupts
- * will have been disabled by do_gettimeofday()
- *  'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
- *  'tick' is usecs per jiffy (linux/timex.h).
- */
-static unsigned long at91rm9200_gettimeoffset(void)
-{
-	unsigned long elapsed;
-
-	elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV;
-
-	return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
-}
-
-/*
  * IRQ handler for the timer.
  */
 static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
@@ -91,6 +81,20 @@ static struct irqaction at91rm9200_timer
 	.handler	= at91rm9200_timer_interrupt
 };
 
+static cycle_t read_clk32k(void)
+{
+	return read_CRTR();
+}
+
+static struct clocksource clk32k = {
+	.name		= "32k_counter",
+	.rating		= 200,
+	.read		= read_clk32k,
+	.mask		= CLOCKSOURCE_MASK(20),
+	.shift		= 10,
+	.is_continuous	= 1,
+};
+
 void at91rm9200_timer_reset(void)
 {
 	last_crtr = 0;
@@ -125,6 +129,10 @@ void __init at91rm9200_timer_init(void)
 
 	/* Initialize and enable the timer interrupt */
 	at91rm9200_timer_reset();
+
+	/* register clocksource */
+	clk32k.mult = clocksource_hz2mult(32768, clk32k.shift);
+	clocksource_register(&clk32k);
 }
 
 #ifdef CONFIG_PM
@@ -139,7 +147,6 @@ static void at91rm9200_timer_suspend(voi
 
 struct sys_timer at91rm9200_timer = {
 	.init		= at91rm9200_timer_init,
-	.offset		= at91rm9200_gettimeoffset,
 	.suspend	= at91rm9200_timer_suspend,
 	.resume		= at91rm9200_timer_reset,
 };
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux