aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/time.c
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2008-12-03 06:11:52 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-04 12:17:21 -0500
commita88b5ba8bd8ac18aad65ee6c6a254e2e74876db3 (patch)
treeeb3d0ffaf53c3f7ec6083752c2097cecd1cb892a /arch/sparc64/kernel/time.c
parentd670bd4f803c8b646acd20f3ba21e65458293faf (diff)
sparc,sparc64: unify kernel/
o Move all files from sparc64/kernel/ to sparc/kernel - rename as appropriate o Update sparc/Makefile to the changes o Update sparc/kernel/Makefile to include the sparc64 files NOTE: This commit changes link order on sparc64! Link order had to change for either of sparc32 and sparc64. And assuming sparc64 see more testing than sparc32 change link order on sparc64 where issues will be caught faster. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r--arch/sparc64/kernel/time.c862
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
54DEFINE_SPINLOCK(rtc_lock);
55
56#define TICK_PRIV_BIT (1UL << 63)
57#define TICKCMP_IRQ_BIT (1UL << 63)
58
59#ifdef CONFIG_SMP
60unsigned 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}
68EXPORT_SYMBOL(profile_pc);
69#endif
70
71static 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
91static 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
103static void tick_init_tick(void)
104{
105 tick_disable_protection();
106 tick_disable_irq();
107}
108
109static 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
120static 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
154static 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
168static 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
178struct sparc64_tick_ops *tick_ops __read_mostly = &tick_operations;
179
180static void stick_disable_irq(void)
181{
182 __asm__ __volatile__(
183 "wr %0, 0x0, %%asr25"
184 : /* no outputs */
185 : "r" (TICKCMP_IRQ_BIT));
186}
187
188static 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
211static 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
221static 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
234static 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
253static 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
283static 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
306static 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
322static 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
336static void hbtick_disable_irq(void)
337{
338 __hbird_write_compare(TICKCMP_IRQ_BIT);
339}
340
341static 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
355static unsigned long hbtick_get_tick(void)
356{
357 return __hbird_read_stick() & ~TICK_PRIV_BIT;
358}
359
360static 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
370static 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
384static 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
394static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
395
396int 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
409unsigned long cmos_regs;
410EXPORT_SYMBOL(cmos_regs);
411
412static struct resource rtc_cmos_resource;
413
414static struct platform_device rtc_cmos_device = {
415 .name = "rtc_cmos",
416 .id = -1,
417 .resource = &rtc_cmos_resource,
418 .num_resources = 1,
419};
420
421static 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
444static 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
464static struct of_platform_driver rtc_driver = {
465 .match_table = rtc_match,
466 .probe = rtc_probe,
467 .driver = {
468 .name = "rtc",
469 },
470};
471
472static struct platform_device rtc_bq4802_device = {
473 .name = "rtc-bq4802",
474 .id = -1,
475 .num_resources = 1,
476};
477
478static 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
488static struct of_device_id __initdata bq4802_match[] = {
489 {
490 .name = "rtc",
491 .compatible = "bq4802",
492 },
493 {},
494};
495
496static struct of_platform_driver bq4802_driver = {
497 .match_table = bq4802_match,
498 .probe = bq4802_probe,
499 .driver = {
500 .name = "bq4802",
501 },
502};
503
504static 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
512static 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
520static struct m48t59_plat_data m48t59_data = {
521 .read_byte = mostek_read_byte,
522 .write_byte = mostek_write_byte,
523};
524
525static 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
534static 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
552static struct of_device_id __initdata mostek_match[] = {
553 {
554 .name = "eeprom",
555 },
556 {},
557};
558
559static struct of_platform_driver mostek_driver = {
560 .match_table = mostek_match,
561 .probe = mostek_probe,
562 .driver = {
563 .name = "mostek",
564 },
565};
566
567static struct platform_device rtc_sun4v_device = {
568 .name = "rtc-sun4v",
569 .id = -1,
570};
571
572static struct platform_device rtc_starfire_device = {
573 .name = "rtc-starfire",
574 .id = -1,
575};
576
577static 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 */
596fs_initcall(clock_init);
597
598/* This is gets the master TICK_INT timer going. */
599static 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
628struct freq_table {
629 unsigned long clock_tick_ref;
630 unsigned int ref_freq;
631};
632static DEFINE_PER_CPU(struct freq_table, sparc64_freq_table) = { 0, 0 };
633
634unsigned 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
645static 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
668static struct notifier_block sparc64_cpufreq_notifier_block = {
669 .notifier_call = sparc64_cpufreq_notifier
670};
671
672static 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
680core_initcall(register_sparc64_cpufreq_notifier);
681
682#endif /* CONFIG_CPU_FREQ */
683
684static 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
690static 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
709static 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};
717static DEFINE_PER_CPU(struct clock_event_device, sparc64_events);
718
719void 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
743void __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
773static struct clocksource clocksource_tick = {
774 .rating = 100,
775 .mask = CLOCKSOURCE_MASK(64),
776 .shift = 16,
777 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
778};
779
780static 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
796static unsigned long tb_ticks_per_usec __read_mostly;
797
798void __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}
807EXPORT_SYMBOL(__delay);
808
809void udelay(unsigned long usecs)
810{
811 __delay(tb_ticks_per_usec * usecs);
812}
813EXPORT_SYMBOL(udelay);
814
815void __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
850unsigned 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
858int __devinit read_current_timer(unsigned long *timer_val)
859{
860 *timer_val = tick_ops->get_tick();
861 return 0;
862}