diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-05-08 03:17:36 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-05-08 03:17:36 -0400 |
commit | b179b72fad5c88c3b616fb88a9ae7cbbc1a750d3 (patch) | |
tree | 705f19b9756654e8799191e1c3d7ea3b2b4e812d /arch/sh/kernel/time.c | |
parent | add47067a8ca324e9d26c4373350dc3cce7f1e7f (diff) |
sh: Rename arch/sh/kernel/time_32.c to arch/sh/kernel/time.c.
This is now fully generic, and used both by _32 and _64 variants.
Rename it accordingly.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/time.c')
-rw-r--r-- | arch/sh/kernel/time.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c new file mode 100644 index 000000000000..d41ca4cf20cf --- /dev/null +++ b/arch/sh/kernel/time.c | |||
@@ -0,0 +1,231 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/time_32.c | ||
3 | * | ||
4 | * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka | ||
5 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> | ||
6 | * Copyright (C) 2002 - 2009 Paul Mundt | ||
7 | * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> | ||
8 | * | ||
9 | * Some code taken from i386 version. | ||
10 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/profile.h> | ||
16 | #include <linux/timex.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/clockchips.h> | ||
19 | #include <linux/mc146818rtc.h> /* for rtc_lock */ | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <linux/rtc.h> | ||
23 | #include <asm/clock.h> | ||
24 | #include <asm/rtc.h> | ||
25 | #include <asm/timer.h> | ||
26 | #include <asm/kgdb.h> | ||
27 | |||
28 | struct sys_timer *sys_timer; | ||
29 | |||
30 | /* Move this somewhere more sensible.. */ | ||
31 | DEFINE_SPINLOCK(rtc_lock); | ||
32 | EXPORT_SYMBOL(rtc_lock); | ||
33 | |||
34 | /* Dummy RTC ops */ | ||
35 | static void null_rtc_get_time(struct timespec *tv) | ||
36 | { | ||
37 | tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0); | ||
38 | tv->tv_nsec = 0; | ||
39 | } | ||
40 | |||
41 | static int null_rtc_set_time(const time_t secs) | ||
42 | { | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; | ||
47 | int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; | ||
48 | |||
49 | unsigned int get_rtc_time(struct rtc_time *tm) | ||
50 | { | ||
51 | if (rtc_sh_get_time != null_rtc_get_time) { | ||
52 | struct timespec tv; | ||
53 | |||
54 | rtc_sh_get_time(&tv); | ||
55 | rtc_time_to_tm(tv.tv_sec, tm); | ||
56 | } | ||
57 | |||
58 | return RTC_24H; | ||
59 | } | ||
60 | EXPORT_SYMBOL(get_rtc_time); | ||
61 | |||
62 | int set_rtc_time(struct rtc_time *tm) | ||
63 | { | ||
64 | unsigned long secs; | ||
65 | |||
66 | rtc_tm_to_time(tm, &secs); | ||
67 | return rtc_sh_set_time(secs); | ||
68 | } | ||
69 | EXPORT_SYMBOL(set_rtc_time); | ||
70 | |||
71 | static int __init rtc_generic_init(void) | ||
72 | { | ||
73 | struct platform_device *pdev; | ||
74 | |||
75 | if (rtc_sh_get_time == null_rtc_get_time) | ||
76 | return -ENODEV; | ||
77 | |||
78 | pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); | ||
79 | if (IS_ERR(pdev)) | ||
80 | return PTR_ERR(pdev); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | module_init(rtc_generic_init); | ||
85 | |||
86 | /* last time the RTC clock got updated */ | ||
87 | static long last_rtc_update; | ||
88 | |||
89 | /* | ||
90 | * handle_timer_tick() needs to keep up the real-time clock, | ||
91 | * as well as call the "do_timer()" routine every clocktick | ||
92 | */ | ||
93 | void handle_timer_tick(void) | ||
94 | { | ||
95 | if (current->pid) | ||
96 | profile_tick(CPU_PROFILING); | ||
97 | |||
98 | /* | ||
99 | * Here we are in the timer irq handler. We just have irqs locally | ||
100 | * disabled but we don't know if the timer_bh is running on the other | ||
101 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need | ||
102 | * the irq version of write_lock because as just said we have irq | ||
103 | * locally disabled. -arca | ||
104 | */ | ||
105 | write_seqlock(&xtime_lock); | ||
106 | do_timer(1); | ||
107 | |||
108 | /* | ||
109 | * If we have an externally synchronized Linux clock, then update | ||
110 | * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | ||
111 | * called as close as possible to 500 ms before the new second starts. | ||
112 | */ | ||
113 | if (ntp_synced() && | ||
114 | xtime.tv_sec > last_rtc_update + 660 && | ||
115 | (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && | ||
116 | (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { | ||
117 | if (rtc_sh_set_time(xtime.tv_sec) == 0) | ||
118 | last_rtc_update = xtime.tv_sec; | ||
119 | else | ||
120 | /* do it again in 60s */ | ||
121 | last_rtc_update = xtime.tv_sec - 600; | ||
122 | } | ||
123 | write_sequnlock(&xtime_lock); | ||
124 | |||
125 | #ifndef CONFIG_SMP | ||
126 | update_process_times(user_mode(get_irq_regs())); | ||
127 | #endif | ||
128 | } | ||
129 | |||
130 | #ifdef CONFIG_PM | ||
131 | int timer_suspend(struct sys_device *dev, pm_message_t state) | ||
132 | { | ||
133 | struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev); | ||
134 | |||
135 | sys_timer->ops->stop(); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | int timer_resume(struct sys_device *dev) | ||
141 | { | ||
142 | struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev); | ||
143 | |||
144 | sys_timer->ops->start(); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | #else | ||
149 | #define timer_suspend NULL | ||
150 | #define timer_resume NULL | ||
151 | #endif | ||
152 | |||
153 | static struct sysdev_class timer_sysclass = { | ||
154 | .name = "timer", | ||
155 | .suspend = timer_suspend, | ||
156 | .resume = timer_resume, | ||
157 | }; | ||
158 | |||
159 | static int __init timer_init_sysfs(void) | ||
160 | { | ||
161 | int ret; | ||
162 | |||
163 | if (!sys_timer) | ||
164 | return 0; | ||
165 | |||
166 | ret = sysdev_class_register(&timer_sysclass); | ||
167 | if (ret != 0) | ||
168 | return ret; | ||
169 | |||
170 | sys_timer->dev.cls = &timer_sysclass; | ||
171 | return sysdev_register(&sys_timer->dev); | ||
172 | } | ||
173 | device_initcall(timer_init_sysfs); | ||
174 | |||
175 | void (*board_time_init)(void); | ||
176 | |||
177 | struct clocksource clocksource_sh = { | ||
178 | .name = "SuperH", | ||
179 | }; | ||
180 | |||
181 | unsigned long long sched_clock(void) | ||
182 | { | ||
183 | unsigned long long cycles; | ||
184 | |||
185 | /* jiffies based sched_clock if no clocksource is installed */ | ||
186 | if (!clocksource_sh.rating) | ||
187 | return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ); | ||
188 | |||
189 | cycles = clocksource_sh.read(&clocksource_sh); | ||
190 | return cyc2ns(&clocksource_sh, cycles); | ||
191 | } | ||
192 | |||
193 | static void __init sh_late_time_init(void) | ||
194 | { | ||
195 | /* | ||
196 | * Make sure all compiled-in early timers register themselves. | ||
197 | * Run probe() for one "earlytimer" device. | ||
198 | */ | ||
199 | early_platform_driver_register_all("earlytimer"); | ||
200 | if (early_platform_driver_probe("earlytimer", 1, 0)) | ||
201 | return; | ||
202 | |||
203 | /* | ||
204 | * Find the timer to use as the system timer, it will be | ||
205 | * initialized for us. | ||
206 | */ | ||
207 | sys_timer = get_sys_timer(); | ||
208 | if (unlikely(!sys_timer)) | ||
209 | panic("System timer missing.\n"); | ||
210 | |||
211 | printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); | ||
212 | } | ||
213 | |||
214 | void __init time_init(void) | ||
215 | { | ||
216 | if (board_time_init) | ||
217 | board_time_init(); | ||
218 | |||
219 | clk_init(); | ||
220 | |||
221 | rtc_sh_get_time(&xtime); | ||
222 | set_normalized_timespec(&wall_to_monotonic, | ||
223 | -xtime.tv_sec, -xtime.tv_nsec); | ||
224 | |||
225 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
226 | local_timer_setup(smp_processor_id()); | ||
227 | #endif | ||
228 | |||
229 | late_time_init = sh_late_time_init; | ||
230 | } | ||
231 | |||