1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/errno.h>
18#include <linux/rwsem.h>
19#include <linux/sched.h>
20#include <linux/kernel.h>
21#include <linux/param.h>
22#include <linux/string.h>
23#include <linux/mm.h>
24#include <linux/interrupt.h>
25#include <linux/time.h>
26#include <linux/delay.h>
27#include <linux/init.h>
28#include <linux/profile.h>
29#include <linux/smp.h>
30#include <linux/module.h>
31#include <linux/bcd.h>
32#include <linux/timex.h>
33#include <linux/irq.h>
34#include <linux/io.h>
35#include <linux/platform_device.h>
36#include <cpu/registers.h>
37#include <cpu/irq.h>
38#include <asm/addrspace.h>
39#include <asm/processor.h>
40#include <asm/uaccess.h>
41#include <asm/delay.h>
42#include <asm/clock.h>
43
44#define TMU_TOCR_INIT 0x00
45#define TMU0_TCR_INIT 0x0020
46#define TMU_TSTR_INIT 1
47#define TMU_TSTR_OFF 0
48
49
50#define RTC_BLOCK_OFF 0x01040000
51#define RTC_BASE PHYS_PERIPHERAL_BLOCK + RTC_BLOCK_OFF
52#define RTC_RCR1_CIE 0x10
53#define RTC_RCR1 (rtc_base + 0x38)
54
55
56#define TMU_BLOCK_OFF 0x01020000
57#define TMU_BASE PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
58#define TMU0_BASE tmu_base + 0x8 + (0xc * 0x0)
59#define TMU1_BASE tmu_base + 0x8 + (0xc * 0x1)
60#define TMU2_BASE tmu_base + 0x8 + (0xc * 0x2)
61
62#define TMU_TOCR tmu_base+0x0
63#define TMU_TSTR tmu_base+0x4
64
65#define TMU0_TCOR TMU0_BASE+0x0
66#define TMU0_TCNT TMU0_BASE+0x4
67#define TMU0_TCR TMU0_BASE+0x8
68
69#define TICK_SIZE (tick_nsec / 1000)
70
71static unsigned long tmu_base, rtc_base;
72unsigned long cprc_base;
73
74
75
76
77
78static unsigned long ctc_last_interrupt;
79static unsigned long long usecs_per_jiffy = 1000000/HZ;
80
81#define CTC_JIFFY_SCALE_SHIFT 40
82
83
84static unsigned long long scaled_recip_ctc_ticks_per_jiffy;
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106static unsigned long usecs_since_tick(void)
107{
108 unsigned long long current_ctc;
109 long ctc_ticks_since_interrupt;
110 unsigned long long ull_ctc_ticks_since_interrupt;
111 unsigned long result;
112
113 unsigned long long mul1_out;
114 unsigned long long mul1_out_high;
115 unsigned long long mul2_out_low, mul2_out_high;
116
117
118 asm ("getcon cr62, %0" : "=r" (current_ctc));
119
120
121
122 ctc_ticks_since_interrupt = (long) ctc_last_interrupt - (long) current_ctc;
123 ull_ctc_ticks_since_interrupt = (unsigned long long) ctc_ticks_since_interrupt;
124
125
126 asm volatile ("mulu.l %1, %2, %0" :
127 "=r" (mul1_out) :
128 "r" (ull_ctc_ticks_since_interrupt), "r" (usecs_per_jiffy));
129
130 mul1_out_high = mul1_out >> 32;
131
132 asm volatile ("mulu.l %1, %2, %0" :
133 "=r" (mul2_out_low) :
134 "r" (mul1_out), "r" (scaled_recip_ctc_ticks_per_jiffy));
135
136#if 1
137 asm volatile ("mulu.l %1, %2, %0" :
138 "=r" (mul2_out_high) :
139 "r" (mul1_out_high), "r" (scaled_recip_ctc_ticks_per_jiffy));
140#endif
141
142 result = (unsigned long) (((mul2_out_high << 32) + mul2_out_low) >> CTC_JIFFY_SCALE_SHIFT);
143
144 return result;
145}
146
147void do_gettimeofday(struct timeval *tv)
148{
149 unsigned long flags;
150 unsigned long seq;
151 unsigned long usec, sec;
152
153 do {
154 seq = read_seqbegin_irqsave(&xtime_lock, flags);
155 usec = usecs_since_tick();
156 sec = xtime.tv_sec;
157 usec += xtime.tv_nsec / 1000;
158 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
159
160 while (usec >= 1000000) {
161 usec -= 1000000;
162 sec++;
163 }
164
165 tv->tv_sec = sec;
166 tv->tv_usec = usec;
167}
168EXPORT_SYMBOL(do_gettimeofday);
169
170int do_settimeofday(struct timespec *tv)
171{
172 time_t wtm_sec, sec = tv->tv_sec;
173 long wtm_nsec, nsec = tv->tv_nsec;
174
175 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
176 return -EINVAL;
177
178 write_seqlock_irq(&xtime_lock);
179
180
181
182
183
184
185 nsec -= 1000 * usecs_since_tick();
186
187 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
188 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
189
190 set_normalized_timespec(&xtime, sec, nsec);
191 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
192
193 ntp_clear();
194 write_sequnlock_irq(&xtime_lock);
195 clock_was_set();
196
197 return 0;
198}
199EXPORT_SYMBOL(do_settimeofday);
200
201
202static void null_rtc_get_time(struct timespec *tv)
203{
204 tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
205 tv->tv_nsec = 0;
206}
207
208static int null_rtc_set_time(const time_t secs)
209{
210 return 0;
211}
212
213void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
214int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
215
216
217static long last_rtc_update;
218
219
220
221
222
223static inline void do_timer_interrupt(void)
224{
225 unsigned long long current_ctc;
226
227 if (current->pid)
228 profile_tick(CPU_PROFILING);
229
230
231
232
233
234
235
236
237 write_seqlock(&xtime_lock);
238 asm ("getcon cr62, %0" : "=r" (current_ctc));
239 ctc_last_interrupt = (unsigned long) current_ctc;
240
241 do_timer(1);
242
243#ifdef CONFIG_HEARTBEAT
244 if (sh_mv.mv_heartbeat != NULL)
245 sh_mv.mv_heartbeat();
246#endif
247
248
249
250
251
252
253 if (ntp_synced() &&
254 xtime.tv_sec > last_rtc_update + 660 &&
255 (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
256 (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
257 if (rtc_sh_set_time(xtime.tv_sec) == 0)
258 last_rtc_update = xtime.tv_sec;
259 else
260
261 last_rtc_update = xtime.tv_sec - 600;
262 }
263 write_sequnlock(&xtime_lock);
264
265#ifndef CONFIG_SMP
266 update_process_times(user_mode(get_irq_regs()));
267#endif
268}
269
270
271
272
273
274
275static irqreturn_t timer_interrupt(int irq, void *dev_id)
276{
277 unsigned long timer_status;
278
279
280 timer_status = ctrl_inw(TMU0_TCR);
281 timer_status &= ~0x100;
282 ctrl_outw(timer_status, TMU0_TCR);
283
284 do_timer_interrupt();
285
286 return IRQ_HANDLED;
287}
288
289static struct irqaction irq0 = {
290 .handler = timer_interrupt,
291 .flags = IRQF_DISABLED,
292 .mask = CPU_MASK_NONE,
293 .name = "timer",
294};
295
296void __init time_init(void)
297{
298 unsigned long interval;
299 struct clk *clk;
300
301 tmu_base = onchip_remap(TMU_BASE, 1024, "TMU");
302 if (!tmu_base) {
303 panic("Unable to remap TMU\n");
304 }
305
306 rtc_base = onchip_remap(RTC_BASE, 1024, "RTC");
307 if (!rtc_base) {
308 panic("Unable to remap RTC\n");
309 }
310
311 clk = clk_get(NULL, "cpu_clk");
312 scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) /
313 (unsigned long long)(clk_get_rate(clk) / HZ));
314
315 rtc_sh_get_time(&xtime);
316
317 setup_irq(TIMER_IRQ, &irq0);
318
319 clk = clk_get(NULL, "module_clk");
320 interval = (clk_get_rate(clk)/(HZ*4));
321
322 printk("Interval = %ld\n", interval);
323
324
325 ctrl_outb(TMU_TSTR_OFF, TMU_TSTR);
326 ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
327 ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
328 ctrl_outl(interval, TMU0_TCOR);
329 ctrl_outl(interval, TMU0_TCNT);
330 ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
331}
332
333static struct resource rtc_resources[] = {
334 [0] = {
335
336 .flags = IORESOURCE_IO,
337 },
338 [1] = {
339
340 .start = IRQ_PRI,
341 .flags = IORESOURCE_IRQ,
342 },
343 [2] = {
344
345 .start = IRQ_CUI,
346 .flags = IORESOURCE_IRQ,
347 },
348 [3] = {
349
350 .start = IRQ_ATI,
351 .flags = IORESOURCE_IRQ,
352 },
353};
354
355static struct platform_device rtc_device = {
356 .name = "sh-rtc",
357 .id = -1,
358 .num_resources = ARRAY_SIZE(rtc_resources),
359 .resource = rtc_resources,
360};
361
362static int __init rtc_init(void)
363{
364 rtc_resources[0].start = rtc_base;
365 rtc_resources[0].end = rtc_resources[0].start + 0x58 - 1;
366
367 return platform_device_register(&rtc_device);
368}
369device_initcall(rtc_init);
370