MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / arch / nios2nommu / kernel / time.c
blob8f2fb58b58ebeccb73cd9058abc06a5f7abd4327
1 /*--------------------------------------------------------------------
3 * arch/nios2nommu/kernel/time.c
5 * Architecture specific time handling details.
7 * Derived from various works, Alpha, ix86, M68K, Sparc, ...et al
9 * Most of the stuff is located in the machine specific files.
11 * Copyright (C) 2004 Microtronix Datacom Ltd
12 * Copyright (C) 1998-2000 D. Jeff Dionne <jeff@lineo.ca>,
13 * Kenneth Albanowski <kjahds@kjahds.com>,
14 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
27 * Jan/20/2004 dgt NiosII
29 ---------------------------------------------------------------------*/
32 #include <linux/errno.h>
33 #include <linux/module.h>
34 #include <linux/sched.h>
35 #include <linux/kernel.h>
36 #include <linux/param.h>
37 #include <linux/string.h>
38 #include <linux/mm.h>
39 #include <linux/interrupt.h>
40 #include <linux/profile.h>
41 #include <linux/time.h>
42 #include <linux/timex.h>
43 #include <linux/irq.h>
45 #include <asm/segment.h>
46 #include <asm/io.h>
47 #include <asm/nios.h>
50 #define TICK_SIZE (tick_nsec / 1000)
52 unsigned long cpu_khz;
53 static inline int set_rtc_mmss(unsigned long nowtime)
55 return -1;
59 * timer_interrupt() needs to keep up the real-time clock,
60 * as well as call the "do_timer()" routine every clocktick
62 static irqreturn_t timer_interrupt(int irq, void *dummy)
64 /* last time the cmos clock got updated */
65 static long last_rtc_update=0;
67 write_seqlock(&xtime_lock);
68 na_timer0->np_timerstatus = 0; /* Clear the interrupt condition */
70 do_timer(1);
71 #ifndef CONFIG_SMP
72 update_process_times(user_mode(get_irq_regs()));
73 #endif
74 profile_tick(CPU_PROFILING);
76 * If we have an externally synchronized Linux clock, then update
77 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
78 * called as close as possible to 500 ms before the new second starts.
80 if (ntp_synced() && xtime.tv_sec > last_rtc_update + 660 &&
81 (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
82 (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
83 if (set_rtc_mmss(xtime.tv_sec) == 0)
84 last_rtc_update = xtime.tv_sec;
85 else
86 last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
89 write_sequnlock(&xtime_lock);
90 return(IRQ_HANDLED);
93 void time_init(void)
95 unsigned int year, mon, day, hour, min, sec;
97 extern void arch_gettod(int *year, int *mon, int *day, int *hour,
98 int *min, int *sec);
100 cpu_khz=nasys_clock_freq_1000;
101 arch_gettod(&year, &mon, &day, &hour, &min, &sec);
103 if ((year += 1900) < 1970)
104 year += 100;
105 xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
106 xtime.tv_nsec = 0;
107 wall_to_monotonic.tv_sec = -xtime.tv_sec;
109 request_irq(na_timer0_irq, timer_interrupt, IRQ_FLG_LOCK, "timer", NULL);
111 na_timer0->np_timerperiodl = (nasys_clock_freq/HZ)-1;
112 na_timer0->np_timerperiodh = ((nasys_clock_freq/HZ)-1) >> 16;
114 /* interrupt enable + continuous + start */
115 na_timer0->np_timercontrol = np_timercontrol_start_mask
116 + np_timercontrol_cont_mask
117 + np_timercontrol_ito_mask;
121 * This version of gettimeofday has near microsecond resolution.
123 void do_gettimeofday(struct timeval *tv)
125 unsigned long flags;
126 unsigned long seq;
127 unsigned long usec, sec;
129 do {
130 seq = read_seqbegin_irqsave(&xtime_lock, flags);
131 usec = 0; // For now use timeoffset 0
132 // usec = mach_gettimeoffset ? mach_gettimeoffset() : 0;
133 sec = xtime.tv_sec;
134 usec += (xtime.tv_nsec / 1000);
135 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
137 while (usec >= 1000000) {
138 usec -= 1000000;
139 sec++;
142 tv->tv_sec = sec;
143 tv->tv_usec = usec;
147 int do_settimeofday(struct timespec *tv)
149 time_t wtm_sec, sec = tv->tv_sec;
150 long wtm_nsec, nsec = tv->tv_nsec;
152 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
153 return -EINVAL;
155 write_seqlock_irq(&xtime_lock);
157 * This is revolting. We need to set "xtime" correctly. However, the
158 * value in this location is the value at the most recent update of
159 * wall time. Discover what correction gettimeofday() would have
160 * made, and then undo it!
161 * FIXME On m68knommu this is if (mach_gettimeoffset) nsec -= (mach_gettimeoffset() * 1000);
163 // nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
164 // nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
166 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
167 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
169 set_normalized_timespec(&xtime, sec, nsec);
170 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
172 time_adjust = 0; /* stop active adjtime() */
173 time_status |= STA_UNSYNC;
174 time_maxerror = NTP_PHASE_LIMIT;
175 time_esterror = NTP_PHASE_LIMIT;
176 write_sequnlock_irq(&xtime_lock);
177 clock_was_set();
178 return 0;
183 * Scheduler clock - returns current time in nanosec units.
185 unsigned long long sched_clock(void)
187 return (unsigned long long)jiffies * (1000000000 / HZ);
190 EXPORT_SYMBOL(do_gettimeofday);
191 EXPORT_SYMBOL(do_settimeofday);