aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/smp.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-03-05 18:28:37 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 04:54:15 -0400
commit112f48716d9f292c92a033cff9e3ce7405ed4280 (patch)
tree5be2952ca83adb519df5995c10e0686447fea88f /arch/sparc64/kernel/smp.c
parent038cb01ea69cb24ecf30e3ec882e429c84badbeb (diff)
[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: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/smp.c')
-rw-r--r--arch/sparc64/kernel/smp.c29
1 files changed, 3 insertions, 26 deletions
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 39deb0346eb5..d4f0a70f4845 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -123,7 +123,7 @@ void __init smp_store_cpu_info(int id)
123 cpu_data(id).ecache_size, cpu_data(id).ecache_line_size); 123 cpu_data(id).ecache_size, cpu_data(id).ecache_line_size);
124} 124}
125 125
126static void smp_setup_percpu_timer(void); 126extern void setup_sparc64_timer(void);
127 127
128static volatile unsigned long callin_flag = 0; 128static volatile unsigned long callin_flag = 0;
129 129
@@ -138,7 +138,7 @@ void __init smp_callin(void)
138 138
139 __flush_tlb_all(); 139 __flush_tlb_all();
140 140
141 smp_setup_percpu_timer(); 141 setup_sparc64_timer();
142 142
143 if (cheetah_pcache_forced_on) 143 if (cheetah_pcache_forced_on)
144 cheetah_enable_pcache(); 144 cheetah_enable_pcache();
@@ -175,8 +175,6 @@ void cpu_panic(void)
175 panic("SMP bolixed\n"); 175 panic("SMP bolixed\n");
176} 176}
177 177
178static unsigned long current_tick_offset __read_mostly;
179
180/* This tick register synchronization scheme is taken entirely from 178/* This tick register synchronization scheme is taken entirely from
181 * the ia64 port, see arch/ia64/kernel/smpboot.c for details and credit. 179 * the ia64 port, see arch/ia64/kernel/smpboot.c for details and credit.
182 * 180 *
@@ -259,7 +257,7 @@ void smp_synchronize_tick_client(void)
259 } else 257 } else
260 adj = -delta; 258 adj = -delta;
261 259
262 tick_ops->add_tick(adj, current_tick_offset); 260 tick_ops->add_tick(adj);
263 } 261 }
264#if DEBUG_TICK_SYNC 262#if DEBUG_TICK_SYNC
265 t[i].rt = rt; 263 t[i].rt = rt;
@@ -1178,30 +1176,9 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
1178 preempt_enable(); 1176 preempt_enable();
1179} 1177}
1180 1178
1181static void __init smp_setup_percpu_timer(void)
1182{
1183 unsigned long pstate;
1184
1185 /* Guarantee that the following sequences execute
1186 * uninterrupted.
1187 */
1188 __asm__ __volatile__("rdpr %%pstate, %0\n\t"
1189 "wrpr %0, %1, %%pstate"
1190 : "=r" (pstate)
1191 : "i" (PSTATE_IE));
1192
1193 tick_ops->init_tick(current_tick_offset);
1194
1195 /* Restore PSTATE_IE. */
1196 __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
1197 : /* no outputs */
1198 : "r" (pstate));
1199}
1200
1201void __init smp_tick_init(void) 1179void __init smp_tick_init(void)
1202{ 1180{
1203 boot_cpu_id = hard_smp_processor_id(); 1181 boot_cpu_id = hard_smp_processor_id();
1204 current_tick_offset = timer_tick_offset;
1205} 1182}
1206 1183
1207/* /proc/profile writes can call this, don't __init it please. */ 1184/* /proc/profile writes can call this, don't __init it please. */