port enough sendpoint support for DSM-G600 from D-Link 2.4.21-pre4
[linux-2.4.git] / arch / ppc / platforms / chrp_smp.c
1 /*
2  * Smp support for CHRP machines.
3  *
4  * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
5  * deal of code from the sparc and intel versions.
6  *
7  * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
8  *
9  */
10
11 #include <linux/config.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/smp.h>
15 #include <linux/smp_lock.h>
16 #include <linux/interrupt.h>
17 #include <linux/kernel_stat.h>
18 #include <linux/delay.h>
19 #define __KERNEL_SYSCALLS__
20 #include <linux/unistd.h>
21 #include <linux/init.h>
22 #include <linux/spinlock.h>
23
24 #include <asm/ptrace.h>
25 #include <asm/atomic.h>
26 #include <asm/irq.h>
27 #include <asm/page.h>
28 #include <asm/pgtable.h>
29 #include <asm/hardirq.h>
30 #include <asm/softirq.h>
31 #include <asm/sections.h>
32 #include <asm/io.h>
33 #include <asm/prom.h>
34 #include <asm/smp.h>
35 #include <asm/residual.h>
36 #include <asm/time.h>
37 #include <asm/open_pic.h>
38
39 extern unsigned long smp_chrp_cpu_nr;
40
41 /*
42  * The CHRP RTAS note on multiprocessor systems:
43  * "In a multiprocessor system, each processor should
44  * call event-scan periodically, not always the same
45  * one.  The event-scan function needs to be called a
46  * total of rtas-event-scan-rate times a minute"
47  *
48  * We must call on each cpu in on a regular basis
49  * so that firmware can watch for cpu unique errors.
50  */
51 static void spread_heartbeat(void)
52 {
53         unsigned count = heartbeat_count(0);
54         unsigned offset = count;
55         int i;
56
57         if (!count || smp_chrp_cpu_nr < 2)
58                 return;
59
60         count *=  smp_chrp_cpu_nr;
61
62         for (i = 0; i < smp_chrp_cpu_nr ; i++)
63         {
64                 heartbeat_reset(i) = count;
65                 heartbeat_count(i) = i * offset;
66         }
67         printk("RTAS Event Scan now every %u jiffes on each cpu\n", count);
68 }
69
70 static int __init
71 smp_chrp_probe(void)
72 {
73         if (smp_chrp_cpu_nr > 1)
74                 openpic_request_IPIs();
75
76         return smp_chrp_cpu_nr;
77 }
78
79 static void __init
80 smp_chrp_kick_cpu(int nr)
81 {
82         *(unsigned long *)KERNELBASE = nr;
83         asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
84 }
85
86 static void __init
87 smp_chrp_setup_cpu(int cpu_nr)
88 {
89         static atomic_t ready = ATOMIC_INIT(1);
90         static volatile int frozen = 0;
91
92         if (cpu_nr == 0) {
93                 /* wait for all the others */
94                 while (atomic_read(&ready) < smp_num_cpus)
95                         barrier();
96                 atomic_set(&ready, 1);
97                 /* freeze the timebase */
98                 call_rtas("freeze-time-base", 0, 1, NULL);
99                 mb();
100                 frozen = 1;
101                 /* XXX assumes this is not a 601 */
102                 set_tb(0, 0);
103                 last_jiffy_stamp(0) = 0;
104                 while (atomic_read(&ready) < smp_num_cpus)
105                         barrier();
106                 /* thaw the timebase again */
107                 call_rtas("thaw-time-base", 0, 1, NULL);
108                 mb();
109                 frozen = 0;
110                 smp_tb_synchronized = 1;
111         } else {
112                 atomic_inc(&ready);
113                 while (!frozen)
114                         barrier();
115                 set_tb(0, 0);
116                 last_jiffy_stamp(0) = 0;
117                 mb();
118                 atomic_inc(&ready);
119                 while (frozen)
120                         barrier();
121         }
122
123         if (OpenPIC_Addr)
124                 do_openpic_setup_cpu();
125
126         spread_heartbeat();
127 }
128
129 /* CHRP with openpic */
130 struct smp_ops_t chrp_smp_ops __chrpdata = {
131         smp_openpic_message_pass,
132         smp_chrp_probe,
133         smp_chrp_kick_cpu,
134         smp_chrp_setup_cpu,
135 };