2005-04-16 15:20:36 -07:00
/*
* 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/rtc.h>
2009-02-19 16:50:46 +01:00
# include <linux/platform_device.h>
2005-04-16 15:20:36 -07:00
# include <asm/machdep.h>
# include <asm/io.h>
2006-10-07 14:16:45 +01:00
# include <asm/irq_regs.h>
2005-04-16 15:20:36 -07:00
# include <linux/time.h>
# include <linux/timex.h>
# include <linux/profile.h>
static inline int set_rtc_mmss ( unsigned long nowtime )
{
if ( mach_set_clock_mmss )
return mach_set_clock_mmss ( nowtime ) ;
return - 1 ;
}
/*
* timer_interrupt ( ) needs to keep up the real - time clock ,
* as well as call the " do_timer() " routine every clocktick
*/
2006-10-07 14:16:45 +01:00
static irqreturn_t timer_interrupt ( int irq , void * dummy )
2005-04-16 15:20:36 -07:00
{
2006-09-29 02:00:32 -07:00
do_timer ( 1 ) ;
2005-04-16 15:20:36 -07:00
# ifndef CONFIG_SMP
2006-10-07 14:16:45 +01:00
update_process_times ( user_mode ( get_irq_regs ( ) ) ) ;
2005-04-16 15:20:36 -07:00
# endif
2006-10-07 14:16:45 +01:00
profile_tick ( CPU_PROFILING ) ;
2005-04-16 15:20:36 -07:00
# 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 ( 5 min ) 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 */
return IRQ_HANDLED ;
}
2007-07-20 04:33:28 +01:00
void __init time_init ( void )
2005-04-16 15:20:36 -07:00
{
struct rtc_time time ;
if ( mach_hwclk ) {
mach_hwclk ( 0 , & time ) ;
if ( ( time . tm_year + = 1900 ) < 1970 )
time . tm_year + = 100 ;
xtime . tv_sec = mktime ( time . tm_year , time . tm_mon , time . tm_mday ,
time . tm_hour , time . tm_min , time . tm_sec ) ;
xtime . tv_nsec = 0 ;
}
wall_to_monotonic . tv_sec = - xtime . tv_sec ;
mach_sched_init ( timer_interrupt ) ;
}
2009-09-21 17:04:05 -07:00
u32 arch_gettimeoffset ( void )
2005-04-16 15:20:36 -07:00
{
2009-09-21 17:04:05 -07:00
return mach_gettimeoffset ( ) * 1000 ;
2005-04-16 15:20:36 -07:00
}
2009-02-19 16:50:46 +01:00
static int __init rtc_init ( void )
{
struct platform_device * pdev ;
if ( ! mach_hwclk )
return - ENODEV ;
pdev = platform_device_register_simple ( " rtc-generic " , - 1 , NULL , 0 ) ;
if ( IS_ERR ( pdev ) )
return PTR_ERR ( pdev ) ;
return 0 ;
}
module_init ( rtc_init ) ;