diff options
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r-- | arch/sparc64/kernel/time.c | 862 |
1 files changed, 0 insertions, 862 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c deleted file mode 100644 index 141da3759091..000000000000 --- a/arch/sparc64/kernel/time.c +++ /dev/null | |||
@@ -1,862 +0,0 @@ | |||
1 | /* time.c: UltraSparc timer and TOD clock support. | ||
2 | * | ||
3 | * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net) | ||
4 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) | ||
5 | * | ||
6 | * Based largely on code which is: | ||
7 | * | ||
8 | * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) | ||
9 | */ | ||
10 | |||
11 | #include <linux/errno.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/smp_lock.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/param.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/time.h> | ||
21 | #include <linux/timex.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/ioport.h> | ||
24 | #include <linux/mc146818rtc.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/profile.h> | ||
27 | #include <linux/bcd.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | #include <linux/cpufreq.h> | ||
30 | #include <linux/percpu.h> | ||
31 | #include <linux/miscdevice.h> | ||
32 | #include <linux/rtc.h> | ||
33 | #include <linux/rtc/m48t59.h> | ||
34 | #include <linux/kernel_stat.h> | ||
35 | #include <linux/clockchips.h> | ||
36 | #include <linux/clocksource.h> | ||
37 | #include <linux/of_device.h> | ||
38 | #include <linux/platform_device.h> | ||
39 | |||
40 | #include <asm/oplib.h> | ||
41 | #include <asm/timer.h> | ||
42 | #include <asm/irq.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/prom.h> | ||
45 | #include <asm/starfire.h> | ||
46 | #include <asm/smp.h> | ||
47 | #include <asm/sections.h> | ||
48 | #include <asm/cpudata.h> | ||
49 | #include <asm/uaccess.h> | ||
50 | #include <asm/irq_regs.h> | ||
51 | |||
52 | #include "entry.h" | ||
53 | |||
54 | DEFINE_SPINLOCK(rtc_lock); | ||
55 | |||
56 | #define TICK_PRIV_BIT (1UL << 63) | ||
57 | #define TICKCMP_IRQ_BIT (1UL << 63) | ||
58 | |||
59 | #ifdef CONFIG_SMP | ||
60 | unsigned long profile_pc(struct pt_regs *regs) | ||
61 | { | ||
62 | unsigned long pc = instruction_pointer(regs); | ||
63 | |||
64 | if (in_lock_functions(pc)) | ||
65 | return regs->u_regs[UREG_RETPC]; | ||
66 | return pc; | ||
67 | } | ||
68 | EXPORT_SYMBOL(profile_pc); | ||
69 | #endif | ||
70 | |||
71 | static void tick_disable_protection(void) | ||
72 | { | ||
73 | /* Set things up so user can access tick register for profiling | ||
74 | * purposes. Also workaround BB_ERRATA_1 by doing a dummy | ||
75 | * read back of %tick after writing it. | ||
76 | */ | ||
77 | __asm__ __volatile__( | ||
78 | " ba,pt %%xcc, 1f\n" | ||
79 | " nop\n" | ||
80 | " .align 64\n" | ||
81 | "1: rd %%tick, %%g2\n" | ||
82 | " add %%g2, 6, %%g2\n" | ||
83 | " andn %%g2, %0, %%g2\n" | ||
84 | " wrpr %%g2, 0, %%tick\n" | ||
85 | " rdpr %%tick, %%g0" | ||
86 | : /* no outputs */ | ||
87 | : "r" (TICK_PRIV_BIT) | ||
88 | : "g2"); | ||
89 | } | ||
90 | |||
91 | static void tick_disable_irq(void) | ||
92 | { | ||
93 | __asm__ __volatile__( | ||
94 | " ba,pt %%xcc, 1f\n" | ||
95 | " nop\n" | ||
96 | " .align 64\n" | ||
97 | "1: wr %0, 0x0, %%tick_cmpr\n" | ||
98 | " rd %%tick_cmpr, %%g0" | ||
99 | : /* no outputs */ | ||
100 | : "r" (TICKCMP_IRQ_BIT)); | ||
101 | } | ||
102 | |||
103 | static void tick_init_tick(void) | ||
104 | { | ||
105 | tick_disable_protection(); | ||
106 | tick_disable_irq(); | ||
107 | } | ||
108 | |||
109 | static unsigned long tick_get_tick(void) | ||
110 | { | ||
111 | unsigned long ret; | ||
112 | |||
113 | __asm__ __volatile__("rd %%tick, %0\n\t" | ||
114 | "mov %0, %0" | ||
115 | : "=r" (ret)); | ||
116 | |||
117 | return ret & ~TICK_PRIV_BIT; | ||
118 | } | ||
119 | |||
120 | static int tick_add_compare(unsigned long adj) | ||
121 | { | ||
122 | unsigned long orig_tick, new_tick, new_compare; | ||
123 | |||
124 | __asm__ __volatile__("rd %%tick, %0" | ||
125 | : "=r" (orig_tick)); | ||
126 | |||
127 | orig_tick &= ~TICKCMP_IRQ_BIT; | ||
128 | |||
129 | /* Workaround for Spitfire Errata (#54 I think??), I discovered | ||
130 | * this via Sun BugID 4008234, mentioned in Solaris-2.5.1 patch | ||
131 | * number 103640. | ||
132 | * | ||
133 | * On Blackbird writes to %tick_cmpr can fail, the | ||
134 | * workaround seems to be to execute the wr instruction | ||
135 | * at the start of an I-cache line, and perform a dummy | ||
136 | * read back from %tick_cmpr right after writing to it. -DaveM | ||
137 | */ | ||
138 | __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" | ||
139 | " add %1, %2, %0\n\t" | ||
140 | ".align 64\n" | ||
141 | "1:\n\t" | ||
142 | "wr %0, 0, %%tick_cmpr\n\t" | ||
143 | "rd %%tick_cmpr, %%g0\n\t" | ||
144 | : "=r" (new_compare) | ||
145 | : "r" (orig_tick), "r" (adj)); | ||
146 | |||
147 | __asm__ __volatile__("rd %%tick, %0" | ||
148 | : "=r" (new_tick)); | ||
149 | new_tick &= ~TICKCMP_IRQ_BIT; | ||
150 | |||
151 | return ((long)(new_tick - (orig_tick+adj))) > 0L; | ||
152 | } | ||
153 | |||
154 | static unsigned long tick_add_tick(unsigned long adj) | ||
155 | { | ||
156 | unsigned long new_tick; | ||
157 | |||
158 | /* Also need to handle Blackbird bug here too. */ | ||
159 | __asm__ __volatile__("rd %%tick, %0\n\t" | ||
160 | "add %0, %1, %0\n\t" | ||
161 | "wrpr %0, 0, %%tick\n\t" | ||
162 | : "=&r" (new_tick) | ||
163 | : "r" (adj)); | ||
164 | |||
165 | return new_tick; | ||
166 | } | ||
167 | |||
168 | static struct sparc64_tick_ops tick_operations __read_mostly = { | ||
169 | .name = "tick", | ||
170 | .init_tick = tick_init_tick, | ||
171 | .disable_irq = tick_disable_irq, | ||
172 | .get_tick = tick_get_tick, | ||
173 | .add_tick = tick_add_tick, | ||
174 | .add_compare = tick_add_compare, | ||
175 | .softint_mask = 1UL << 0, | ||
176 | }; | ||
177 | |||
178 | struct sparc64_tick_ops *tick_ops __read_mostly = &tick_operations; | ||
179 | |||
180 | static void stick_disable_irq(void) | ||
181 | { | ||
182 | __asm__ __volatile__( | ||
183 | "wr %0, 0x0, %%asr25" | ||
184 | : /* no outputs */ | ||
185 | : "r" (TICKCMP_IRQ_BIT)); | ||
186 | } | ||
187 | |||
188 | static void stick_init_tick(void) | ||
189 | { | ||
190 | /* Writes to the %tick and %stick register are not | ||
191 | * allowed on sun4v. The Hypervisor controls that | ||
192 | * bit, per-strand. | ||
193 | */ | ||
194 | if (tlb_type != hypervisor) { | ||
195 | tick_disable_protection(); | ||
196 | tick_disable_irq(); | ||
197 | |||
198 | /* Let the user get at STICK too. */ | ||
199 | __asm__ __volatile__( | ||
200 | " rd %%asr24, %%g2\n" | ||
201 | " andn %%g2, %0, %%g2\n" | ||
202 | " wr %%g2, 0, %%asr24" | ||
203 | : /* no outputs */ | ||
204 | : "r" (TICK_PRIV_BIT) | ||
205 | : "g1", "g2"); | ||
206 | } | ||
207 | |||
208 | stick_disable_irq(); | ||
209 | } | ||
210 | |||
211 | static unsigned long stick_get_tick(void) | ||
212 | { | ||
213 | unsigned long ret; | ||
214 | |||
215 | __asm__ __volatile__("rd %%asr24, %0" | ||
216 | : "=r" (ret)); | ||
217 | |||
218 | return ret & ~TICK_PRIV_BIT; | ||
219 | } | ||
220 | |||
221 | static unsigned long stick_add_tick(unsigned long adj) | ||
222 | { | ||
223 | unsigned long new_tick; | ||
224 | |||
225 | __asm__ __volatile__("rd %%asr24, %0\n\t" | ||
226 | "add %0, %1, %0\n\t" | ||
227 | "wr %0, 0, %%asr24\n\t" | ||
228 | : "=&r" (new_tick) | ||
229 | : "r" (adj)); | ||
230 | |||
231 | return new_tick; | ||
232 | } | ||
233 | |||
234 | static int stick_add_compare(unsigned long adj) | ||
235 | { | ||
236 | unsigned long orig_tick, new_tick; | ||
237 | |||
238 | __asm__ __volatile__("rd %%asr24, %0" | ||
239 | : "=r" (orig_tick)); | ||
240 | orig_tick &= ~TICKCMP_IRQ_BIT; | ||
241 | |||
242 | __asm__ __volatile__("wr %0, 0, %%asr25" | ||
243 | : /* no outputs */ | ||
244 | : "r" (orig_tick + adj)); | ||
245 | |||
246 | __asm__ __volatile__("rd %%asr24, %0" | ||
247 | : "=r" (new_tick)); | ||
248 | new_tick &= ~TICKCMP_IRQ_BIT; | ||
249 | |||
250 | return ((long)(new_tick - (orig_tick+adj))) > 0L; | ||
251 | } | ||
252 | |||
253 | static struct sparc64_tick_ops stick_operations __read_mostly = { | ||
254 | .name = "stick", | ||
255 | .init_tick = stick_init_tick, | ||
256 | .disable_irq = stick_disable_irq, | ||
257 | .get_tick = stick_get_tick, | ||
258 | .add_tick = stick_add_tick, | ||
259 | .add_compare = stick_add_compare, | ||
260 | .softint_mask = 1UL << 16, | ||
261 | }; | ||
262 | |||
263 | /* On Hummingbird the STICK/STICK_CMPR register is implemented | ||
264 | * in I/O space. There are two 64-bit registers each, the | ||
265 | * first holds the low 32-bits of the value and the second holds | ||
266 | * the high 32-bits. | ||
267 | * | ||
268 | * Since STICK is constantly updating, we have to access it carefully. | ||
269 | * | ||
270 | * The sequence we use to read is: | ||
271 | * 1) read high | ||
272 | * 2) read low | ||
273 | * 3) read high again, if it rolled re-read both low and high again. | ||
274 | * | ||
275 | * Writing STICK safely is also tricky: | ||
276 | * 1) write low to zero | ||
277 | * 2) write high | ||
278 | * 3) write low | ||
279 | */ | ||
280 | #define HBIRD_STICKCMP_ADDR 0x1fe0000f060UL | ||
281 | #define HBIRD_STICK_ADDR 0x1fe0000f070UL | ||
282 | |||
283 | static unsigned long __hbird_read_stick(void) | ||
284 | { | ||
285 | unsigned long ret, tmp1, tmp2, tmp3; | ||
286 | unsigned long addr = HBIRD_STICK_ADDR+8; | ||
287 | |||
288 | __asm__ __volatile__("ldxa [%1] %5, %2\n" | ||
289 | "1:\n\t" | ||
290 | "sub %1, 0x8, %1\n\t" | ||
291 | "ldxa [%1] %5, %3\n\t" | ||
292 | "add %1, 0x8, %1\n\t" | ||
293 | "ldxa [%1] %5, %4\n\t" | ||
294 | "cmp %4, %2\n\t" | ||
295 | "bne,a,pn %%xcc, 1b\n\t" | ||
296 | " mov %4, %2\n\t" | ||
297 | "sllx %4, 32, %4\n\t" | ||
298 | "or %3, %4, %0\n\t" | ||
299 | : "=&r" (ret), "=&r" (addr), | ||
300 | "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3) | ||
301 | : "i" (ASI_PHYS_BYPASS_EC_E), "1" (addr)); | ||
302 | |||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | static void __hbird_write_stick(unsigned long val) | ||
307 | { | ||
308 | unsigned long low = (val & 0xffffffffUL); | ||
309 | unsigned long high = (val >> 32UL); | ||
310 | unsigned long addr = HBIRD_STICK_ADDR; | ||
311 | |||
312 | __asm__ __volatile__("stxa %%g0, [%0] %4\n\t" | ||
313 | "add %0, 0x8, %0\n\t" | ||
314 | "stxa %3, [%0] %4\n\t" | ||
315 | "sub %0, 0x8, %0\n\t" | ||
316 | "stxa %2, [%0] %4" | ||
317 | : "=&r" (addr) | ||
318 | : "0" (addr), "r" (low), "r" (high), | ||
319 | "i" (ASI_PHYS_BYPASS_EC_E)); | ||
320 | } | ||
321 | |||
322 | static void __hbird_write_compare(unsigned long val) | ||
323 | { | ||
324 | unsigned long low = (val & 0xffffffffUL); | ||
325 | unsigned long high = (val >> 32UL); | ||
326 | unsigned long addr = HBIRD_STICKCMP_ADDR + 0x8UL; | ||
327 | |||
328 | __asm__ __volatile__("stxa %3, [%0] %4\n\t" | ||
329 | "sub %0, 0x8, %0\n\t" | ||
330 | "stxa %2, [%0] %4" | ||
331 | : "=&r" (addr) | ||
332 | : "0" (addr), "r" (low), "r" (high), | ||
333 | "i" (ASI_PHYS_BYPASS_EC_E)); | ||
334 | } | ||
335 | |||
336 | static void hbtick_disable_irq(void) | ||
337 | { | ||
338 | __hbird_write_compare(TICKCMP_IRQ_BIT); | ||
339 | } | ||
340 | |||
341 | static void hbtick_init_tick(void) | ||
342 | { | ||
343 | tick_disable_protection(); | ||
344 | |||
345 | /* XXX This seems to be necessary to 'jumpstart' Hummingbird | ||
346 | * XXX into actually sending STICK interrupts. I think because | ||
347 | * XXX of how we store %tick_cmpr in head.S this somehow resets the | ||
348 | * XXX {TICK + STICK} interrupt mux. -DaveM | ||
349 | */ | ||
350 | __hbird_write_stick(__hbird_read_stick()); | ||
351 | |||
352 | hbtick_disable_irq(); | ||
353 | } | ||
354 | |||
355 | static unsigned long hbtick_get_tick(void) | ||
356 | { | ||
357 | return __hbird_read_stick() & ~TICK_PRIV_BIT; | ||
358 | } | ||
359 | |||
360 | static unsigned long hbtick_add_tick(unsigned long adj) | ||
361 | { | ||
362 | unsigned long val; | ||
363 | |||
364 | val = __hbird_read_stick() + adj; | ||
365 | __hbird_write_stick(val); | ||
366 | |||
367 | return val; | ||
368 | } | ||
369 | |||
370 | static int hbtick_add_compare(unsigned long adj) | ||
371 | { | ||
372 | unsigned long val = __hbird_read_stick(); | ||
373 | unsigned long val2; | ||
374 | |||
375 | val &= ~TICKCMP_IRQ_BIT; | ||
376 | val += adj; | ||
377 | __hbird_write_compare(val); | ||
378 | |||
379 | val2 = __hbird_read_stick() & ~TICKCMP_IRQ_BIT; | ||
380 | |||
381 | return ((long)(val2 - val)) > 0L; | ||
382 | } | ||
383 | |||
384 | static struct sparc64_tick_ops hbtick_operations __read_mostly = { | ||
385 | .name = "hbtick", | ||
386 | .init_tick = hbtick_init_tick, | ||
387 | .disable_irq = hbtick_disable_irq, | ||
388 | .get_tick = hbtick_get_tick, | ||
389 | .add_tick = hbtick_add_tick, | ||
390 | .add_compare = hbtick_add_compare, | ||
391 | .softint_mask = 1UL << 0, | ||
392 | }; | ||
393 | |||
394 | static unsigned long timer_ticks_per_nsec_quotient __read_mostly; | ||
395 | |||
396 | int update_persistent_clock(struct timespec now) | ||
397 | { | ||
398 | struct rtc_device *rtc = rtc_class_open("rtc0"); | ||
399 | int err = -1; | ||
400 | |||
401 | if (rtc) { | ||
402 | err = rtc_set_mmss(rtc, now.tv_sec); | ||
403 | rtc_class_close(rtc); | ||
404 | } | ||
405 | |||
406 | return err; | ||
407 | } | ||
408 | |||
409 | unsigned long cmos_regs; | ||
410 | EXPORT_SYMBOL(cmos_regs); | ||
411 | |||
412 | static struct resource rtc_cmos_resource; | ||
413 | |||
414 | static struct platform_device rtc_cmos_device = { | ||
415 | .name = "rtc_cmos", | ||
416 | .id = -1, | ||
417 | .resource = &rtc_cmos_resource, | ||
418 | .num_resources = 1, | ||
419 | }; | ||
420 | |||
421 | static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match) | ||
422 | { | ||
423 | struct resource *r; | ||
424 | |||
425 | printk(KERN_INFO "%s: RTC regs at 0x%lx\n", | ||
426 | op->node->full_name, op->resource[0].start); | ||
427 | |||
428 | /* The CMOS RTC driver only accepts IORESOURCE_IO, so cons | ||
429 | * up a fake resource so that the probe works for all cases. | ||
430 | * When the RTC is behind an ISA bus it will have IORESOURCE_IO | ||
431 | * already, whereas when it's behind EBUS is will be IORESOURCE_MEM. | ||
432 | */ | ||
433 | |||
434 | r = &rtc_cmos_resource; | ||
435 | r->flags = IORESOURCE_IO; | ||
436 | r->name = op->resource[0].name; | ||
437 | r->start = op->resource[0].start; | ||
438 | r->end = op->resource[0].end; | ||
439 | |||
440 | cmos_regs = op->resource[0].start; | ||
441 | return platform_device_register(&rtc_cmos_device); | ||
442 | } | ||
443 | |||
444 | static struct of_device_id __initdata rtc_match[] = { | ||
445 | { | ||
446 | .name = "rtc", | ||
447 | .compatible = "m5819", | ||
448 | }, | ||
449 | { | ||
450 | .name = "rtc", | ||
451 | .compatible = "isa-m5819p", | ||
452 | }, | ||
453 | { | ||
454 | .name = "rtc", | ||
455 | .compatible = "isa-m5823p", | ||
456 | }, | ||
457 | { | ||
458 | .name = "rtc", | ||
459 | .compatible = "ds1287", | ||
460 | }, | ||
461 | {}, | ||
462 | }; | ||
463 | |||
464 | static struct of_platform_driver rtc_driver = { | ||
465 | .match_table = rtc_match, | ||
466 | .probe = rtc_probe, | ||
467 | .driver = { | ||
468 | .name = "rtc", | ||
469 | }, | ||
470 | }; | ||
471 | |||
472 | static struct platform_device rtc_bq4802_device = { | ||
473 | .name = "rtc-bq4802", | ||
474 | .id = -1, | ||
475 | .num_resources = 1, | ||
476 | }; | ||
477 | |||
478 | static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match) | ||
479 | { | ||
480 | |||
481 | printk(KERN_INFO "%s: BQ4802 regs at 0x%lx\n", | ||
482 | op->node->full_name, op->resource[0].start); | ||
483 | |||
484 | rtc_bq4802_device.resource = &op->resource[0]; | ||
485 | return platform_device_register(&rtc_bq4802_device); | ||
486 | } | ||
487 | |||
488 | static struct of_device_id __initdata bq4802_match[] = { | ||
489 | { | ||
490 | .name = "rtc", | ||
491 | .compatible = "bq4802", | ||
492 | }, | ||
493 | {}, | ||
494 | }; | ||
495 | |||
496 | static struct of_platform_driver bq4802_driver = { | ||
497 | .match_table = bq4802_match, | ||
498 | .probe = bq4802_probe, | ||
499 | .driver = { | ||
500 | .name = "bq4802", | ||
501 | }, | ||
502 | }; | ||
503 | |||
504 | static unsigned char mostek_read_byte(struct device *dev, u32 ofs) | ||
505 | { | ||
506 | struct platform_device *pdev = to_platform_device(dev); | ||
507 | void __iomem *regs = (void __iomem *) pdev->resource[0].start; | ||
508 | |||
509 | return readb(regs + ofs); | ||
510 | } | ||
511 | |||
512 | static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) | ||
513 | { | ||
514 | struct platform_device *pdev = to_platform_device(dev); | ||
515 | void __iomem *regs = (void __iomem *) pdev->resource[0].start; | ||
516 | |||
517 | writeb(val, regs + ofs); | ||
518 | } | ||
519 | |||
520 | static struct m48t59_plat_data m48t59_data = { | ||
521 | .read_byte = mostek_read_byte, | ||
522 | .write_byte = mostek_write_byte, | ||
523 | }; | ||
524 | |||
525 | static struct platform_device m48t59_rtc = { | ||
526 | .name = "rtc-m48t59", | ||
527 | .id = 0, | ||
528 | .num_resources = 1, | ||
529 | .dev = { | ||
530 | .platform_data = &m48t59_data, | ||
531 | }, | ||
532 | }; | ||
533 | |||
534 | static int __devinit mostek_probe(struct of_device *op, const struct of_device_id *match) | ||
535 | { | ||
536 | struct device_node *dp = op->node; | ||
537 | |||
538 | /* On an Enterprise system there can be multiple mostek clocks. | ||
539 | * We should only match the one that is on the central FHC bus. | ||
540 | */ | ||
541 | if (!strcmp(dp->parent->name, "fhc") && | ||
542 | strcmp(dp->parent->parent->name, "central") != 0) | ||
543 | return -ENODEV; | ||
544 | |||
545 | printk(KERN_INFO "%s: Mostek regs at 0x%lx\n", | ||
546 | dp->full_name, op->resource[0].start); | ||
547 | |||
548 | m48t59_rtc.resource = &op->resource[0]; | ||
549 | return platform_device_register(&m48t59_rtc); | ||
550 | } | ||
551 | |||
552 | static struct of_device_id __initdata mostek_match[] = { | ||
553 | { | ||
554 | .name = "eeprom", | ||
555 | }, | ||
556 | {}, | ||
557 | }; | ||
558 | |||
559 | static struct of_platform_driver mostek_driver = { | ||
560 | .match_table = mostek_match, | ||
561 | .probe = mostek_probe, | ||
562 | .driver = { | ||
563 | .name = "mostek", | ||
564 | }, | ||
565 | }; | ||
566 | |||
567 | static struct platform_device rtc_sun4v_device = { | ||
568 | .name = "rtc-sun4v", | ||
569 | .id = -1, | ||
570 | }; | ||
571 | |||
572 | static struct platform_device rtc_starfire_device = { | ||
573 | .name = "rtc-starfire", | ||
574 | .id = -1, | ||
575 | }; | ||
576 | |||
577 | static int __init clock_init(void) | ||
578 | { | ||
579 | if (this_is_starfire) | ||
580 | return platform_device_register(&rtc_starfire_device); | ||
581 | |||
582 | if (tlb_type == hypervisor) | ||
583 | return platform_device_register(&rtc_sun4v_device); | ||
584 | |||
585 | (void) of_register_driver(&rtc_driver, &of_platform_bus_type); | ||
586 | (void) of_register_driver(&mostek_driver, &of_platform_bus_type); | ||
587 | (void) of_register_driver(&bq4802_driver, &of_platform_bus_type); | ||
588 | |||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | /* Must be after subsys_initcall() so that busses are probed. Must | ||
593 | * be before device_initcall() because things like the RTC driver | ||
594 | * need to see the clock registers. | ||
595 | */ | ||
596 | fs_initcall(clock_init); | ||
597 | |||
598 | /* This is gets the master TICK_INT timer going. */ | ||
599 | static unsigned long sparc64_init_timers(void) | ||
600 | { | ||
601 | struct device_node *dp; | ||
602 | unsigned long freq; | ||
603 | |||
604 | dp = of_find_node_by_path("/"); | ||
605 | if (tlb_type == spitfire) { | ||
606 | unsigned long ver, manuf, impl; | ||
607 | |||
608 | __asm__ __volatile__ ("rdpr %%ver, %0" | ||
609 | : "=&r" (ver)); | ||
610 | manuf = ((ver >> 48) & 0xffff); | ||
611 | impl = ((ver >> 32) & 0xffff); | ||
612 | if (manuf == 0x17 && impl == 0x13) { | ||
613 | /* Hummingbird, aka Ultra-IIe */ | ||
614 | tick_ops = &hbtick_operations; | ||
615 | freq = of_getintprop_default(dp, "stick-frequency", 0); | ||
616 | } else { | ||
617 | tick_ops = &tick_operations; | ||
618 | freq = local_cpu_data().clock_tick; | ||
619 | } | ||
620 | } else { | ||
621 | tick_ops = &stick_operations; | ||
622 | freq = of_getintprop_default(dp, "stick-frequency", 0); | ||
623 | } | ||
624 | |||
625 | return freq; | ||
626 | } | ||
627 | |||
628 | struct freq_table { | ||
629 | unsigned long clock_tick_ref; | ||
630 | unsigned int ref_freq; | ||
631 | }; | ||
632 | static DEFINE_PER_CPU(struct freq_table, sparc64_freq_table) = { 0, 0 }; | ||
633 | |||
634 | unsigned long sparc64_get_clock_tick(unsigned int cpu) | ||
635 | { | ||
636 | struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu); | ||
637 | |||
638 | if (ft->clock_tick_ref) | ||
639 | return ft->clock_tick_ref; | ||
640 | return cpu_data(cpu).clock_tick; | ||
641 | } | ||
642 | |||
643 | #ifdef CONFIG_CPU_FREQ | ||
644 | |||
645 | static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | ||
646 | void *data) | ||
647 | { | ||
648 | struct cpufreq_freqs *freq = data; | ||
649 | unsigned int cpu = freq->cpu; | ||
650 | struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu); | ||
651 | |||
652 | if (!ft->ref_freq) { | ||
653 | ft->ref_freq = freq->old; | ||
654 | ft->clock_tick_ref = cpu_data(cpu).clock_tick; | ||
655 | } | ||
656 | if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || | ||
657 | (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || | ||
658 | (val == CPUFREQ_RESUMECHANGE)) { | ||
659 | cpu_data(cpu).clock_tick = | ||
660 | cpufreq_scale(ft->clock_tick_ref, | ||
661 | ft->ref_freq, | ||
662 | freq->new); | ||
663 | } | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | static struct notifier_block sparc64_cpufreq_notifier_block = { | ||
669 | .notifier_call = sparc64_cpufreq_notifier | ||
670 | }; | ||
671 | |||
672 | static int __init register_sparc64_cpufreq_notifier(void) | ||
673 | { | ||
674 | |||
675 | cpufreq_register_notifier(&sparc64_cpufreq_notifier_block, | ||
676 | CPUFREQ_TRANSITION_NOTIFIER); | ||
677 | return 0; | ||
678 | } | ||
679 | |||
680 | core_initcall(register_sparc64_cpufreq_notifier); | ||
681 | |||
682 | #endif /* CONFIG_CPU_FREQ */ | ||
683 | |||
684 | static int sparc64_next_event(unsigned long delta, | ||
685 | struct clock_event_device *evt) | ||
686 | { | ||
687 | return tick_ops->add_compare(delta) ? -ETIME : 0; | ||
688 | } | ||
689 | |||
690 | static void sparc64_timer_setup(enum clock_event_mode mode, | ||
691 | struct clock_event_device *evt) | ||
692 | { | ||
693 | switch (mode) { | ||
694 | case CLOCK_EVT_MODE_ONESHOT: | ||
695 | case CLOCK_EVT_MODE_RESUME: | ||
696 | break; | ||
697 | |||
698 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
699 | tick_ops->disable_irq(); | ||
700 | break; | ||
701 | |||
702 | case CLOCK_EVT_MODE_PERIODIC: | ||
703 | case CLOCK_EVT_MODE_UNUSED: | ||
704 | WARN_ON(1); | ||
705 | break; | ||
706 | }; | ||
707 | } | ||
708 | |||
709 | static struct clock_event_device sparc64_clockevent = { | ||
710 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
711 | .set_mode = sparc64_timer_setup, | ||
712 | .set_next_event = sparc64_next_event, | ||
713 | .rating = 100, | ||
714 | .shift = 30, | ||
715 | .irq = -1, | ||
716 | }; | ||
717 | static DEFINE_PER_CPU(struct clock_event_device, sparc64_events); | ||
718 | |||
719 | void timer_interrupt(int irq, struct pt_regs *regs) | ||
720 | { | ||
721 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
722 | unsigned long tick_mask = tick_ops->softint_mask; | ||
723 | int cpu = smp_processor_id(); | ||
724 | struct clock_event_device *evt = &per_cpu(sparc64_events, cpu); | ||
725 | |||
726 | clear_softint(tick_mask); | ||
727 | |||
728 | irq_enter(); | ||
729 | |||
730 | kstat_this_cpu.irqs[0]++; | ||
731 | |||
732 | if (unlikely(!evt->event_handler)) { | ||
733 | printk(KERN_WARNING | ||
734 | "Spurious SPARC64 timer interrupt on cpu %d\n", cpu); | ||
735 | } else | ||
736 | evt->event_handler(evt); | ||
737 | |||
738 | irq_exit(); | ||
739 | |||
740 | set_irq_regs(old_regs); | ||
741 | } | ||
742 | |||
743 | void __devinit setup_sparc64_timer(void) | ||
744 | { | ||
745 | struct clock_event_device *sevt; | ||
746 | unsigned long pstate; | ||
747 | |||
748 | /* Guarantee that the following sequences execute | ||
749 | * uninterrupted. | ||
750 | */ | ||
751 | __asm__ __volatile__("rdpr %%pstate, %0\n\t" | ||
752 | "wrpr %0, %1, %%pstate" | ||
753 | : "=r" (pstate) | ||
754 | : "i" (PSTATE_IE)); | ||
755 | |||
756 | tick_ops->init_tick(); | ||
757 | |||
758 | /* Restore PSTATE_IE. */ | ||
759 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" | ||
760 | : /* no outputs */ | ||
761 | : "r" (pstate)); | ||
762 | |||
763 | sevt = &__get_cpu_var(sparc64_events); | ||
764 | |||
765 | memcpy(sevt, &sparc64_clockevent, sizeof(*sevt)); | ||
766 | sevt->cpumask = cpumask_of_cpu(smp_processor_id()); | ||
767 | |||
768 | clockevents_register_device(sevt); | ||
769 | } | ||
770 | |||
771 | #define SPARC64_NSEC_PER_CYC_SHIFT 10UL | ||
772 | |||
773 | static struct clocksource clocksource_tick = { | ||
774 | .rating = 100, | ||
775 | .mask = CLOCKSOURCE_MASK(64), | ||
776 | .shift = 16, | ||
777 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
778 | }; | ||
779 | |||
780 | static void __init setup_clockevent_multiplier(unsigned long hz) | ||
781 | { | ||
782 | unsigned long mult, shift = 32; | ||
783 | |||
784 | while (1) { | ||
785 | mult = div_sc(hz, NSEC_PER_SEC, shift); | ||
786 | if (mult && (mult >> 32UL) == 0UL) | ||
787 | break; | ||
788 | |||
789 | shift--; | ||
790 | } | ||
791 | |||
792 | sparc64_clockevent.shift = shift; | ||
793 | sparc64_clockevent.mult = mult; | ||
794 | } | ||
795 | |||
796 | static unsigned long tb_ticks_per_usec __read_mostly; | ||
797 | |||
798 | void __delay(unsigned long loops) | ||
799 | { | ||
800 | unsigned long bclock, now; | ||
801 | |||
802 | bclock = tick_ops->get_tick(); | ||
803 | do { | ||
804 | now = tick_ops->get_tick(); | ||
805 | } while ((now-bclock) < loops); | ||
806 | } | ||
807 | EXPORT_SYMBOL(__delay); | ||
808 | |||
809 | void udelay(unsigned long usecs) | ||
810 | { | ||
811 | __delay(tb_ticks_per_usec * usecs); | ||
812 | } | ||
813 | EXPORT_SYMBOL(udelay); | ||
814 | |||
815 | void __init time_init(void) | ||
816 | { | ||
817 | unsigned long freq = sparc64_init_timers(); | ||
818 | |||
819 | tb_ticks_per_usec = freq / USEC_PER_SEC; | ||
820 | |||
821 | timer_ticks_per_nsec_quotient = | ||
822 | clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); | ||
823 | |||
824 | clocksource_tick.name = tick_ops->name; | ||
825 | clocksource_tick.mult = | ||
826 | clocksource_hz2mult(freq, | ||
827 | clocksource_tick.shift); | ||
828 | clocksource_tick.read = tick_ops->get_tick; | ||
829 | |||
830 | printk("clocksource: mult[%x] shift[%d]\n", | ||
831 | clocksource_tick.mult, clocksource_tick.shift); | ||
832 | |||
833 | clocksource_register(&clocksource_tick); | ||
834 | |||
835 | sparc64_clockevent.name = tick_ops->name; | ||
836 | |||
837 | setup_clockevent_multiplier(freq); | ||
838 | |||
839 | sparc64_clockevent.max_delta_ns = | ||
840 | clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); | ||
841 | sparc64_clockevent.min_delta_ns = | ||
842 | clockevent_delta2ns(0xF, &sparc64_clockevent); | ||
843 | |||
844 | printk("clockevent: mult[%lx] shift[%d]\n", | ||
845 | sparc64_clockevent.mult, sparc64_clockevent.shift); | ||
846 | |||
847 | setup_sparc64_timer(); | ||
848 | } | ||
849 | |||
850 | unsigned long long sched_clock(void) | ||
851 | { | ||
852 | unsigned long ticks = tick_ops->get_tick(); | ||
853 | |||
854 | return (ticks * timer_ticks_per_nsec_quotient) | ||
855 | >> SPARC64_NSEC_PER_CYC_SHIFT; | ||
856 | } | ||
857 | |||
858 | int __devinit read_current_timer(unsigned long *timer_val) | ||
859 | { | ||
860 | *timer_val = tick_ops->get_tick(); | ||
861 | return 0; | ||
862 | } | ||