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>
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>
50 #define TICK_SIZE (tick_nsec / 1000)
52 unsigned long cpu_khz
;
53 static inline int set_rtc_mmss(unsigned long nowtime
)
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 */
72 update_process_times(user_mode(get_irq_regs()));
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
;
86 last_rtc_update
= xtime
.tv_sec
- 600; /* do it again in 60 s */
89 write_sequnlock(&xtime_lock
);
95 unsigned int year
, mon
, day
, hour
, min
, sec
;
97 extern void arch_gettod(int *year
, int *mon
, int *day
, int *hour
,
100 cpu_khz
=nasys_clock_freq_1000
;
101 arch_gettod(&year
, &mon
, &day
, &hour
, &min
, &sec
);
103 if ((year
+= 1900) < 1970)
105 xtime
.tv_sec
= mktime(year
, mon
, day
, hour
, min
, sec
);
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
)
127 unsigned long usec
, sec
;
130 seq
= read_seqbegin_irqsave(&xtime_lock
, flags
);
131 usec
= 0; // For now use timeoffset 0
132 // usec = mach_gettimeoffset ? mach_gettimeoffset() : 0;
134 usec
+= (xtime
.tv_nsec
/ 1000);
135 } while (read_seqretry_irqrestore(&xtime_lock
, seq
, flags
));
137 while (usec
>= 1000000) {
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
)
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
);
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
);