android_kernel_xiaomi_sm8350/arch/v850/kernel/time.c

191 lines
4.4 KiB
C
Raw Normal View History

/*
* linux/arch/v850/kernel/time.c -- Arch-dependent timer functions
*
* Copyright (C) 1991, 1992, 1995, 2001, 2002 Linus Torvalds
*
* This file contains the v850-specific time handling details.
* Most of the stuff is located in the machine specific files.
*
* 1997-09-10 Updated NTP code according to technical memorandum Jan '96
* "A Kernel Model for Precision Timekeeping" by Dave Mills
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/profile.h>
#include <asm/io.h>
#include "mach.h"
#define TICK_SIZE (tick_nsec / 1000)
/*
* Scheduler clock - returns current time in nanosec units.
*/
unsigned long long sched_clock(void)
{
return (unsigned long long)jiffies * (1000000000 / HZ);
}
/*
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
{
#if 0
/* last time the cmos clock got updated */
static long last_rtc_update=0;
#endif
/* may need to kick the hardware timer */
if (mach_tick)
mach_tick ();
[PATCH] simplify update_times (avoid jiffies/jiffies_64 aliasing problem) Pass ticks to do_timer() and update_times(), and adjust x86_64 and s390 timer interrupt handler with this change. Currently update_times() calculates ticks by "jiffies - wall_jiffies", but callers of do_timer() should know how many ticks to update. Passing ticks get rid of this redundant calculation. Also there are another redundancy pointed out by Martin Schwidefsky. This cleanup make a barrier added by 5aee405c662ca644980c184774277fc6d0769a84 needless. So this patch removes it. As a bonus, this cleanup make wall_jiffies can be removed easily, since now wall_jiffies is always synced with jiffies. (This patch does not really remove wall_jiffies. It would be another cleanup patch) Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Cc: john stultz <johnstul@us.ibm.com> Cc: Andi Kleen <ak@muc.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Richard Henderson <rth@twiddle.net> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Acked-by: Russell King <rmk@arm.linux.org.uk> Cc: Ian Molton <spyro@f2s.com> Cc: Mikael Starvik <starvik@axis.com> Acked-by: David Howells <dhowells@redhat.com> Cc: Yoshinori Sato <ysato@users.sourceforge.jp> Cc: Hirokazu Takata <takata.hirokazu@renesas.com> Acked-by: Ralf Baechle <ralf@linux-mips.org> Cc: Kyle McMartin <kyle@mcmartin.ca> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Paul Mundt <lethal@linux-sh.org> Cc: Kazumoto Kojima <kkojima@rr.iij4u.or.jp> Cc: Richard Curnow <rc@rc0.org.uk> Cc: William Lee Irwin III <wli@holomorphy.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Cc: Miles Bader <uclinux-v850@lsi.nec.co.jp> Cc: Chris Zankel <chris@zankel.net> Acked-by: "Luck, Tony" <tony.luck@intel.com> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Roman Zippel <zippel@linux-m68k.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-29 05:00:32 -04:00
do_timer (1);
#ifndef CONFIG_SMP
update_process_times(user_mode(regs));
#endif
profile_tick(CPU_PROFILING, regs);
#if 0
/*
* If we have an externally synchronized Linux clock, then update
* CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
*/
if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
(xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
if (set_rtc_mmss (xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
}
#ifdef CONFIG_HEARTBEAT
/* use power LED as a heartbeat instead -- much more useful
for debugging -- based on the version for PReP by Cort */
/* acts like an actual heart beat -- ie thump-thump-pause... */
if (mach_heartbeat) {
static unsigned cnt = 0, period = 0, dist = 0;
if (cnt == 0 || cnt == dist)
mach_heartbeat ( 1 );
else if (cnt == 7 || cnt == dist+7)
mach_heartbeat ( 0 );
if (++cnt > period) {
cnt = 0;
/* The hyperbolic function below modifies the heartbeat period
* length in dependency of the current (5min) load. It goes
* through the points f(0)=126, f(1)=86, f(5)=51,
* f(inf)->30. */
period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
dist = period / 4;
}
}
#endif /* CONFIG_HEARTBEAT */
#endif /* 0 */
return IRQ_HANDLED;
}
/*
* This version of gettimeofday has near microsecond resolution.
*/
void do_gettimeofday (struct timeval *tv)
{
#if 0 /* DAVIDM later if possible */
extern volatile unsigned long lost_ticks;
unsigned long lost;
#endif
unsigned long flags;
unsigned long usec, sec;
unsigned long seq;
do {
seq = read_seqbegin_irqsave(&xtime_lock, flags);
#if 0
usec = mach_gettimeoffset ? mach_gettimeoffset () : 0;
#else
usec = 0;
#endif
#if 0 /* DAVIDM later if possible */
lost = lost_ticks;
if (lost)
usec += lost * (1000000/HZ);
#endif
sec = xtime.tv_sec;
usec += xtime.tv_nsec / 1000;
} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
while (usec >= 1000000) {
usec -= 1000000;
sec++;
}
tv->tv_sec = sec;
tv->tv_usec = usec;
}
EXPORT_SYMBOL(do_gettimeofday);
int do_settimeofday(struct timespec *tv)
{
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_nsec
* 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!
*/
#if 0
tv->tv_nsec -= mach_gettimeoffset() * 1000;
#endif
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
ntp_clear();
write_sequnlock_irq (&xtime_lock);
clock_was_set();
return 0;
}
EXPORT_SYMBOL(do_settimeofday);
static int timer_dev_id;
static struct irqaction timer_irqaction = {
timer_interrupt,
IRQF_DISABLED,
CPU_MASK_NONE,
"timer",
&timer_dev_id,
NULL
};
void time_init (void)
{
mach_gettimeofday (&xtime);
mach_sched_init (&timer_irqaction);
}