smp.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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/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>
  15. #include <asm/mmu_context.h>
  16. #include <asm/system.h>
  17. #include <asm/time.h>
  18. #include <asm/octeon/octeon.h>
  19. volatile unsigned long octeon_processor_boot = 0xff;
  20. volatile unsigned long octeon_processor_sp;
  21. volatile unsigned long octeon_processor_gp;
  22. static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
  23. {
  24. const int coreid = cvmx_get_core_num();
  25. uint64_t action;
  26. /* Load the mailbox register to figure out what we're supposed to do */
  27. action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid));
  28. /* Clear the mailbox to clear the interrupt */
  29. cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action);
  30. if (action & SMP_CALL_FUNCTION)
  31. smp_call_function_interrupt();
  32. /* Check if we've been told to flush the icache */
  33. if (action & SMP_ICACHE_FLUSH)
  34. asm volatile ("synci 0($0)\n");
  35. return IRQ_HANDLED;
  36. }
  37. /**
  38. * Cause the function described by call_data to be executed on the passed
  39. * cpu. When the function has finished, increment the finished field of
  40. * call_data.
  41. */
  42. void octeon_send_ipi_single(int cpu, unsigned int action)
  43. {
  44. int coreid = cpu_logical_map(cpu);
  45. /*
  46. pr_info("SMP: Mailbox send cpu=%d, coreid=%d, action=%u\n", cpu,
  47. coreid, action);
  48. */
  49. cvmx_write_csr(CVMX_CIU_MBOX_SETX(coreid), action);
  50. }
  51. static inline void octeon_send_ipi_mask(cpumask_t mask, unsigned int action)
  52. {
  53. unsigned int i;
  54. for_each_cpu_mask(i, mask)
  55. octeon_send_ipi_single(i, action);
  56. }
  57. /**
  58. * Detect available CPUs, populate phys_cpu_present_map
  59. */
  60. static void octeon_smp_setup(void)
  61. {
  62. const int coreid = cvmx_get_core_num();
  63. int cpus;
  64. int id;
  65. int core_mask = octeon_get_boot_coremask();
  66. cpus_clear(cpu_possible_map);
  67. __cpu_number_map[coreid] = 0;
  68. __cpu_logical_map[0] = coreid;
  69. cpu_set(0, cpu_possible_map);
  70. cpus = 1;
  71. for (id = 0; id < 16; id++) {
  72. if ((id != coreid) && (core_mask & (1 << id))) {
  73. cpu_set(cpus, cpu_possible_map);
  74. __cpu_number_map[id] = cpus;
  75. __cpu_logical_map[cpus] = id;
  76. cpus++;
  77. }
  78. }
  79. }
  80. /**
  81. * Firmware CPU startup hook
  82. *
  83. */
  84. static void octeon_boot_secondary(int cpu, struct task_struct *idle)
  85. {
  86. int count;
  87. pr_info("SMP: Booting CPU%02d (CoreId %2d)...\n", cpu,
  88. cpu_logical_map(cpu));
  89. octeon_processor_sp = __KSTK_TOS(idle);
  90. octeon_processor_gp = (unsigned long)(task_thread_info(idle));
  91. octeon_processor_boot = cpu_logical_map(cpu);
  92. mb();
  93. count = 10000;
  94. while (octeon_processor_sp && count) {
  95. /* Waiting for processor to get the SP and GP */
  96. udelay(1);
  97. count--;
  98. }
  99. if (count == 0)
  100. pr_err("Secondary boot timeout\n");
  101. }
  102. /**
  103. * After we've done initial boot, this function is called to allow the
  104. * board code to clean up state, if needed
  105. */
  106. static void octeon_init_secondary(void)
  107. {
  108. const int coreid = cvmx_get_core_num();
  109. union cvmx_ciu_intx_sum0 interrupt_enable;
  110. octeon_check_cpu_bist();
  111. octeon_init_cvmcount();
  112. /*
  113. pr_info("SMP: CPU%d (CoreId %lu) started\n", cpu, coreid);
  114. */
  115. /* Enable Mailbox interrupts to this core. These are the only
  116. interrupts allowed on line 3 */
  117. cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), 0xffffffff);
  118. interrupt_enable.u64 = 0;
  119. interrupt_enable.s.mbox = 0x3;
  120. cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), interrupt_enable.u64);
  121. cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
  122. cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
  123. cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
  124. /* Enable core interrupt processing for 2,3 and 7 */
  125. set_c0_status(0x8c01);
  126. }
  127. /**
  128. * Callout to firmware before smp_init
  129. *
  130. */
  131. void octeon_prepare_cpus(unsigned int max_cpus)
  132. {
  133. cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff);
  134. if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_SHARED,
  135. "mailbox0", mailbox_interrupt)) {
  136. panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
  137. }
  138. if (request_irq(OCTEON_IRQ_MBOX1, mailbox_interrupt, IRQF_SHARED,
  139. "mailbox1", mailbox_interrupt)) {
  140. panic("Cannot request_irq(OCTEON_IRQ_MBOX1)\n");
  141. }
  142. }
  143. /**
  144. * Last chance for the board code to finish SMP initialization before
  145. * the CPU is "online".
  146. */
  147. static void octeon_smp_finish(void)
  148. {
  149. #ifdef CONFIG_CAVIUM_GDB
  150. unsigned long tmp;
  151. /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0
  152. to be not masked by this core so we know the signal is received by
  153. someone */
  154. asm volatile ("dmfc0 %0, $22\n"
  155. "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp));
  156. #endif
  157. octeon_user_io_init();
  158. /* to generate the first CPU timer interrupt */
  159. write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
  160. }
  161. /**
  162. * Hook for after all CPUs are online
  163. */
  164. static void octeon_cpus_done(void)
  165. {
  166. #ifdef CONFIG_CAVIUM_GDB
  167. unsigned long tmp;
  168. /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0
  169. to be not masked by this core so we know the signal is received by
  170. someone */
  171. asm volatile ("dmfc0 %0, $22\n"
  172. "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp));
  173. #endif
  174. }
  175. struct plat_smp_ops octeon_smp_ops = {
  176. .send_ipi_single = octeon_send_ipi_single,
  177. .send_ipi_mask = octeon_send_ipi_mask,
  178. .init_secondary = octeon_init_secondary,
  179. .smp_finish = octeon_smp_finish,
  180. .cpus_done = octeon_cpus_done,
  181. .boot_secondary = octeon_boot_secondary,
  182. .smp_setup = octeon_smp_setup,
  183. .prepare_cpus = octeon_prepare_cpus,
  184. };