diff options
author | Pavel Tatashin <pasha.tatashin@oracle.com> | 2017-06-12 16:41:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-12 18:44:03 -0400 |
commit | 89108c3423e8047cd0da73182ea09b9da190b57e (patch) | |
tree | 9096d52fddf142a7b1c90ef17b350a9f537aadd5 | |
parent | 178bf2b9a20e866677bbca5cb521b09a8498c1d7 (diff) |
sparc64: improve modularity tick options
This patch prepares the code for early boot time stamps by making it more
modular.
- init_tick_ops() to initialize struct sparc64_tick_ops
- new sparc64_tick_ops operation get_frequency() which returns a
frequency
Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com>
Reviewed-by: Bob Picco <bob.picco@oracle.com>
Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/include/asm/timer_64.h | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/time_64.c | 83 |
2 files changed, 57 insertions, 28 deletions
diff --git a/arch/sparc/include/asm/timer_64.h b/arch/sparc/include/asm/timer_64.h index bde2cc40ae02..61d07251792c 100644 --- a/arch/sparc/include/asm/timer_64.h +++ b/arch/sparc/include/asm/timer_64.h | |||
@@ -22,6 +22,8 @@ struct sparc64_tick_ops { | |||
22 | 22 | ||
23 | void (*init_tick)(void); | 23 | void (*init_tick)(void); |
24 | unsigned long (*add_tick)(unsigned long); | 24 | unsigned long (*add_tick)(unsigned long); |
25 | unsigned long (*get_frequency)(void); | ||
26 | unsigned long frequency; | ||
25 | 27 | ||
26 | char *name; | 28 | char *name; |
27 | }; | 29 | }; |
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 44e37e9f8428..3bd9e499755b 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c | |||
@@ -164,6 +164,11 @@ static unsigned long tick_add_tick(unsigned long adj) | |||
164 | return new_tick; | 164 | return new_tick; |
165 | } | 165 | } |
166 | 166 | ||
167 | static unsigned long tick_get_frequency(void) | ||
168 | { | ||
169 | return local_cpu_data().clock_tick; | ||
170 | } | ||
171 | |||
167 | static struct sparc64_tick_ops tick_operations __cacheline_aligned = { | 172 | static struct sparc64_tick_ops tick_operations __cacheline_aligned = { |
168 | .name = "tick", | 173 | .name = "tick", |
169 | .init_tick = tick_init_tick, | 174 | .init_tick = tick_init_tick, |
@@ -171,6 +176,7 @@ static struct sparc64_tick_ops tick_operations __cacheline_aligned = { | |||
171 | .get_tick = tick_get_tick, | 176 | .get_tick = tick_get_tick, |
172 | .add_tick = tick_add_tick, | 177 | .add_tick = tick_add_tick, |
173 | .add_compare = tick_add_compare, | 178 | .add_compare = tick_add_compare, |
179 | .get_frequency = tick_get_frequency, | ||
174 | .softint_mask = 1UL << 0, | 180 | .softint_mask = 1UL << 0, |
175 | }; | 181 | }; |
176 | 182 | ||
@@ -250,6 +256,13 @@ static int stick_add_compare(unsigned long adj) | |||
250 | return ((long)(new_tick - (orig_tick+adj))) > 0L; | 256 | return ((long)(new_tick - (orig_tick+adj))) > 0L; |
251 | } | 257 | } |
252 | 258 | ||
259 | static unsigned long stick_get_frequency(void) | ||
260 | { | ||
261 | struct device_node *dp = of_find_node_by_path("/"); | ||
262 | |||
263 | return of_getintprop_default(dp, "stick-frequency", 0); | ||
264 | } | ||
265 | |||
253 | static struct sparc64_tick_ops stick_operations __read_mostly = { | 266 | static struct sparc64_tick_ops stick_operations __read_mostly = { |
254 | .name = "stick", | 267 | .name = "stick", |
255 | .init_tick = stick_init_tick, | 268 | .init_tick = stick_init_tick, |
@@ -257,6 +270,7 @@ static struct sparc64_tick_ops stick_operations __read_mostly = { | |||
257 | .get_tick = stick_get_tick, | 270 | .get_tick = stick_get_tick, |
258 | .add_tick = stick_add_tick, | 271 | .add_tick = stick_add_tick, |
259 | .add_compare = stick_add_compare, | 272 | .add_compare = stick_add_compare, |
273 | .get_frequency = stick_get_frequency, | ||
260 | .softint_mask = 1UL << 16, | 274 | .softint_mask = 1UL << 16, |
261 | }; | 275 | }; |
262 | 276 | ||
@@ -381,6 +395,13 @@ static int hbtick_add_compare(unsigned long adj) | |||
381 | return ((long)(val2 - val)) > 0L; | 395 | return ((long)(val2 - val)) > 0L; |
382 | } | 396 | } |
383 | 397 | ||
398 | static unsigned long hbtick_get_frequency(void) | ||
399 | { | ||
400 | struct device_node *dp = of_find_node_by_path("/"); | ||
401 | |||
402 | return of_getintprop_default(dp, "stick-frequency", 0); | ||
403 | } | ||
404 | |||
384 | static struct sparc64_tick_ops hbtick_operations __read_mostly = { | 405 | static struct sparc64_tick_ops hbtick_operations __read_mostly = { |
385 | .name = "hbtick", | 406 | .name = "hbtick", |
386 | .init_tick = hbtick_init_tick, | 407 | .init_tick = hbtick_init_tick, |
@@ -388,6 +409,7 @@ static struct sparc64_tick_ops hbtick_operations __read_mostly = { | |||
388 | .get_tick = hbtick_get_tick, | 409 | .get_tick = hbtick_get_tick, |
389 | .add_tick = hbtick_add_tick, | 410 | .add_tick = hbtick_add_tick, |
390 | .add_compare = hbtick_add_compare, | 411 | .add_compare = hbtick_add_compare, |
412 | .get_frequency = hbtick_get_frequency, | ||
391 | .softint_mask = 1UL << 0, | 413 | .softint_mask = 1UL << 0, |
392 | }; | 414 | }; |
393 | 415 | ||
@@ -580,36 +602,17 @@ static int __init clock_init(void) | |||
580 | */ | 602 | */ |
581 | fs_initcall(clock_init); | 603 | fs_initcall(clock_init); |
582 | 604 | ||
583 | /* This is gets the master TICK_INT timer going. */ | 605 | /* Return true if this is Hummingbird, aka Ultra-IIe */ |
584 | static unsigned long sparc64_init_timers(void) | 606 | static bool is_hummingbird(void) |
585 | { | 607 | { |
586 | struct sparc64_tick_ops *ops = NULL; | 608 | unsigned long ver, manuf, impl; |
587 | struct device_node *dp; | ||
588 | unsigned long freq; | ||
589 | 609 | ||
590 | dp = of_find_node_by_path("/"); | 610 | __asm__ __volatile__ ("rdpr %%ver, %0" |
591 | if (tlb_type == spitfire) { | 611 | : "=&r" (ver)); |
592 | unsigned long ver, manuf, impl; | 612 | manuf = ((ver >> 48) & 0xffff); |
593 | 613 | impl = ((ver >> 32) & 0xffff); | |
594 | __asm__ __volatile__ ("rdpr %%ver, %0" | ||
595 | : "=&r" (ver)); | ||
596 | manuf = ((ver >> 48) & 0xffff); | ||
597 | impl = ((ver >> 32) & 0xffff); | ||
598 | if (manuf == 0x17 && impl == 0x13) { | ||
599 | /* Hummingbird, aka Ultra-IIe */ | ||
600 | ops = &hbtick_operations; | ||
601 | freq = of_getintprop_default(dp, "stick-frequency", 0); | ||
602 | } else { | ||
603 | freq = local_cpu_data().clock_tick; | ||
604 | } | ||
605 | } else { | ||
606 | ops = &stick_operations; | ||
607 | freq = of_getintprop_default(dp, "stick-frequency", 0); | ||
608 | } | ||
609 | if (ops) | ||
610 | memcpy(&tick_operations, ops, sizeof(struct sparc64_tick_ops)); | ||
611 | 614 | ||
612 | return freq; | 615 | return (manuf == 0x17 && impl == 0x13); |
613 | } | 616 | } |
614 | 617 | ||
615 | struct freq_table { | 618 | struct freq_table { |
@@ -775,10 +778,34 @@ static u64 clocksource_tick_read(struct clocksource *cs) | |||
775 | return tick_operations.get_tick(); | 778 | return tick_operations.get_tick(); |
776 | } | 779 | } |
777 | 780 | ||
781 | static void init_tick_ops(struct sparc64_tick_ops *ops) | ||
782 | { | ||
783 | unsigned long freq, quotient, tick; | ||
784 | |||
785 | freq = ops->get_frequency(); | ||
786 | quotient = clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); | ||
787 | tick = ops->get_tick(); | ||
788 | |||
789 | ops->offset = (tick * quotient) >> SPARC64_NSEC_PER_CYC_SHIFT; | ||
790 | ops->ticks_per_nsec_quotient = quotient; | ||
791 | ops->frequency = freq; | ||
792 | tick_operations = *ops; | ||
793 | } | ||
794 | |||
778 | void __init time_init(void) | 795 | void __init time_init(void) |
779 | { | 796 | { |
780 | unsigned long freq = sparc64_init_timers(); | 797 | unsigned long freq; |
798 | |||
799 | if (tlb_type == spitfire) { | ||
800 | if (is_hummingbird()) | ||
801 | init_tick_ops(&hbtick_operations); | ||
802 | else | ||
803 | init_tick_ops(&tick_operations); | ||
804 | } else { | ||
805 | init_tick_ops(&stick_operations); | ||
806 | } | ||
781 | 807 | ||
808 | freq = tick_operations.frequency; | ||
782 | tb_ticks_per_usec = freq / USEC_PER_SEC; | 809 | tb_ticks_per_usec = freq / USEC_PER_SEC; |
783 | 810 | ||
784 | tick_operations.ticks_per_nsec_quotient = | 811 | tick_operations.ticks_per_nsec_quotient = |