aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Tatashin <pasha.tatashin@oracle.com>2017-06-12 16:41:45 -0400
committerDavid S. Miller <davem@davemloft.net>2017-06-12 18:44:03 -0400
commit89108c3423e8047cd0da73182ea09b9da190b57e (patch)
tree9096d52fddf142a7b1c90ef17b350a9f537aadd5
parent178bf2b9a20e866677bbca5cb521b09a8498c1d7 (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.h2
-rw-r--r--arch/sparc/kernel/time_64.c83
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
167static unsigned long tick_get_frequency(void)
168{
169 return local_cpu_data().clock_tick;
170}
171
167static struct sparc64_tick_ops tick_operations __cacheline_aligned = { 172static 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
259static 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
253static struct sparc64_tick_ops stick_operations __read_mostly = { 266static 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
398static 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
384static struct sparc64_tick_ops hbtick_operations __read_mostly = { 405static 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 */
581fs_initcall(clock_init); 603fs_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 */
584static unsigned long sparc64_init_timers(void) 606static 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
615struct freq_table { 618struct 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
781static 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
778void __init time_init(void) 795void __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 =