X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=arch%2Fsparc%2Fkernel%2Ftime.c;h=6c7aa51b590fd5c7d0d10d457698d9c9146a157b;hp=9631e8f4ae60cc669e47b21451dfbf195259ec13;hb=cde49b058474ab3f7ff830283e5b538e8fbeefe5;hpb=74e651f0aa100f3e5d3432a8dd8869c089e8d72f diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 9631e8f4ae60..6c7aa51b590f 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -15,7 +15,6 @@ * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 * "A Kernel Model for Precision Timekeeping" by Dave Mills */ -#include #include #include #include @@ -43,8 +42,7 @@ #include #include #include - -extern unsigned long wall_jiffies; +#include DEFINE_SPINLOCK(rtc_lock); enum sparc_clock_type sp_clock_typ; @@ -97,6 +95,8 @@ unsigned long profile_pc(struct pt_regs *regs) return pc; } +EXPORT_SYMBOL(profile_pc); + __volatile__ unsigned int *master_l10_counter; __volatile__ unsigned int *master_l10_limit; @@ -107,13 +107,13 @@ __volatile__ unsigned int *master_l10_limit; #define TICK_SIZE (tick_nsec / 1000) -irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +irqreturn_t timer_interrupt(int irq, void *dev_id) { /* last time the cmos clock got updated */ static long last_rtc_update; #ifndef CONFIG_SMP - profile_tick(CPU_PROFILING, regs); + profile_tick(CPU_PROFILING); #endif /* Protect counter clear so that do_gettimeoffset works */ @@ -129,9 +129,9 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) #endif clear_clock_irq(); - do_timer(regs); + do_timer(1); #ifndef CONFIG_SMP - update_process_times(user_mode(regs)); + update_process_times(user_mode(get_irq_regs())); #endif @@ -226,6 +226,32 @@ static __inline__ int has_low_battery(void) return (data1 == data2); /* Was the write blocked? */ } +static void __init mostek_set_system_time(void) +{ + unsigned int year, mon, day, hour, min, sec; + struct mostek48t02 *mregs; + + mregs = (struct mostek48t02 *)mstk48t02_regs; + if(!mregs) { + prom_printf("Something wrong, clock regs not mapped yet.\n"); + prom_halt(); + } + spin_lock_irq(&mostek_lock); + mregs->creg |= MSTK_CREG_READ; + sec = MSTK_REG_SEC(mregs); + min = MSTK_REG_MIN(mregs); + hour = MSTK_REG_HOUR(mregs); + day = MSTK_REG_DOM(mregs); + mon = MSTK_REG_MONTH(mregs); + year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); + mregs->creg &= ~MSTK_CREG_READ; + spin_unlock_irq(&mostek_lock); +} + /* Probe for the real time clock chip on Sun4 */ static __inline__ void sun4_clock_probe(void) { @@ -274,6 +300,7 @@ static __inline__ void sun4_clock_probe(void) #endif } +#ifndef CONFIG_SUN4 static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; @@ -308,6 +335,8 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) kick_start_clock(); + mostek_set_system_time(); + return 0; } @@ -326,56 +355,37 @@ static struct of_platform_driver clock_driver = { /* Probe for the mostek real time clock chip. */ -static void clock_init(void) +static int __init clock_init(void) { - of_register_driver(&clock_driver, &of_bus_type); + return of_register_driver(&clock_driver, &of_bus_type); } +/* Must be after subsys_initcall() so that busses are probed. Must + * be before device_initcall() because things like the RTC driver + * need to see the clock registers. + */ +fs_initcall(clock_init); +#endif /* !CONFIG_SUN4 */ + void __init sbus_time_init(void) { - unsigned int year, mon, day, hour, min, sec; - struct mostek48t02 *mregs; - -#ifdef CONFIG_SUN4 - int temp; - struct intersil *iregs; -#endif BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); btfixup(); if (ARCH_SUN4) sun4_clock_probe(); - else - clock_init(); sparc_init_timers(timer_interrupt); #ifdef CONFIG_SUN4 if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { -#endif - mregs = (struct mostek48t02 *)mstk48t02_regs; - if(!mregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - spin_lock_irq(&mostek_lock); - mregs->creg |= MSTK_CREG_READ; - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - mregs->creg &= ~MSTK_CREG_READ; - spin_unlock_irq(&mostek_lock); -#ifdef CONFIG_SUN4 + mostek_set_system_time(); } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { /* initialise the intersil on sun4 */ + unsigned int year, mon, day, hour, min, sec; + int temp; + struct intersil *iregs; iregs=intersil_clock; if(!iregs) { @@ -440,7 +450,7 @@ unsigned long long sched_clock(void) /* Ok, my cute asm atomicity trick doesn't work anymore. * There are just too many variables that need to be protected - * now (both members of xtime, wall_jiffies, et al.) + * now (both members of xtime, et al.) */ void do_gettimeofday(struct timeval *tv) { @@ -450,26 +460,17 @@ void do_gettimeofday(struct timeval *tv) unsigned long max_ntp_tick = tick_usec - tickadj; do { - unsigned long lost; - seq = read_seqbegin_irqsave(&xtime_lock, flags); usec = do_gettimeoffset(); - lost = jiffies - wall_jiffies; /* * If time_adjust is negative then NTP is slowing the clock * so make sure not to go into next possible interval. * Better to lose some accuracy than have time go backwards.. */ - if (unlikely(time_adjust < 0)) { + if (unlikely(time_adjust < 0)) usec = min(usec, max_ntp_tick); - if (lost) - usec += lost * max_ntp_tick; - } - else if (unlikely(lost)) - usec += lost * tick_usec; - sec = xtime.tv_sec; usec += (xtime.tv_nsec / 1000); } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); @@ -512,8 +513,7 @@ static int sbus_do_settimeofday(struct timespec *tv) * wall time. Discover what correction gettimeofday() would have * made, and then undo it! */ - nsec -= 1000 * (do_gettimeoffset() + - (jiffies - wall_jiffies) * (USEC_PER_SEC / HZ)); + nsec -= 1000 * do_gettimeoffset(); wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);