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. 5 * 6 * Copyright (C) 2004-2008 Cavium Networks 7 */ 8 #include <linux/cpu.h> 9 #include <linux/init.h> 10 #include <linux/delay.h> 11 #include <linux/smp.h> 12 #include <linux/interrupt.h> 13 #include <linux/kernel_stat.h> 14 #include <linux/sched.h> 15 #include <linux/module.h> 16 17 #include <asm/mmu_context.h> 18 #include <asm/system.h> 19 #include <asm/time.h> 20 21 #include <asm/octeon/octeon.h> 22 23 #include "octeon_boot.h" 24 25 volatile unsigned long octeon_processor_boot = 0xff; 26 volatile unsigned long octeon_processor_sp; 27 volatile unsigned long octeon_processor_gp; 28 29 #ifdef CONFIG_HOTPLUG_CPU 30 static unsigned int InitTLBStart_addr; 31 #endif 32 33 static irqreturn_t mailbox_interrupt(int irq, void *dev_id) 34 { 35 const int coreid = cvmx_get_core_num(); 36 uint64_t action; 37 38 /* Load the mailbox register to figure out what we're supposed to do */ 39 action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid)); 40 41 /* Clear the mailbox to clear the interrupt */ 42 cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action); 43 44 if (action & SMP_CALL_FUNCTION) 45 smp_call_function_interrupt(); 46 47 /* Check if we've been told to flush the icache */ 48 if (action & SMP_ICACHE_FLUSH) 49 asm volatile ("synci 0($0)\n"); 50 return IRQ_HANDLED; 51 } 52 53 /** 54 * Cause the function described by call_data to be executed on the passed 55 * cpu. When the function has finished, increment the finished field of 56 * call_data. 57 */ 58 void octeon_send_ipi_single(int cpu, unsigned int action) 59 { 60 int coreid = cpu_logical_map(cpu); 61 /* 62 pr_info("SMP: Mailbox send cpu=%d, coreid=%d, action=%u\n", cpu, 63 coreid, action); 64 */ 65 cvmx_write_csr(CVMX_CIU_MBOX_SETX(coreid), action); 66 } 67 68 static inline void octeon_send_ipi_mask(const struct cpumask *mask, 69 unsigned int action) 70 { 71 unsigned int i; 72 73 for_each_cpu_mask(i, *mask) 74 octeon_send_ipi_single(i, action); 75 } 76 77 /** 78 * Detect available CPUs, populate cpu_possible_map 79 */ 80 static void octeon_smp_hotplug_setup(void) 81 { 82 #ifdef CONFIG_HOTPLUG_CPU 83 uint32_t labi_signature; 84 85 labi_signature = 86 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 87 LABI_ADDR_IN_BOOTLOADER + 88 offsetof(struct linux_app_boot_info, 89 labi_signature))); 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 98 } 99 100 static void octeon_smp_setup(void) 101 { 102 const int coreid = cvmx_get_core_num(); 103 int cpus; 104 int id; 105 106 int core_mask = octeon_get_boot_coremask(); 107 108 cpus_clear(cpu_possible_map); 109 __cpu_number_map[coreid] = 0; 110 __cpu_logical_map[0] = coreid; 111 cpu_set(0, cpu_possible_map); 112 113 cpus = 1; 114 for (id = 0; id < 16; id++) { 115 if ((id != coreid) && (core_mask & (1 << id))) { 116 cpu_set(cpus, cpu_possible_map); 117 __cpu_number_map[id] = cpus; 118 __cpu_logical_map[cpus] = id; 119 cpus++; 120 } 121 } 122 cpu_present_map = cpu_possible_map; 123 124 octeon_smp_hotplug_setup(); 125 } 126 127 /** 128 * Firmware CPU startup hook 129 * 130 */ 131 static void octeon_boot_secondary(int cpu, struct task_struct *idle) 132 { 133 int count; 134 135 pr_info("SMP: Booting CPU%02d (CoreId %2d)...\n", cpu, 136 cpu_logical_map(cpu)); 137 138 octeon_processor_sp = __KSTK_TOS(idle); 139 octeon_processor_gp = (unsigned long)(task_thread_info(idle)); 140 octeon_processor_boot = cpu_logical_map(cpu); 141 mb(); 142 143 count = 10000; 144 while (octeon_processor_sp && count) { 145 /* Waiting for processor to get the SP and GP */ 146 udelay(1); 147 count--; 148 } 149 if (count == 0) 150 pr_err("Secondary boot timeout\n"); 151 } 152 153 /** 154 * After we've done initial boot, this function is called to allow the 155 * board code to clean up state, if needed 156 */ 157 static void octeon_init_secondary(void) 158 { 159 const int coreid = cvmx_get_core_num(); 160 union cvmx_ciu_intx_sum0 interrupt_enable; 161 162 #ifdef CONFIG_HOTPLUG_CPU 163 unsigned int cur_exception_base; 164 165 cur_exception_base = cvmx_read64_uint32( 166 CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 167 LABI_ADDR_IN_BOOTLOADER + 168 offsetof(struct linux_app_boot_info, 169 cur_exception_base))); 170 /* cur_exception_base is incremented in bootloader after setting */ 171 write_c0_ebase((unsigned int)(cur_exception_base - EXCEPTION_BASE_INCR)); 172 #endif 173 octeon_check_cpu_bist(); 174 octeon_init_cvmcount(); 175 /* 176 pr_info("SMP: CPU%d (CoreId %lu) started\n", cpu, coreid); 177 */ 178 /* Enable Mailbox interrupts to this core. These are the only 179 interrupts allowed on line 3 */ 180 cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), 0xffffffff); 181 interrupt_enable.u64 = 0; 182 interrupt_enable.s.mbox = 0x3; 183 cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), interrupt_enable.u64); 184 cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0); 185 cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0); 186 cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0); 187 /* Enable core interrupt processing for 2,3 and 7 */ 188 set_c0_status(0x8c01); 189 } 190 191 /** 192 * Callout to firmware before smp_init 193 * 194 */ 195 void octeon_prepare_cpus(unsigned int max_cpus) 196 { 197 cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff); 198 if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED, 199 "mailbox0", mailbox_interrupt)) { 200 panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n"); 201 } 202 if (request_irq(OCTEON_IRQ_MBOX1, mailbox_interrupt, IRQF_DISABLED, 203 "mailbox1", mailbox_interrupt)) { 204 panic("Cannot request_irq(OCTEON_IRQ_MBOX1)\n"); 205 } 206 } 207 208 /** 209 * Last chance for the board code to finish SMP initialization before 210 * the CPU is "online". 211 */ 212 static void octeon_smp_finish(void) 213 { 214 #ifdef CONFIG_CAVIUM_GDB 215 unsigned long tmp; 216 /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0 217 to be not masked by this core so we know the signal is received by 218 someone */ 219 asm volatile ("dmfc0 %0, $22\n" 220 "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp)); 221 #endif 222 223 octeon_user_io_init(); 224 225 /* to generate the first CPU timer interrupt */ 226 write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ); 227 } 228 229 /** 230 * Hook for after all CPUs are online 231 */ 232 static void octeon_cpus_done(void) 233 { 234 #ifdef CONFIG_CAVIUM_GDB 235 unsigned long tmp; 236 /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0 237 to be not masked by this core so we know the signal is received by 238 someone */ 239 asm volatile ("dmfc0 %0, $22\n" 240 "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp)); 241 #endif 242 } 243 244 #ifdef CONFIG_HOTPLUG_CPU 245 246 /* State of each CPU. */ 247 DEFINE_PER_CPU(int, cpu_state); 248 249 extern void fixup_irqs(void); 250 251 static DEFINE_SPINLOCK(smp_reserve_lock); 252 253 static int octeon_cpu_disable(void) 254 { 255 unsigned int cpu = smp_processor_id(); 256 257 if (cpu == 0) 258 return -EBUSY; 259 260 spin_lock(&smp_reserve_lock); 261 262 cpu_clear(cpu, cpu_online_map); 263 cpu_clear(cpu, cpu_callin_map); 264 local_irq_disable(); 265 fixup_irqs(); 266 local_irq_enable(); 267 268 flush_cache_all(); 269 local_flush_tlb_all(); 270 271 spin_unlock(&smp_reserve_lock); 272 273 return 0; 274 } 275 276 static void octeon_cpu_die(unsigned int cpu) 277 { 278 int coreid = cpu_logical_map(cpu); 279 uint32_t avail_coremask; 280 struct cvmx_bootmem_named_block_desc *block_desc; 281 282 #ifdef CONFIG_CAVIUM_OCTEON_WATCHDOG 283 /* Disable the watchdog */ 284 cvmx_ciu_wdogx_t ciu_wdog; 285 ciu_wdog.u64 = cvmx_read_csr(CVMX_CIU_WDOGX(cpu)); 286 ciu_wdog.s.mode = 0; 287 cvmx_write_csr(CVMX_CIU_WDOGX(cpu), ciu_wdog.u64); 288 #endif 289 290 while (per_cpu(cpu_state, cpu) != CPU_DEAD) 291 cpu_relax(); 292 293 /* 294 * This is a bit complicated strategics of getting/settig available 295 * cores mask, copied from bootloader 296 */ 297 /* LINUX_APP_BOOT_BLOCK is initialized in bootoct binary */ 298 block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); 299 300 if (!block_desc) { 301 avail_coremask = 302 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 303 LABI_ADDR_IN_BOOTLOADER + 304 offsetof 305 (struct linux_app_boot_info, 306 avail_coremask))); 307 } else { /* alternative, already initialized */ 308 avail_coremask = 309 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 310 block_desc->base_addr + 311 AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); 312 } 313 314 avail_coremask |= 1 << coreid; 315 316 /* Setting avail_coremask for bootoct binary */ 317 if (!block_desc) { 318 cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 319 LABI_ADDR_IN_BOOTLOADER + 320 offsetof(struct linux_app_boot_info, 321 avail_coremask)), 322 avail_coremask); 323 } else { 324 cvmx_write64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 325 block_desc->base_addr + 326 AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK), 327 avail_coremask); 328 } 329 330 pr_info("Reset core %d. Available Coremask = %x \n", coreid, 331 avail_coremask); 332 cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); 333 cvmx_write_csr(CVMX_CIU_PP_RST, 0); 334 } 335 336 void play_dead(void) 337 { 338 int coreid = cvmx_get_core_num(); 339 340 idle_task_exit(); 341 octeon_processor_boot = 0xff; 342 per_cpu(cpu_state, coreid) = CPU_DEAD; 343 344 while (1) /* core will be reset here */ 345 ; 346 } 347 348 extern void kernel_entry(unsigned long arg1, ...); 349 350 static void start_after_reset(void) 351 { 352 kernel_entry(0, 0, 0); /* set a2 = 0 for secondary core */ 353 } 354 355 int octeon_update_boot_vector(unsigned int cpu) 356 { 357 358 int coreid = cpu_logical_map(cpu); 359 unsigned int avail_coremask; 360 struct cvmx_bootmem_named_block_desc *block_desc; 361 struct boot_init_vector *boot_vect = 362 (struct boot_init_vector *) cvmx_phys_to_ptr(0x0 + 363 BOOTLOADER_BOOT_VECTOR); 364 365 block_desc = cvmx_bootmem_find_named_block(LINUX_APP_BOOT_BLOCK_NAME); 366 367 if (!block_desc) { 368 avail_coremask = 369 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 370 LABI_ADDR_IN_BOOTLOADER + 371 offsetof(struct linux_app_boot_info, 372 avail_coremask))); 373 } else { /* alternative, already initialized */ 374 avail_coremask = 375 cvmx_read64_uint32(CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 376 block_desc->base_addr + 377 AVAIL_COREMASK_OFFSET_IN_LINUX_APP_BOOT_BLOCK)); 378 } 379 380 if (!(avail_coremask & (1 << coreid))) { 381 /* core not available, assume, that catched by simple-executive */ 382 cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); 383 cvmx_write_csr(CVMX_CIU_PP_RST, 0); 384 } 385 386 boot_vect[coreid].app_start_func_addr = 387 (uint32_t) (unsigned long) start_after_reset; 388 boot_vect[coreid].code_addr = InitTLBStart_addr; 389 390 CVMX_SYNC; 391 392 cvmx_write_csr(CVMX_CIU_NMI, (1 << coreid) & avail_coremask); 393 394 return 0; 395 } 396 397 static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb, 398 unsigned long action, void *hcpu) 399 { 400 unsigned int cpu = (unsigned long)hcpu; 401 402 switch (action) { 403 case CPU_UP_PREPARE: 404 octeon_update_boot_vector(cpu); 405 break; 406 case CPU_ONLINE: 407 pr_info("Cpu %d online\n", cpu); 408 break; 409 case CPU_DEAD: 410 break; 411 } 412 413 return NOTIFY_OK; 414 } 415 416 static struct notifier_block __cpuinitdata octeon_cpu_notifier = { 417 .notifier_call = octeon_cpu_callback, 418 }; 419 420 static int __cpuinit register_cavium_notifier(void) 421 { 422 register_hotcpu_notifier(&octeon_cpu_notifier); 423 424 return 0; 425 } 426 427 late_initcall(register_cavium_notifier); 428 429 #endif /* CONFIG_HOTPLUG_CPU */ 430 431 struct plat_smp_ops octeon_smp_ops = { 432 .send_ipi_single = octeon_send_ipi_single, 433 .send_ipi_mask = octeon_send_ipi_mask, 434 .init_secondary = octeon_init_secondary, 435 .smp_finish = octeon_smp_finish, 436 .cpus_done = octeon_cpus_done, 437 .boot_secondary = octeon_boot_secondary, 438 .smp_setup = octeon_smp_setup, 439 .prepare_cpus = octeon_prepare_cpus, 440 #ifdef CONFIG_HOTPLUG_CPU 441 .cpu_disable = octeon_cpu_disable, 442 .cpu_die = octeon_cpu_die, 443 #endif 444 }; 445