xref: /openbmc/linux/arch/powerpc/platforms/chrp/smp.c (revision bbd0abda9cc689a54df509aae00000bbb2a1a7d1)
1*bbd0abdaSPaul Mackerras /*
2*bbd0abdaSPaul Mackerras  * Smp support for CHRP machines.
3*bbd0abdaSPaul Mackerras  *
4*bbd0abdaSPaul Mackerras  * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
5*bbd0abdaSPaul Mackerras  * deal of code from the sparc and intel versions.
6*bbd0abdaSPaul Mackerras  *
7*bbd0abdaSPaul Mackerras  * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
8*bbd0abdaSPaul Mackerras  *
9*bbd0abdaSPaul Mackerras  */
10*bbd0abdaSPaul Mackerras 
11*bbd0abdaSPaul Mackerras #include <linux/config.h>
12*bbd0abdaSPaul Mackerras #include <linux/kernel.h>
13*bbd0abdaSPaul Mackerras #include <linux/sched.h>
14*bbd0abdaSPaul Mackerras #include <linux/smp.h>
15*bbd0abdaSPaul Mackerras #include <linux/smp_lock.h>
16*bbd0abdaSPaul Mackerras #include <linux/interrupt.h>
17*bbd0abdaSPaul Mackerras #include <linux/kernel_stat.h>
18*bbd0abdaSPaul Mackerras #include <linux/delay.h>
19*bbd0abdaSPaul Mackerras #include <linux/init.h>
20*bbd0abdaSPaul Mackerras #include <linux/spinlock.h>
21*bbd0abdaSPaul Mackerras 
22*bbd0abdaSPaul Mackerras #include <asm/ptrace.h>
23*bbd0abdaSPaul Mackerras #include <asm/atomic.h>
24*bbd0abdaSPaul Mackerras #include <asm/irq.h>
25*bbd0abdaSPaul Mackerras #include <asm/page.h>
26*bbd0abdaSPaul Mackerras #include <asm/pgtable.h>
27*bbd0abdaSPaul Mackerras #include <asm/sections.h>
28*bbd0abdaSPaul Mackerras #include <asm/io.h>
29*bbd0abdaSPaul Mackerras #include <asm/prom.h>
30*bbd0abdaSPaul Mackerras #include <asm/smp.h>
31*bbd0abdaSPaul Mackerras #include <asm/residual.h>
32*bbd0abdaSPaul Mackerras #include <asm/time.h>
33*bbd0abdaSPaul Mackerras #include <asm/open_pic.h>
34*bbd0abdaSPaul Mackerras #include <asm/machdep.h>
35*bbd0abdaSPaul Mackerras 
36*bbd0abdaSPaul Mackerras extern unsigned long smp_chrp_cpu_nr;
37*bbd0abdaSPaul Mackerras 
38*bbd0abdaSPaul Mackerras static int __init smp_chrp_probe(void)
39*bbd0abdaSPaul Mackerras {
40*bbd0abdaSPaul Mackerras 	if (smp_chrp_cpu_nr > 1)
41*bbd0abdaSPaul Mackerras 		openpic_request_IPIs();
42*bbd0abdaSPaul Mackerras 
43*bbd0abdaSPaul Mackerras 	return smp_chrp_cpu_nr;
44*bbd0abdaSPaul Mackerras }
45*bbd0abdaSPaul Mackerras 
46*bbd0abdaSPaul Mackerras static void __devinit smp_chrp_kick_cpu(int nr)
47*bbd0abdaSPaul Mackerras {
48*bbd0abdaSPaul Mackerras 	*(unsigned long *)KERNELBASE = nr;
49*bbd0abdaSPaul Mackerras 	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
50*bbd0abdaSPaul Mackerras }
51*bbd0abdaSPaul Mackerras 
52*bbd0abdaSPaul Mackerras static void __devinit smp_chrp_setup_cpu(int cpu_nr)
53*bbd0abdaSPaul Mackerras {
54*bbd0abdaSPaul Mackerras 	if (OpenPIC_Addr)
55*bbd0abdaSPaul Mackerras 		do_openpic_setup_cpu();
56*bbd0abdaSPaul Mackerras }
57*bbd0abdaSPaul Mackerras 
58*bbd0abdaSPaul Mackerras static DEFINE_SPINLOCK(timebase_lock);
59*bbd0abdaSPaul Mackerras static unsigned int timebase_upper = 0, timebase_lower = 0;
60*bbd0abdaSPaul Mackerras 
61*bbd0abdaSPaul Mackerras void __devinit smp_chrp_give_timebase(void)
62*bbd0abdaSPaul Mackerras {
63*bbd0abdaSPaul Mackerras 	spin_lock(&timebase_lock);
64*bbd0abdaSPaul Mackerras 	rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
65*bbd0abdaSPaul Mackerras 	timebase_upper = get_tbu();
66*bbd0abdaSPaul Mackerras 	timebase_lower = get_tbl();
67*bbd0abdaSPaul Mackerras 	spin_unlock(&timebase_lock);
68*bbd0abdaSPaul Mackerras 
69*bbd0abdaSPaul Mackerras 	while (timebase_upper || timebase_lower)
70*bbd0abdaSPaul Mackerras 		barrier();
71*bbd0abdaSPaul Mackerras 	rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
72*bbd0abdaSPaul Mackerras }
73*bbd0abdaSPaul Mackerras 
74*bbd0abdaSPaul Mackerras void __devinit smp_chrp_take_timebase(void)
75*bbd0abdaSPaul Mackerras {
76*bbd0abdaSPaul Mackerras 	while (!(timebase_upper || timebase_lower))
77*bbd0abdaSPaul Mackerras 		barrier();
78*bbd0abdaSPaul Mackerras 	spin_lock(&timebase_lock);
79*bbd0abdaSPaul Mackerras 	set_tb(timebase_upper, timebase_lower);
80*bbd0abdaSPaul Mackerras 	timebase_upper = 0;
81*bbd0abdaSPaul Mackerras 	timebase_lower = 0;
82*bbd0abdaSPaul Mackerras 	spin_unlock(&timebase_lock);
83*bbd0abdaSPaul Mackerras 	printk("CPU %i taken timebase\n", smp_processor_id());
84*bbd0abdaSPaul Mackerras }
85*bbd0abdaSPaul Mackerras 
86*bbd0abdaSPaul Mackerras /* CHRP with openpic */
87*bbd0abdaSPaul Mackerras struct smp_ops_t chrp_smp_ops = {
88*bbd0abdaSPaul Mackerras 	.message_pass = smp_openpic_message_pass,
89*bbd0abdaSPaul Mackerras 	.probe = smp_chrp_probe,
90*bbd0abdaSPaul Mackerras 	.kick_cpu = smp_chrp_kick_cpu,
91*bbd0abdaSPaul Mackerras 	.setup_cpu = smp_chrp_setup_cpu,
92*bbd0abdaSPaul Mackerras 	.give_timebase = smp_chrp_give_timebase,
93*bbd0abdaSPaul Mackerras 	.take_timebase = smp_chrp_take_timebase,
94*bbd0abdaSPaul Mackerras };
95