aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/netlogic/common/smp.c
diff options
context:
space:
mode:
authorJayachandran C <jayachandranc@netlogicmicro.com>2011-11-15 19:21:29 -0500
committerRalf Baechle <ralf@linux-mips.org>2011-12-07 17:04:56 -0500
commit66d29985fab8207b1b2c03ac34a2c294c5b47a30 (patch)
treef73145e09c53606716266577eef5e14262129ed9 /arch/mips/netlogic/common/smp.c
parent8da24631e60438631112e6fdd198ef62416ff14a (diff)
MIPS: Netlogic: Merge some of XLR/XLP wakup code
Create a common NMI and reset handler in smpboot.S and use this for both XLR and XLP. In the earlier code, the woken up CPUs would busy wait until released, switch this to wakeup by NMI. The initial wakeup code or XLR and XLP are differ since they are started from different bootloaders (XLP from u-boot and XLR from netlogic bootloader). But in both platforms the woken up CPUs wait and are released by sending an NMI. Add support for starting XLR and XLP in 1/2/4 threads per core. Signed-off-by: Jayachandran C <jayachandranc@netlogicmicro.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2970/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/netlogic/common/smp.c')
-rw-r--r--arch/mips/netlogic/common/smp.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index c1960439f7e1..476c93ef3037 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -47,10 +47,12 @@
47 47
48#if defined(CONFIG_CPU_XLP) 48#if defined(CONFIG_CPU_XLP)
49#include <asm/netlogic/xlp-hal/iomap.h> 49#include <asm/netlogic/xlp-hal/iomap.h>
50#include <asm/netlogic/xlp-hal/xlp.h>
50#include <asm/netlogic/xlp-hal/pic.h> 51#include <asm/netlogic/xlp-hal/pic.h>
51#elif defined(CONFIG_CPU_XLR) 52#elif defined(CONFIG_CPU_XLR)
52#include <asm/netlogic/xlr/iomap.h> 53#include <asm/netlogic/xlr/iomap.h>
53#include <asm/netlogic/xlr/pic.h> 54#include <asm/netlogic/xlr/pic.h>
55#include <asm/netlogic/xlr/xlr.h>
54#else 56#else
55#error "Unknown CPU" 57#error "Unknown CPU"
56#endif 58#endif
@@ -125,10 +127,10 @@ void nlm_cpus_done(void)
125 * Boot all other cpus in the system, initialize them, and bring them into 127 * Boot all other cpus in the system, initialize them, and bring them into
126 * the boot function 128 * the boot function
127 */ 129 */
128int nlm_cpu_unblock[NR_CPUS];
129int nlm_cpu_ready[NR_CPUS]; 130int nlm_cpu_ready[NR_CPUS];
130unsigned long nlm_next_gp; 131unsigned long nlm_next_gp;
131unsigned long nlm_next_sp; 132unsigned long nlm_next_sp;
133
132cpumask_t phys_cpu_present_map; 134cpumask_t phys_cpu_present_map;
133 135
134void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) 136void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
@@ -142,7 +144,7 @@ void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
142 144
143 /* barrier */ 145 /* barrier */
144 __sync(); 146 __sync();
145 nlm_cpu_unblock[cpu] = 1; 147 nlm_pic_send_ipi(nlm_pic_base, cpu, 1, 1);
146} 148}
147 149
148void __init nlm_smp_setup(void) 150void __init nlm_smp_setup(void)
@@ -178,12 +180,81 @@ void __init nlm_smp_setup(void)
178 (unsigned long)cpu_possible_map.bits[0]); 180 (unsigned long)cpu_possible_map.bits[0]);
179 181
180 pr_info("Detected %i Slave CPU(s)\n", num_cpus); 182 pr_info("Detected %i Slave CPU(s)\n", num_cpus);
183 nlm_set_nmi_handler(nlm_boot_secondary_cpus);
181} 184}
182 185
183void nlm_prepare_cpus(unsigned int max_cpus) 186void nlm_prepare_cpus(unsigned int max_cpus)
184{ 187{
185} 188}
186 189
190static int nlm_parse_cpumask(u32 cpu_mask)
191{
192 uint32_t core0_thr_mask, core_thr_mask;
193 int threadmode, i;
194
195 core0_thr_mask = cpu_mask & 0xf;
196 switch (core0_thr_mask) {
197 case 1:
198 nlm_threads_per_core = 1;
199 threadmode = 0;
200 break;
201 case 3:
202 nlm_threads_per_core = 2;
203 threadmode = 2;
204 break;
205 case 0xf:
206 nlm_threads_per_core = 4;
207 threadmode = 3;
208 break;
209 default:
210 goto unsupp;
211 }
212
213 /* Verify other cores CPU masks */
214 nlm_coremask = 1;
215 nlm_cpumask = core0_thr_mask;
216 for (i = 1; i < 8; i++) {
217 core_thr_mask = (cpu_mask >> (i * 4)) & 0xf;
218 if (core_thr_mask) {
219 if (core_thr_mask != core0_thr_mask)
220 goto unsupp;
221 nlm_coremask |= 1 << i;
222 nlm_cpumask |= core0_thr_mask << (4 * i);
223 }
224 }
225 return threadmode;
226
227unsupp:
228 panic("Unsupported CPU mask %x\n", cpu_mask);
229 return 0;
230}
231
232int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask)
233{
234 unsigned long reset_vec;
235 char *reset_data;
236 int threadmode;
237
238 /* Update reset entry point with CPU init code */
239 reset_vec = CKSEG1ADDR(RESET_VEC_PHYS);
240 memcpy((void *)reset_vec, (void *)nlm_reset_entry,
241 (nlm_reset_entry_end - nlm_reset_entry));
242
243 /* verify the mask and setup core config variables */
244 threadmode = nlm_parse_cpumask(wakeup_mask);
245
246 /* Setup CPU init parameters */
247 reset_data = (char *)CKSEG1ADDR(RESET_DATA_PHYS);
248 *(int *)(reset_data + BOOT_THREAD_MODE) = threadmode;
249
250#ifdef CONFIG_CPU_XLP
251 xlp_wakeup_secondary_cpus();
252#else
253 xlr_wakeup_secondary_cpus();
254#endif
255 return 0;
256}
257
187struct plat_smp_ops nlm_smp_ops = { 258struct plat_smp_ops nlm_smp_ops = {
188 .send_ipi_single = nlm_send_ipi_single, 259 .send_ipi_single = nlm_send_ipi_single,
189 .send_ipi_mask = nlm_send_ipi_mask, 260 .send_ipi_mask = nlm_send_ipi_mask,