2005-04-16 15:20:36 -07:00
/*
* linux / arch / h8300 / kernel / time . c
*
* Yoshinori Sato < ysato @ users . sourceforge . jp >
*
* Copied / hacked from :
*
* linux / arch / m68k / kernel / time . c
*
* Copyright ( C ) 1991 , 1992 , 1995 Linus Torvalds
*
* This file contains the m68k - 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/module.h>
# include <linux/sched.h>
# include <linux/kernel.h>
# include <linux/param.h>
# include <linux/string.h>
# include <linux/mm.h>
# include <linux/timex.h>
# include <linux/profile.h>
# include <asm/io.h>
# include <asm/target_time.h>
# define TICK_SIZE (tick_nsec / 1000)
/*
* timer_interrupt ( ) needs to keep up the real - time clock ,
* as well as call the " do_timer() " routine every clocktick
*/
static void timer_interrupt ( int irq , void * dummy , struct pt_regs * regs )
{
/* may need to kick the hardware timer */
platform_timer_eoi ( ) ;
2006-09-29 02:00:32 -07:00
do_timer ( 1 ) ;
2005-04-16 15:20:36 -07:00
# ifndef CONFIG_SMP
update_process_times ( user_mode ( regs ) ) ;
# endif
profile_tick ( CPU_PROFILING , regs ) ;
}
void time_init ( void )
{
unsigned int year , mon , day , hour , min , sec ;
/* FIX by dqg : Set to zero for platforms that don't have tod */
/* without this time is undefined and can overflow time_t, causing */
/* very stange errors */
year = 1980 ;
mon = day = 1 ;
hour = min = sec = 0 ;
platform_gettod ( & year , & mon , & day , & hour , & min , & sec ) ;
if ( ( year + = 1900 ) < 1970 )
year + = 100 ;
xtime . tv_sec = mktime ( year , mon , day , hour , min , sec ) ;
xtime . tv_nsec = 0 ;
platform_timer_setup ( timer_interrupt ) ;
}
/*
* This version of gettimeofday has near microsecond resolution .
*/
void do_gettimeofday ( struct timeval * tv )
{
unsigned long flags ;
unsigned long usec , sec ;
read_lock_irqsave ( & xtime_lock , flags ) ;
usec = 0 ;
sec = xtime . tv_sec ;
usec + = ( xtime . tv_nsec / 1000 ) ;
read_unlock_irqrestore ( & xtime_lock , 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_lock_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 !
*/
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 ;
2005-09-06 15:17:46 -07:00
ntp_clear ( ) ;
2005-04-16 15:20:36 -07:00
write_sequnlock_irq ( & xtime_lock ) ;
clock_was_set ( ) ;
return 0 ;
}
EXPORT_SYMBOL ( do_settimeofday ) ;
unsigned long long sched_clock ( void )
{
return ( unsigned long long ) jiffies * ( 1000000000 / HZ ) ;
}