]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/h8300/kernel/time.c | |
3 | * | |
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | |
5 | * | |
6 | * Copied/hacked from: | |
7 | * | |
8 | * linux/arch/m68k/kernel/time.c | |
9 | * | |
10 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | |
11 | * | |
12 | * This file contains the m68k-specific time handling details. | |
13 | * Most of the stuff is located in the machine specific files. | |
14 | * | |
15 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 | |
16 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | |
17 | */ | |
18 | ||
1da177e4 LT |
19 | #include <linux/errno.h> |
20 | #include <linux/module.h> | |
21 | #include <linux/sched.h> | |
22 | #include <linux/kernel.h> | |
23 | #include <linux/param.h> | |
24 | #include <linux/string.h> | |
25 | #include <linux/mm.h> | |
26 | #include <linux/timex.h> | |
27 | #include <linux/profile.h> | |
28 | ||
29 | #include <asm/io.h> | |
30 | #include <asm/target_time.h> | |
31 | ||
32 | #define TICK_SIZE (tick_nsec / 1000) | |
33 | ||
1da177e4 LT |
34 | /* |
35 | * timer_interrupt() needs to keep up the real-time clock, | |
36 | * as well as call the "do_timer()" routine every clocktick | |
37 | */ | |
38 | static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs) | |
39 | { | |
40 | /* may need to kick the hardware timer */ | |
41 | platform_timer_eoi(); | |
42 | ||
3171a030 | 43 | do_timer(1); |
1da177e4 LT |
44 | #ifndef CONFIG_SMP |
45 | update_process_times(user_mode(regs)); | |
46 | #endif | |
47 | profile_tick(CPU_PROFILING, regs); | |
48 | } | |
49 | ||
50 | void time_init(void) | |
51 | { | |
52 | unsigned int year, mon, day, hour, min, sec; | |
53 | ||
54 | /* FIX by dqg : Set to zero for platforms that don't have tod */ | |
55 | /* without this time is undefined and can overflow time_t, causing */ | |
56 | /* very stange errors */ | |
57 | year = 1980; | |
58 | mon = day = 1; | |
59 | hour = min = sec = 0; | |
60 | platform_gettod (&year, &mon, &day, &hour, &min, &sec); | |
61 | ||
62 | if ((year += 1900) < 1970) | |
63 | year += 100; | |
64 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | |
65 | xtime.tv_nsec = 0; | |
66 | ||
67 | platform_timer_setup(timer_interrupt); | |
68 | } | |
69 | ||
70 | /* | |
71 | * This version of gettimeofday has near microsecond resolution. | |
72 | */ | |
73 | void do_gettimeofday(struct timeval *tv) | |
74 | { | |
75 | unsigned long flags; | |
76 | unsigned long usec, sec; | |
77 | ||
78 | read_lock_irqsave(&xtime_lock, flags); | |
79 | usec = 0; | |
80 | sec = xtime.tv_sec; | |
81 | usec += (xtime.tv_nsec / 1000); | |
82 | read_unlock_irqrestore(&xtime_lock, flags); | |
83 | ||
84 | while (usec >= 1000000) { | |
85 | usec -= 1000000; | |
86 | sec++; | |
87 | } | |
88 | ||
89 | tv->tv_sec = sec; | |
90 | tv->tv_usec = usec; | |
91 | } | |
92 | ||
93 | EXPORT_SYMBOL(do_gettimeofday); | |
94 | ||
95 | int do_settimeofday(struct timespec *tv) | |
96 | { | |
97 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | |
98 | return -EINVAL; | |
99 | ||
100 | write_lock_irq(&xtime_lock); | |
101 | /* This is revolting. We need to set the xtime.tv_usec | |
102 | * correctly. However, the value in this location is | |
103 | * is value at the last tick. | |
104 | * Discover what correction gettimeofday | |
105 | * would have done, and then undo it! | |
106 | */ | |
107 | while (tv->tv_nsec < 0) { | |
108 | tv->tv_nsec += NSEC_PER_SEC; | |
109 | tv->tv_sec--; | |
110 | } | |
111 | ||
112 | xtime.tv_sec = tv->tv_sec; | |
113 | xtime.tv_nsec = tv->tv_nsec; | |
b149ee22 | 114 | ntp_clear(); |
1da177e4 LT |
115 | write_sequnlock_irq(&xtime_lock); |
116 | clock_was_set(); | |
117 | return 0; | |
118 | } | |
119 | ||
120 | EXPORT_SYMBOL(do_settimeofday); |