Commit 89108c34 authored by Pavel Tatashin's avatar Pavel Tatashin Committed by David S. Miller

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: default avatarPavel Tatashin <pasha.tatashin@oracle.com>
Reviewed-by: default avatarBob Picco <bob.picco@oracle.com>
Reviewed-by: default avatarSteven Sistare <steven.sistare@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 178bf2b9
...@@ -22,6 +22,8 @@ struct sparc64_tick_ops { ...@@ -22,6 +22,8 @@ struct sparc64_tick_ops {
void (*init_tick)(void); void (*init_tick)(void);
unsigned long (*add_tick)(unsigned long); unsigned long (*add_tick)(unsigned long);
unsigned long (*get_frequency)(void);
unsigned long frequency;
char *name; char *name;
}; };
......
...@@ -164,6 +164,11 @@ static unsigned long tick_add_tick(unsigned long adj) ...@@ -164,6 +164,11 @@ static unsigned long tick_add_tick(unsigned long adj)
return new_tick; return new_tick;
} }
static unsigned long tick_get_frequency(void)
{
return local_cpu_data().clock_tick;
}
static struct sparc64_tick_ops tick_operations __cacheline_aligned = { static struct sparc64_tick_ops tick_operations __cacheline_aligned = {
.name = "tick", .name = "tick",
.init_tick = tick_init_tick, .init_tick = tick_init_tick,
...@@ -171,6 +176,7 @@ static struct sparc64_tick_ops tick_operations __cacheline_aligned = { ...@@ -171,6 +176,7 @@ static struct sparc64_tick_ops tick_operations __cacheline_aligned = {
.get_tick = tick_get_tick, .get_tick = tick_get_tick,
.add_tick = tick_add_tick, .add_tick = tick_add_tick,
.add_compare = tick_add_compare, .add_compare = tick_add_compare,
.get_frequency = tick_get_frequency,
.softint_mask = 1UL << 0, .softint_mask = 1UL << 0,
}; };
...@@ -250,6 +256,13 @@ static int stick_add_compare(unsigned long adj) ...@@ -250,6 +256,13 @@ static int stick_add_compare(unsigned long adj)
return ((long)(new_tick - (orig_tick+adj))) > 0L; return ((long)(new_tick - (orig_tick+adj))) > 0L;
} }
static unsigned long stick_get_frequency(void)
{
struct device_node *dp = of_find_node_by_path("/");
return of_getintprop_default(dp, "stick-frequency", 0);
}
static struct sparc64_tick_ops stick_operations __read_mostly = { static struct sparc64_tick_ops stick_operations __read_mostly = {
.name = "stick", .name = "stick",
.init_tick = stick_init_tick, .init_tick = stick_init_tick,
...@@ -257,6 +270,7 @@ static struct sparc64_tick_ops stick_operations __read_mostly = { ...@@ -257,6 +270,7 @@ static struct sparc64_tick_ops stick_operations __read_mostly = {
.get_tick = stick_get_tick, .get_tick = stick_get_tick,
.add_tick = stick_add_tick, .add_tick = stick_add_tick,
.add_compare = stick_add_compare, .add_compare = stick_add_compare,
.get_frequency = stick_get_frequency,
.softint_mask = 1UL << 16, .softint_mask = 1UL << 16,
}; };
...@@ -381,6 +395,13 @@ static int hbtick_add_compare(unsigned long adj) ...@@ -381,6 +395,13 @@ static int hbtick_add_compare(unsigned long adj)
return ((long)(val2 - val)) > 0L; return ((long)(val2 - val)) > 0L;
} }
static unsigned long hbtick_get_frequency(void)
{
struct device_node *dp = of_find_node_by_path("/");
return of_getintprop_default(dp, "stick-frequency", 0);
}
static struct sparc64_tick_ops hbtick_operations __read_mostly = { static struct sparc64_tick_ops hbtick_operations __read_mostly = {
.name = "hbtick", .name = "hbtick",
.init_tick = hbtick_init_tick, .init_tick = hbtick_init_tick,
...@@ -388,6 +409,7 @@ static struct sparc64_tick_ops hbtick_operations __read_mostly = { ...@@ -388,6 +409,7 @@ static struct sparc64_tick_ops hbtick_operations __read_mostly = {
.get_tick = hbtick_get_tick, .get_tick = hbtick_get_tick,
.add_tick = hbtick_add_tick, .add_tick = hbtick_add_tick,
.add_compare = hbtick_add_compare, .add_compare = hbtick_add_compare,
.get_frequency = hbtick_get_frequency,
.softint_mask = 1UL << 0, .softint_mask = 1UL << 0,
}; };
...@@ -580,36 +602,17 @@ static int __init clock_init(void) ...@@ -580,36 +602,17 @@ static int __init clock_init(void)
*/ */
fs_initcall(clock_init); fs_initcall(clock_init);
/* This is gets the master TICK_INT timer going. */ /* Return true if this is Hummingbird, aka Ultra-IIe */
static unsigned long sparc64_init_timers(void) static bool is_hummingbird(void)
{ {
struct sparc64_tick_ops *ops = NULL; unsigned long ver, manuf, impl;
struct device_node *dp;
unsigned long freq;
dp = of_find_node_by_path("/"); __asm__ __volatile__ ("rdpr %%ver, %0"
if (tlb_type == spitfire) { : "=&r" (ver));
unsigned long ver, manuf, impl; manuf = ((ver >> 48) & 0xffff);
impl = ((ver >> 32) & 0xffff);
__asm__ __volatile__ ("rdpr %%ver, %0"
: "=&r" (ver));
manuf = ((ver >> 48) & 0xffff);
impl = ((ver >> 32) & 0xffff);
if (manuf == 0x17 && impl == 0x13) {
/* Hummingbird, aka Ultra-IIe */
ops = &hbtick_operations;
freq = of_getintprop_default(dp, "stick-frequency", 0);
} else {
freq = local_cpu_data().clock_tick;
}
} else {
ops = &stick_operations;
freq = of_getintprop_default(dp, "stick-frequency", 0);
}
if (ops)
memcpy(&tick_operations, ops, sizeof(struct sparc64_tick_ops));
return freq; return (manuf == 0x17 && impl == 0x13);
} }
struct freq_table { struct freq_table {
...@@ -775,10 +778,34 @@ static u64 clocksource_tick_read(struct clocksource *cs) ...@@ -775,10 +778,34 @@ static u64 clocksource_tick_read(struct clocksource *cs)
return tick_operations.get_tick(); return tick_operations.get_tick();
} }
static void init_tick_ops(struct sparc64_tick_ops *ops)
{
unsigned long freq, quotient, tick;
freq = ops->get_frequency();
quotient = clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT);
tick = ops->get_tick();
ops->offset = (tick * quotient) >> SPARC64_NSEC_PER_CYC_SHIFT;
ops->ticks_per_nsec_quotient = quotient;
ops->frequency = freq;
tick_operations = *ops;
}
void __init time_init(void) void __init time_init(void)
{ {
unsigned long freq = sparc64_init_timers(); unsigned long freq;
if (tlb_type == spitfire) {
if (is_hummingbird())
init_tick_ops(&hbtick_operations);
else
init_tick_ops(&tick_operations);
} else {
init_tick_ops(&stick_operations);
}
freq = tick_operations.frequency;
tb_ticks_per_usec = freq / USEC_PER_SEC; tb_ticks_per_usec = freq / USEC_PER_SEC;
tick_operations.ticks_per_nsec_quotient = tick_operations.ticks_per_nsec_quotient =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment