[RFC][PATCH 3/8] Convert blackfin to use arch_getoffset() infrastructure.

john stultz
2009-04-15T01:43:39Z

This patch converts blackfin to use GENERIC_TIME via the
arch_getoffset() infrastructure

I do not have cross compilers for these architectures, and in some cases
the architectures can be compiles both with and without clocksources. So
I've taken my best swing at converting this, but I'm not confident I got
it right. Any assistance from arch maintainers or testers would be
great.

Signed-off-by: John Stultz <johnstul@us.ibm.com>

diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index 3640cdc..2b41547 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -606,9 +606,7 @@ comment "Kernel Timer/Scheduler"
source kernel/Kconfig.hz

config GENERIC_TIME
- bool "Generic time"
- depends on !SMP
- default y
+ def_bool y

config GENERIC_CLOCKEVENTS
bool "Generic clock events"
@@ -628,6 +626,10 @@ config CYCLES_CLOCKSOURCE
still be able to read it (such as for performance monitoring), but
writing the registers will most likely crash the kernel.

+config ARCH_USES_GETTIMEOFFSET
+ depends on !CYCLES_CLOCKSOURCE
+ def_bool y
+
source kernel/time/Kconfig

comment "Misc"
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index 1bbacfb..ddd1827 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -85,11 +85,11 @@ time_sched_init(irqreturn_t(*timer_routine) (int, void *))
#endif
}

+#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
/*
* Should return useconds since last timer tick
*/
-#ifndef CONFIG_GENERIC_TIME
-static unsigned long gettimeoffset(void)
+u32 arch_gettimeoffset(void)
{
unsigned long offset;
unsigned long clocks_per_jiffy;
@@ -199,64 +199,29 @@ void __init time_init(void)
time_sched_init(timer_interrupt);
}

-#ifndef CONFIG_GENERIC_TIME
-void do_gettimeofday(struct timeval *tv)
-{
- unsigned long flags;
- unsigned long seq;
- unsigned long usec, sec;
-
- do {
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
- usec = gettimeoffset();
- sec = xtime.tv_sec;
- usec += (xtime.tv_nsec / NSEC_PER_USEC);
- }
- while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
- while (usec >= USEC_PER_SEC) {
- usec -= USEC_PER_SEC;
- sec++;
- }
-
- tv->tv_sec = sec;
- tv->tv_usec = usec;
-}
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
+#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
+/*
+ * Should return nseconds since last timer tick
+ */
+u32 arch_gettimeoffset(void)
{
- time_t wtm_sec, sec = tv->tv_sec;
- long wtm_nsec, nsec = tv->tv_nsec;
-
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
- return -EINVAL;
-
- write_seqlock_irq(&xtime_lock);
- /*
- * This is revolting. We need to set the xtime.tv_usec
- * correctly. However, the value in this location is
- * is value at the last tick.
- * Discover what correction gettimeofday
- * would have done, and then undo it!
- */
- nsec -= (gettimeoffset() * NSEC_PER_USEC);
-
- wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
- wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
- set_normalized_timespec(&xtime, sec, nsec);
- set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+ unsigned long offset;
+ unsigned long clocks_per_jiffy;

- ntp_clear();
+ clocks_per_jiffy = bfin_read_TPERIOD();
+ offset =
+ (clocks_per_jiffy -
+ bfin_read_TCOUNT()) / (((clocks_per_jiffy + 1) * HZ) /
+ USEC_PER_SEC);

- write_sequnlock_irq(&xtime_lock);
- clock_was_set();
+ /* Check if we just wrapped the counters and maybe missed a tick */
+ if ((bfin_read_ILAT() & (1 << IRQ_CORETMR))
+ && (offset < (100000 / HZ / 2)))
+ offset += (USEC_PER_SEC / HZ);

- return 0;
+ return offset*1000;
}
-EXPORT_SYMBOL(do_settimeofday);
-#endif /* !CONFIG_GENERIC_TIME */
+#endif /* !CONFIG_ARCH_USES_GETTIMEOFFSET */

/*
* Scheduler clock - returns current time in nanosec units.