2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2004-2008 Cavium Networks
8 #include <linux/init.h>
9 #include <linux/delay.h>
10 #include <linux/smp.h>
11 #include <linux/interrupt.h>
12 #include <linux/kernel_stat.h>
13 #include <linux/sched.h>
14 #include <linux/module.h>
16 #include <asm/mmu_context.h>
17 #include <asm/system.h>
20 #include <asm/octeon/octeon.h>
22 volatile unsigned long octeon_processor_boot
= 0xff;
23 volatile unsigned long octeon_processor_sp
;
24 volatile unsigned long octeon_processor_gp
;
26 static irqreturn_t
mailbox_interrupt(int irq
, void *dev_id
)
28 const int coreid
= cvmx_get_core_num();
31 /* Load the mailbox register to figure out what we're supposed to do */
32 action
= cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid
));
34 /* Clear the mailbox to clear the interrupt */
35 cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid
), action
);
37 if (action
& SMP_CALL_FUNCTION
)
38 smp_call_function_interrupt();
40 /* Check if we've been told to flush the icache */
41 if (action
& SMP_ICACHE_FLUSH
)
42 asm volatile ("synci 0($0)\n");
47 * Cause the function described by call_data to be executed on the passed
48 * cpu. When the function has finished, increment the finished field of
51 void octeon_send_ipi_single(int cpu
, unsigned int action
)
53 int coreid
= cpu_logical_map(cpu
);
55 pr_info("SMP: Mailbox send cpu=%d, coreid=%d, action=%u\n", cpu,
58 cvmx_write_csr(CVMX_CIU_MBOX_SETX(coreid
), action
);
61 static inline void octeon_send_ipi_mask(cpumask_t mask
, unsigned int action
)
65 for_each_cpu_mask(i
, mask
)
66 octeon_send_ipi_single(i
, action
);
70 * Detect available CPUs, populate phys_cpu_present_map
72 static void octeon_smp_setup(void)
74 const int coreid
= cvmx_get_core_num();
78 int core_mask
= octeon_get_boot_coremask();
80 cpus_clear(cpu_possible_map
);
81 __cpu_number_map
[coreid
] = 0;
82 __cpu_logical_map
[0] = coreid
;
83 cpu_set(0, cpu_possible_map
);
86 for (id
= 0; id
< 16; id
++) {
87 if ((id
!= coreid
) && (core_mask
& (1 << id
))) {
88 cpu_set(cpus
, cpu_possible_map
);
89 __cpu_number_map
[id
] = cpus
;
90 __cpu_logical_map
[cpus
] = id
;
97 * Firmware CPU startup hook
100 static void octeon_boot_secondary(int cpu
, struct task_struct
*idle
)
104 pr_info("SMP: Booting CPU%02d (CoreId %2d)...\n", cpu
,
105 cpu_logical_map(cpu
));
107 octeon_processor_sp
= __KSTK_TOS(idle
);
108 octeon_processor_gp
= (unsigned long)(task_thread_info(idle
));
109 octeon_processor_boot
= cpu_logical_map(cpu
);
113 while (octeon_processor_sp
&& count
) {
114 /* Waiting for processor to get the SP and GP */
119 pr_err("Secondary boot timeout\n");
123 * After we've done initial boot, this function is called to allow the
124 * board code to clean up state, if needed
126 static void octeon_init_secondary(void)
128 const int coreid
= cvmx_get_core_num();
129 union cvmx_ciu_intx_sum0 interrupt_enable
;
131 octeon_check_cpu_bist();
132 octeon_init_cvmcount();
134 pr_info("SMP: CPU%d (CoreId %lu) started\n", cpu, coreid);
136 /* Enable Mailbox interrupts to this core. These are the only
137 interrupts allowed on line 3 */
138 cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid
), 0xffffffff);
139 interrupt_enable
.u64
= 0;
140 interrupt_enable
.s
.mbox
= 0x3;
141 cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid
* 2)), interrupt_enable
.u64
);
142 cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid
* 2 + 1)), 0);
143 cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid
* 2)), 0);
144 cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid
* 2 + 1)), 0);
145 /* Enable core interrupt processing for 2,3 and 7 */
146 set_c0_status(0x8c01);
150 * Callout to firmware before smp_init
153 void octeon_prepare_cpus(unsigned int max_cpus
)
155 cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff);
156 if (request_irq(OCTEON_IRQ_MBOX0
, mailbox_interrupt
, IRQF_SHARED
,
157 "mailbox0", mailbox_interrupt
)) {
158 panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
160 if (request_irq(OCTEON_IRQ_MBOX1
, mailbox_interrupt
, IRQF_SHARED
,
161 "mailbox1", mailbox_interrupt
)) {
162 panic("Cannot request_irq(OCTEON_IRQ_MBOX1)\n");
167 * Last chance for the board code to finish SMP initialization before
168 * the CPU is "online".
170 static void octeon_smp_finish(void)
172 #ifdef CONFIG_CAVIUM_GDB
174 /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0
175 to be not masked by this core so we know the signal is received by
177 asm volatile ("dmfc0 %0, $22\n"
178 "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp
));
181 octeon_user_io_init();
183 /* to generate the first CPU timer interrupt */
184 write_c0_compare(read_c0_count() + mips_hpt_frequency
/ HZ
);
188 * Hook for after all CPUs are online
190 static void octeon_cpus_done(void)
192 #ifdef CONFIG_CAVIUM_GDB
194 /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0
195 to be not masked by this core so we know the signal is received by
197 asm volatile ("dmfc0 %0, $22\n"
198 "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp
));
202 struct plat_smp_ops octeon_smp_ops
= {
203 .send_ipi_single
= octeon_send_ipi_single
,
204 .send_ipi_mask
= octeon_send_ipi_mask
,
205 .init_secondary
= octeon_init_secondary
,
206 .smp_finish
= octeon_smp_finish
,
207 .cpus_done
= octeon_cpus_done
,
208 .boot_secondary
= octeon_boot_secondary
,
209 .smp_setup
= octeon_smp_setup
,
210 .prepare_cpus
= octeon_prepare_cpus
,