aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/cavium-octeon/octeon_boot.h16
-rw-r--r--arch/mips/cavium-octeon/smp.c125
-rw-r--r--arch/mips/include/asm/octeon/octeon.h2
3 files changed, 65 insertions, 78 deletions
diff --git a/arch/mips/cavium-octeon/octeon_boot.h b/arch/mips/cavium-octeon/octeon_boot.h
index 0f7f84accf9a..428864b2ba41 100644
--- a/arch/mips/cavium-octeon/octeon_boot.h
+++ b/arch/mips/cavium-octeon/octeon_boot.h
@@ -23,14 +23,16 @@
23#include <linux/types.h> 23#include <linux/types.h>
24 24
25struct boot_init_vector { 25struct boot_init_vector {
26 uint32_t stack_addr; 26 /* First stage address - in ram instead of flash */
27 uint32_t code_addr; 27 uint64_t code_addr;
28 /* Setup code for application, NOT application entry point */
28 uint32_t app_start_func_addr; 29 uint32_t app_start_func_addr;
30 /* k0 is used for global data - needs to be passed to other cores */
29 uint32_t k0_val; 31 uint32_t k0_val;
30 uint32_t flags; 32 /* Address of boot info block structure */
31 uint32_t boot_info_addr; 33 uint64_t boot_info_addr;
34 uint32_t flags; /* flags */
32 uint32_t pad; 35 uint32_t pad;
33 uint32_t pad2;
34}; 36};
35 37
36/* similar to bootloader's linux_app_boot_info but without global data */ 38/* similar to bootloader's linux_app_boot_info but without global data */
@@ -40,7 +42,7 @@ struct linux_app_boot_info {
40 uint32_t avail_coremask; 42 uint32_t avail_coremask;
41 uint32_t pci_console_active; 43 uint32_t pci_console_active;
42 uint32_t icache_prefetch_disable; 44 uint32_t icache_prefetch_disable;
43 uint32_t InitTLBStart_addr; 45 uint64_t InitTLBStart_addr;
44 uint32_t start_app_addr; 46 uint32_t start_app_addr;
45 uint32_t cur_exception_base; 47 uint32_t cur_exception_base;
46 uint32_t no_mark_private_data; 48 uint32_t no_mark_private_data;
@@ -58,7 +60,7 @@ struct linux_app_boot_info {
58 60
59#define LINUX_APP_BOOT_BLOCK_NAME "linux-app-boot" 61#define LINUX_APP_BOOT_BLOCK_NAME "linux-app-boot"
60 62
61#define LABI_SIGNATURE 0xAABBCCDD 63#define LABI_SIGNATURE 0xAABBCC01
62 64
63/* from uboot-headers/octeon_mem_map.h */ 65/* from uboot-headers/octeon_mem_map.h */
64#define EXCEPTION_BASE_INCR (4 * 1024) 66#define EXCEPTION_BASE_INCR (4 * 1024)
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index ceb76496e6ad..391cefe556b3 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -27,7 +27,8 @@ volatile unsigned long octeon_processor_sp;
27volatile unsigned long octeon_processor_gp; 27volatile unsigned long octeon_processor_gp;
28 28
29#ifdef CONFIG_HOTPLUG_CPU 29#ifdef CONFIG_HOTPLUG_CPU
30static unsigned int InitTLBStart_addr; 30uint64_t octeon_bootloader_entry_addr;
31EXPORT_SYMBOL(octeon_bootloader_entry_addr);
31#endif 32#endif
32 33
33static irqreturn_t mailbox_interrupt(int irq, void *dev_id) 34static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
@@ -80,20 +81,13 @@ static inline void octeon_send_ipi_mask(const struct cpumask *mask,
80static void octeon_smp_hotplug_setup(void) 81static void octeon_smp_hotplug_setup(void)
81{ 82{
82#ifdef CONFIG_HOTPLUG_CPU 83#ifdef CONFIG_HOTPLUG_CPU
83 uint32_t labi_signature; 84 struct linux_app_boot_info *labi;
84 85
85 labi_signature = 86 labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
86 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 87 if (labi->labi_signature != LABI_SIGNATURE)
87 LABI_ADDR_IN_BOOTLOADER + 88 panic("The bootloader version on this board is incorrect.");
88 offsetof(struct linux_app_boot_info, 89
89 labi_signature))); 90 octeon_bootloader_entry_addr = labi->InitTLBStart_addr;
90 if (labi_signature != LABI_SIGNATURE)
91 pr_err("The bootloader version on this board is incorrect\n");
92 InitTLBStart_addr =
93 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
94 LABI_ADDR_IN_BOOTLOADER +
95 offsetof(struct linux_app_boot_info,
96 InitTLBStart_addr)));
97#endif 91#endif
98} 92}
99 93
@@ -181,18 +175,21 @@ static void octeon_init_secondary(void)
181{ 175{
182 const int coreid = cvmx_get_core_num(); 176 const int coreid = cvmx_get_core_num();
183 union cvmx_ciu_intx_sum0 interrupt_enable; 177 union cvmx_ciu_intx_sum0 interrupt_enable;
178 unsigned int sr;
184 179
185#ifdef CONFIG_HOTPLUG_CPU 180#ifdef CONFIG_HOTPLUG_CPU
186 unsigned int cur_exception_base; 181 struct linux_app_boot_info *labi;
187 182
188 cur_exception_base = cvmx_read64_uint32( 183 labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
189 CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 184
190 LABI_ADDR_IN_BOOTLOADER + 185 if (labi->labi_signature != LABI_SIGNATURE)
191 offsetof(struct linux_app_boot_info, 186 panic("The bootloader version on this board is incorrect.");
192 cur_exception_base)));
193 /* cur_exception_base is incremented in bootloader after setting */
194 write_c0_ebase((unsigned int)(cur_exception_base - EXCEPTION_BASE_INCR));
195#endif 187#endif
188
189 sr = set_c0_status(ST0_BEV);
190 write_c0_ebase((u32)ebase);
191 write_c0_status(sr);
192
196 octeon_check_cpu_bist(); 193 octeon_check_cpu_bist();
197 octeon_init_cvmcount(); 194 octeon_init_cvmcount();
198 /* 195 /*
@@ -299,8 +296,8 @@ static int octeon_cpu_disable(void)
299static void octeon_cpu_die(unsigned int cpu) 296static void octeon_cpu_die(unsigned int cpu)
300{ 297{
301 int coreid = cpu_logical_map(cpu); 298 int coreid = cpu_logical_map(cpu);
302 uint32_t avail_coremask; 299 uint32_t mask, new_mask;
303 struct cvmx_bootmem_named_block_desc *block_desc; 300 const struct cvmx_bootmem_named_block_desc *block_desc;
304 301
305 while (per_cpu(cpu_state, cpu) != CPU_DEAD) 302 while (per_cpu(cpu_state, cpu) != CPU_DEAD)
306 cpu_relax(); 303 cpu_relax();
@@ -309,52 +306,40 @@ static void octeon_cpu_die(unsigned int cpu)
309 * This is a bit complicated strategics of getting/settig available 306 * This is a bit complicated strategics of getting/settig available
310 * cores mask, copied from bootloader 307 * cores mask, copied from bootloader
311 */ 308 */
309
310 mask = 1 << coreid;
312 /* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */ 311 /* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */
313 block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); 312 block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME);
314 313
315 if (!block_desc) { 314 if (!block_desc) {
316 avail_coremask = 315 struct linux_app_boot_info *labi;
317 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
318 LABI_ADDR_IN_BOOTLOADER +
319 offsetof
320 (struct linux_app_boot_info,
321 avail_coremask)));
322 } else { /* alternative, already initialized */
323 avail_coremask =
324 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
325 block_desc->base_addr +
326 AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK));
327 }
328 316
329 avail_coremask |= 1 << coreid; 317 labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
330 318
331 /* Setting avail_coremask for bootoct binary */ 319 labi->avail_coremask |= mask;
332 if (!block_desc) { 320 new_mask = labi->avail_coremask;
333 cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 321 } else { /* alternative, already initialized */
334 LABI_ADDR_IN_BOOTLOADER + 322 uint32_t *p = (uint32_t *)PHYS_TO_XKSEG_CACHED(block_desc->base_addr +
335 offsetof(struct linux_app_boot_info, 323 AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK);
336 avail_coremask)), 324 *p |= mask;
337 avail_coremask); 325 new_mask = *p;
338 } else {
339 cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
340 block_desc->base_addr +
341 AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK),
342 avail_coremask);
343 } 326 }
344 327
345 pr_info("Reset core %d. Available Coremask = %x\n", coreid, 328 pr_info("Reset core %d. Available Coremask = 0x%x \n", coreid, new_mask);
346 avail_coremask); 329 mb();
347 cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); 330 cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid);
348 cvmx_write_csr(CVMX_CIU_PP_RST, 0); 331 cvmx_write_csr(CVMX_CIU_PP_RST, 0);
349} 332}
350 333
351void play_dead(void) 334void play_dead(void)
352{ 335{
353 int coreid = cvmx_get_core_num(); 336 int cpu = cpu_number_map(cvmx_get_core_num());
354 337
355 idle_task_exit(); 338 idle_task_exit();
356 octeon_processor_boot = 0xff; 339 octeon_processor_boot = 0xff;
357 per_cpu(cpu_state, coreid) = CPU_DEAD; 340 per_cpu(cpu_state, cpu) = CPU_DEAD;
341
342 mb();
358 343
359 while (1) /* core will be reset here */ 344 while (1) /* core will be reset here */
360 ; 345 ;
@@ -367,29 +352,27 @@ static void start_after_reset(void)
367 kernel_entry(0, 0, 0); /* set a2 = 0 for secondary core */ 352 kernel_entry(0, 0, 0); /* set a2 = 0 for secondary core */
368} 353}
369 354
370int octeon_update_boot_vector(unsigned int cpu) 355static int octeon_update_boot_vector(unsigned int cpu)
371{ 356{
372 357
373 int coreid = cpu_logical_map(cpu); 358 int coreid = cpu_logical_map(cpu);
374 unsigned int avail_coremask; 359 uint32_t avail_coremask;
375 struct cvmx_bootmem_named_block_desc *block_desc; 360 const struct cvmx_bootmem_named_block_desc *block_desc;
376 struct boot_init_vector *boot_vect = 361 struct boot_init_vector *boot_vect =
377 (struct boot_init_vector *) cvmx_phys_to_ptr(0x0 + 362 (struct boot_init_vector *)PHYS_TO_XKSEG_CACHED(BOOTLOADER_BOOT_VECTOR);
378 BOOTLOADER_BOOT_VECTOR);
379 363
380 block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); 364 block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME);
381 365
382 if (!block_desc) { 366 if (!block_desc) {
383 avail_coremask = 367 struct linux_app_boot_info *labi;
384 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 368
385 LABI_ADDR_IN_BOOTLOADER + 369 labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
386 offsetof(struct linux_app_boot_info, 370
387 avail_coremask))); 371 avail_coremask = labi->avail_coremask;
372 labi->avail_coremask &= ~(1 << coreid);
388 } else { /* alternative, already initialized */ 373 } else { /* alternative, already initialized */
389 avail_coremask = 374 avail_coremask = *(uint32_t *)PHYS_TO_XKSEG_CACHED(
390 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 375 block_desc->base_addr + AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK);
391 block_desc->base_addr +
392 AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK));
393 } 376 }
394 377
395 if (!(avail_coremask & (1 << coreid))) { 378 if (!(avail_coremask & (1 << coreid))) {
@@ -400,9 +383,9 @@ int octeon_update_boot_vector(unsigned int cpu)
400 383
401 boot_vect[coreid].app_start_func_addr = 384 boot_vect[coreid].app_start_func_addr =
402 (uint32_t) (unsigned long) start_after_reset; 385 (uint32_t) (unsigned long) start_after_reset;
403 boot_vect[coreid].code_addr = InitTLBStart_addr; 386 boot_vect[coreid].code_addr = octeon_bootloader_entry_addr;
404 387
405 CVMX_SYNC; 388 mb();
406 389
407 cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask); 390 cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask);
408 391
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index ca6214b5ccb9..c29debe7a8ad 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -253,4 +253,6 @@ static inline uint32_t octeon_npi_read32(uint64_t address)
253 253
254extern struct cvmx_bootinfo *octeon_bootinfo; 254extern struct cvmx_bootinfo *octeon_bootinfo;
255 255
256extern uint64_t octeon_bootloader_entry_addr;
257
256#endif /* __ASM_OCTEON_OCTEON_H */ 258#endif /* __ASM_OCTEON_OCTEON_H */