omap_hsmmc: Flush posted write to IRQ
[linux-ginger.git] / arch / mips / cavium-octeon / smp.c
blob24e0ad63980afe3940e2618778fd7d136c25e34c
1 /*
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
4 * for more details.
6 * Copyright (C) 2004-2008 Cavium Networks
7 */
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>
18 #include <asm/time.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();
29 uint64_t action;
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");
43 return IRQ_HANDLED;
46 /**
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
49 * call_data.
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,
56 coreid, action);
58 cvmx_write_csr(CVMX_CIU_MBOX_SETX(coreid), action);
61 static inline void octeon_send_ipi_mask(cpumask_t mask, unsigned int action)
63 unsigned int i;
65 for_each_cpu_mask(i, mask)
66 octeon_send_ipi_single(i, action);
69 /**
70 * Detect available CPUs, populate phys_cpu_present_map
72 static void octeon_smp_setup(void)
74 const int coreid = cvmx_get_core_num();
75 int cpus;
76 int id;
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);
85 cpus = 1;
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;
91 cpus++;
96 /**
97 * Firmware CPU startup hook
100 static void octeon_boot_secondary(int cpu, struct task_struct *idle)
102 int count;
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);
110 mb();
112 count = 10000;
113 while (octeon_processor_sp && count) {
114 /* Waiting for processor to get the SP and GP */
115 udelay(1);
116 count--;
118 if (count == 0)
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
173 unsigned long tmp;
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
176 someone */
177 asm volatile ("dmfc0 %0, $22\n"
178 "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp));
179 #endif
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
193 unsigned long tmp;
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
196 someone */
197 asm volatile ("dmfc0 %0, $22\n"
198 "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp));
199 #endif
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,