Commit 112f4871 authored by David S. Miller's avatar David S. Miller

[SPARC64]: Add clocksource/clockevents support.

I'd like to thank John Stul and others for helping
me along the way.

A lot of cleanups fell out of this.  For example, the get_compare()
tick_op was totally unused, so was deleted.  And the most often used
tick_op members were grouped together for cache-friendlyness.

The sparc64 TSC is given to the kernel as a one-shot timer.

tick_ops->init_timer() simply turns off the privileged bit in
the tick register (when possible), and disables the interrupt
by setting bit 63 in the compare register.  The ->disable_irq()
op also sets this bit.

tick_ops->add_compare() is changed to:

1) Add the given delta to "tick" not to "compare"
2) Return a boolean which, if true, means that the tick
   value read after writing the compare value was found
   to have incremented past the initial tick value.  This
   mirrors logic used in the HPET driver's ->next_event()
   method.

Each tick_ops implementation also now provides a name string.
And we feed this into the clocksource and clockevents layers.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 038cb01e
...@@ -19,6 +19,14 @@ config SPARC64 ...@@ -19,6 +19,14 @@ config SPARC64
SPARC64 ports; its web page is available at SPARC64 ports; its web page is available at
<http://www.ultralinux.org/>. <http://www.ultralinux.org/>.
config GENERIC_TIME
bool
default y
config GENERIC_CLOCKEVENTS
bool
default y
config 64BIT config 64BIT
def_bool y def_bool y
...@@ -34,10 +42,6 @@ config LOCKDEP_SUPPORT ...@@ -34,10 +42,6 @@ config LOCKDEP_SUPPORT
bool bool
default y default y
config TIME_INTERPOLATION
bool
default y
config ARCH_MAY_HAVE_PC_FDC config ARCH_MAY_HAVE_PC_FDC
bool bool
default y default y
...@@ -113,6 +117,8 @@ config GENERIC_HARDIRQS ...@@ -113,6 +117,8 @@ config GENERIC_HARDIRQS
menu "General machine setup" menu "General machine setup"
source "kernel/time/Kconfig"
config SMP config SMP
bool "Symmetric multi-processing support" bool "Symmetric multi-processing support"
---help--- ---help---
......
...@@ -123,7 +123,7 @@ void __init smp_store_cpu_info(int id) ...@@ -123,7 +123,7 @@ void __init smp_store_cpu_info(int id)
cpu_data(id).ecache_size, cpu_data(id).ecache_line_size); cpu_data(id).ecache_size, cpu_data(id).ecache_line_size);
} }
static void smp_setup_percpu_timer(void); extern void setup_sparc64_timer(void);
static volatile unsigned long callin_flag = 0; static volatile unsigned long callin_flag = 0;
...@@ -138,7 +138,7 @@ void __init smp_callin(void) ...@@ -138,7 +138,7 @@ void __init smp_callin(void)
__flush_tlb_all(); __flush_tlb_all();
smp_setup_percpu_timer(); setup_sparc64_timer();
if (cheetah_pcache_forced_on) if (cheetah_pcache_forced_on)
cheetah_enable_pcache(); cheetah_enable_pcache();
...@@ -175,8 +175,6 @@ void cpu_panic(void) ...@@ -175,8 +175,6 @@ void cpu_panic(void)
panic("SMP bolixed\n"); panic("SMP bolixed\n");
} }
static unsigned long current_tick_offset __read_mostly;
/* This tick register synchronization scheme is taken entirely from /* This tick register synchronization scheme is taken entirely from
* the ia64 port, see arch/ia64/kernel/smpboot.c for details and credit. * the ia64 port, see arch/ia64/kernel/smpboot.c for details and credit.
* *
...@@ -259,7 +257,7 @@ void smp_synchronize_tick_client(void) ...@@ -259,7 +257,7 @@ void smp_synchronize_tick_client(void)
} else } else
adj = -delta; adj = -delta;
tick_ops->add_tick(adj, current_tick_offset); tick_ops->add_tick(adj);
} }
#if DEBUG_TICK_SYNC #if DEBUG_TICK_SYNC
t[i].rt = rt; t[i].rt = rt;
...@@ -1178,30 +1176,9 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs) ...@@ -1178,30 +1176,9 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
preempt_enable(); preempt_enable();
} }
static void __init smp_setup_percpu_timer(void)
{
unsigned long pstate;
/* Guarantee that the following sequences execute
* uninterrupted.
*/
__asm__ __volatile__("rdpr %%pstate, %0\n\t"
"wrpr %0, %1, %%pstate"
: "=r" (pstate)
: "i" (PSTATE_IE));
tick_ops->init_tick(current_tick_offset);
/* Restore PSTATE_IE. */
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: /* no outputs */
: "r" (pstate));
}
void __init smp_tick_init(void) void __init smp_tick_init(void)
{ {
boot_cpu_id = hard_smp_processor_id(); boot_cpu_id = hard_smp_processor_id();
current_tick_offset = timer_tick_offset;
} }
/* /proc/profile writes can call this, don't __init it please. */ /* /proc/profile writes can call this, don't __init it please. */
......
This diff is collapsed.
...@@ -11,22 +11,19 @@ ...@@ -11,22 +11,19 @@
struct sparc64_tick_ops { struct sparc64_tick_ops {
void (*init_tick)(unsigned long);
unsigned long (*get_tick)(void); unsigned long (*get_tick)(void);
unsigned long (*get_compare)(void); int (*add_compare)(unsigned long);
unsigned long (*add_tick)(unsigned long, unsigned long);
unsigned long (*add_compare)(unsigned long);
unsigned long softint_mask; unsigned long softint_mask;
void (*disable_irq)(void);
void (*init_tick)(void);
unsigned long (*add_tick)(unsigned long);
char *name;
}; };
extern struct sparc64_tick_ops *tick_ops; extern struct sparc64_tick_ops *tick_ops;
#ifdef CONFIG_SMP
extern unsigned long timer_tick_offset;
struct pt_regs;
extern void timer_tick_interrupt(struct pt_regs *);
#endif
extern unsigned long sparc64_get_clock_tick(unsigned int cpu); extern unsigned long sparc64_get_clock_tick(unsigned int cpu);
#endif /* _SPARC64_TIMER_H */ #endif /* _SPARC64_TIMER_H */
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