smp.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. /*
  2. * Copyright (C) 2010, 2011, 2012, Lemote, Inc.
  3. * Author: Chen Huacai, chenhc@lemote.com
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <linux/init.h>
  17. #include <linux/cpu.h>
  18. #include <linux/sched.h>
  19. #include <linux/sched/hotplug.h>
  20. #include <linux/sched/task_stack.h>
  21. #include <linux/smp.h>
  22. #include <linux/cpufreq.h>
  23. #include <asm/processor.h>
  24. #include <asm/time.h>
  25. #include <asm/clock.h>
  26. #include <asm/tlbflush.h>
  27. #include <asm/cacheflush.h>
  28. #include <loongson.h>
  29. #include <workarounds.h>
  30. #include "smp.h"
  31. DEFINE_PER_CPU(int, cpu_state);
  32. static void *ipi_set0_regs[16];
  33. static void *ipi_clear0_regs[16];
  34. static void *ipi_status0_regs[16];
  35. static void *ipi_en0_regs[16];
  36. static void *ipi_mailbox_buf[16];
  37. static uint32_t core0_c0count[NR_CPUS];
  38. /* read a 32bit value from ipi register */
  39. #define loongson3_ipi_read32(addr) readl(addr)
  40. /* read a 64bit value from ipi register */
  41. #define loongson3_ipi_read64(addr) readq(addr)
  42. /* write a 32bit value to ipi register */
  43. #define loongson3_ipi_write32(action, addr) \
  44. do { \
  45. writel(action, addr); \
  46. __wbflush(); \
  47. } while (0)
  48. /* write a 64bit value to ipi register */
  49. #define loongson3_ipi_write64(action, addr) \
  50. do { \
  51. writeq(action, addr); \
  52. __wbflush(); \
  53. } while (0)
  54. static void ipi_set0_regs_init(void)
  55. {
  56. ipi_set0_regs[0] = (void *)
  57. (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0);
  58. ipi_set0_regs[1] = (void *)
  59. (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0);
  60. ipi_set0_regs[2] = (void *)
  61. (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0);
  62. ipi_set0_regs[3] = (void *)
  63. (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0);
  64. ipi_set0_regs[4] = (void *)
  65. (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0);
  66. ipi_set0_regs[5] = (void *)
  67. (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0);
  68. ipi_set0_regs[6] = (void *)
  69. (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0);
  70. ipi_set0_regs[7] = (void *)
  71. (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0);
  72. ipi_set0_regs[8] = (void *)
  73. (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0);
  74. ipi_set0_regs[9] = (void *)
  75. (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0);
  76. ipi_set0_regs[10] = (void *)
  77. (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0);
  78. ipi_set0_regs[11] = (void *)
  79. (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0);
  80. ipi_set0_regs[12] = (void *)
  81. (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0);
  82. ipi_set0_regs[13] = (void *)
  83. (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0);
  84. ipi_set0_regs[14] = (void *)
  85. (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0);
  86. ipi_set0_regs[15] = (void *)
  87. (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0);
  88. }
  89. static void ipi_clear0_regs_init(void)
  90. {
  91. ipi_clear0_regs[0] = (void *)
  92. (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0);
  93. ipi_clear0_regs[1] = (void *)
  94. (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0);
  95. ipi_clear0_regs[2] = (void *)
  96. (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0);
  97. ipi_clear0_regs[3] = (void *)
  98. (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0);
  99. ipi_clear0_regs[4] = (void *)
  100. (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0);
  101. ipi_clear0_regs[5] = (void *)
  102. (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0);
  103. ipi_clear0_regs[6] = (void *)
  104. (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0);
  105. ipi_clear0_regs[7] = (void *)
  106. (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0);
  107. ipi_clear0_regs[8] = (void *)
  108. (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0);
  109. ipi_clear0_regs[9] = (void *)
  110. (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0);
  111. ipi_clear0_regs[10] = (void *)
  112. (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0);
  113. ipi_clear0_regs[11] = (void *)
  114. (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0);
  115. ipi_clear0_regs[12] = (void *)
  116. (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0);
  117. ipi_clear0_regs[13] = (void *)
  118. (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0);
  119. ipi_clear0_regs[14] = (void *)
  120. (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0);
  121. ipi_clear0_regs[15] = (void *)
  122. (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0);
  123. }
  124. static void ipi_status0_regs_init(void)
  125. {
  126. ipi_status0_regs[0] = (void *)
  127. (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0);
  128. ipi_status0_regs[1] = (void *)
  129. (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0);
  130. ipi_status0_regs[2] = (void *)
  131. (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0);
  132. ipi_status0_regs[3] = (void *)
  133. (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0);
  134. ipi_status0_regs[4] = (void *)
  135. (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0);
  136. ipi_status0_regs[5] = (void *)
  137. (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0);
  138. ipi_status0_regs[6] = (void *)
  139. (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0);
  140. ipi_status0_regs[7] = (void *)
  141. (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0);
  142. ipi_status0_regs[8] = (void *)
  143. (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0);
  144. ipi_status0_regs[9] = (void *)
  145. (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0);
  146. ipi_status0_regs[10] = (void *)
  147. (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0);
  148. ipi_status0_regs[11] = (void *)
  149. (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0);
  150. ipi_status0_regs[12] = (void *)
  151. (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0);
  152. ipi_status0_regs[13] = (void *)
  153. (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0);
  154. ipi_status0_regs[14] = (void *)
  155. (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0);
  156. ipi_status0_regs[15] = (void *)
  157. (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0);
  158. }
  159. static void ipi_en0_regs_init(void)
  160. {
  161. ipi_en0_regs[0] = (void *)
  162. (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0);
  163. ipi_en0_regs[1] = (void *)
  164. (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0);
  165. ipi_en0_regs[2] = (void *)
  166. (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0);
  167. ipi_en0_regs[3] = (void *)
  168. (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0);
  169. ipi_en0_regs[4] = (void *)
  170. (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0);
  171. ipi_en0_regs[5] = (void *)
  172. (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0);
  173. ipi_en0_regs[6] = (void *)
  174. (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0);
  175. ipi_en0_regs[7] = (void *)
  176. (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0);
  177. ipi_en0_regs[8] = (void *)
  178. (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0);
  179. ipi_en0_regs[9] = (void *)
  180. (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0);
  181. ipi_en0_regs[10] = (void *)
  182. (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0);
  183. ipi_en0_regs[11] = (void *)
  184. (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0);
  185. ipi_en0_regs[12] = (void *)
  186. (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0);
  187. ipi_en0_regs[13] = (void *)
  188. (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0);
  189. ipi_en0_regs[14] = (void *)
  190. (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0);
  191. ipi_en0_regs[15] = (void *)
  192. (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0);
  193. }
  194. static void ipi_mailbox_buf_init(void)
  195. {
  196. ipi_mailbox_buf[0] = (void *)
  197. (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF);
  198. ipi_mailbox_buf[1] = (void *)
  199. (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF);
  200. ipi_mailbox_buf[2] = (void *)
  201. (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF);
  202. ipi_mailbox_buf[3] = (void *)
  203. (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF);
  204. ipi_mailbox_buf[4] = (void *)
  205. (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF);
  206. ipi_mailbox_buf[5] = (void *)
  207. (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF);
  208. ipi_mailbox_buf[6] = (void *)
  209. (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF);
  210. ipi_mailbox_buf[7] = (void *)
  211. (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF);
  212. ipi_mailbox_buf[8] = (void *)
  213. (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF);
  214. ipi_mailbox_buf[9] = (void *)
  215. (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF);
  216. ipi_mailbox_buf[10] = (void *)
  217. (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF);
  218. ipi_mailbox_buf[11] = (void *)
  219. (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF);
  220. ipi_mailbox_buf[12] = (void *)
  221. (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF);
  222. ipi_mailbox_buf[13] = (void *)
  223. (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF);
  224. ipi_mailbox_buf[14] = (void *)
  225. (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF);
  226. ipi_mailbox_buf[15] = (void *)
  227. (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF);
  228. }
  229. /*
  230. * Simple enough, just poke the appropriate ipi register
  231. */
  232. static void loongson3_send_ipi_single(int cpu, unsigned int action)
  233. {
  234. loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu_logical_map(cpu)]);
  235. }
  236. static void
  237. loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
  238. {
  239. unsigned int i;
  240. for_each_cpu(i, mask)
  241. loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu_logical_map(i)]);
  242. }
  243. #define IPI_IRQ_OFFSET 6
  244. void loongson3_send_irq_by_ipi(int cpu, int irqs)
  245. {
  246. loongson3_ipi_write32(irqs << IPI_IRQ_OFFSET, ipi_set0_regs[cpu_logical_map(cpu)]);
  247. }
  248. void loongson3_ipi_interrupt(struct pt_regs *regs)
  249. {
  250. int i, cpu = smp_processor_id();
  251. unsigned int action, c0count, irqs;
  252. /* Load the ipi register to figure out what we're supposed to do */
  253. action = loongson3_ipi_read32(ipi_status0_regs[cpu_logical_map(cpu)]);
  254. irqs = action >> IPI_IRQ_OFFSET;
  255. /* Clear the ipi register to clear the interrupt */
  256. loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu_logical_map(cpu)]);
  257. if (action & SMP_RESCHEDULE_YOURSELF)
  258. scheduler_ipi();
  259. if (action & SMP_CALL_FUNCTION) {
  260. irq_enter();
  261. generic_smp_call_function_interrupt();
  262. irq_exit();
  263. }
  264. if (action & SMP_ASK_C0COUNT) {
  265. BUG_ON(cpu != 0);
  266. c0count = read_c0_count();
  267. c0count = c0count ? c0count : 1;
  268. for (i = 1; i < nr_cpu_ids; i++)
  269. core0_c0count[i] = c0count;
  270. __wbflush(); /* Let others see the result ASAP */
  271. }
  272. if (irqs) {
  273. int irq;
  274. while ((irq = ffs(irqs))) {
  275. do_IRQ(irq-1);
  276. irqs &= ~(1<<(irq-1));
  277. }
  278. }
  279. }
  280. #define MAX_LOOPS 800
  281. /*
  282. * SMP init and finish on secondary CPUs
  283. */
  284. static void loongson3_init_secondary(void)
  285. {
  286. int i;
  287. uint32_t initcount;
  288. unsigned int cpu = smp_processor_id();
  289. unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
  290. STATUSF_IP3 | STATUSF_IP2;
  291. /* Set interrupt mask, but don't enable */
  292. change_c0_status(ST0_IM, imask);
  293. for (i = 0; i < num_possible_cpus(); i++)
  294. loongson3_ipi_write32(0xffffffff, ipi_en0_regs[cpu_logical_map(i)]);
  295. per_cpu(cpu_state, cpu) = CPU_ONLINE;
  296. cpu_set_core(&cpu_data[cpu],
  297. cpu_logical_map(cpu) % loongson_sysconf.cores_per_package);
  298. cpu_data[cpu].package =
  299. cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
  300. i = 0;
  301. core0_c0count[cpu] = 0;
  302. loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
  303. while (!core0_c0count[cpu]) {
  304. i++;
  305. cpu_relax();
  306. }
  307. if (i > MAX_LOOPS)
  308. i = MAX_LOOPS;
  309. if (cpu_data[cpu].package)
  310. initcount = core0_c0count[cpu] + i;
  311. else /* Local access is faster for loops */
  312. initcount = core0_c0count[cpu] + i/2;
  313. write_c0_count(initcount);
  314. }
  315. static void loongson3_smp_finish(void)
  316. {
  317. int cpu = smp_processor_id();
  318. write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
  319. local_irq_enable();
  320. loongson3_ipi_write64(0,
  321. (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0));
  322. pr_info("CPU#%d finished, CP0_ST=%x\n",
  323. smp_processor_id(), read_c0_status());
  324. }
  325. static void __init loongson3_smp_setup(void)
  326. {
  327. int i = 0, num = 0; /* i: physical id, num: logical id */
  328. init_cpu_possible(cpu_none_mask);
  329. /* For unified kernel, NR_CPUS is the maximum possible value,
  330. * loongson_sysconf.nr_cpus is the really present value */
  331. while (i < loongson_sysconf.nr_cpus) {
  332. if (loongson_sysconf.reserved_cpus_mask & (1<<i)) {
  333. /* Reserved physical CPU cores */
  334. __cpu_number_map[i] = -1;
  335. } else {
  336. __cpu_number_map[i] = num;
  337. __cpu_logical_map[num] = i;
  338. set_cpu_possible(num, true);
  339. num++;
  340. }
  341. i++;
  342. }
  343. pr_info("Detected %i available CPU(s)\n", num);
  344. while (num < loongson_sysconf.nr_cpus) {
  345. __cpu_logical_map[num] = -1;
  346. num++;
  347. }
  348. ipi_set0_regs_init();
  349. ipi_clear0_regs_init();
  350. ipi_status0_regs_init();
  351. ipi_en0_regs_init();
  352. ipi_mailbox_buf_init();
  353. cpu_set_core(&cpu_data[0],
  354. cpu_logical_map(0) % loongson_sysconf.cores_per_package);
  355. cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package;
  356. }
  357. static void __init loongson3_prepare_cpus(unsigned int max_cpus)
  358. {
  359. init_cpu_present(cpu_possible_mask);
  360. per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
  361. }
  362. /*
  363. * Setup the PC, SP, and GP of a secondary processor and start it runing!
  364. */
  365. static int loongson3_boot_secondary(int cpu, struct task_struct *idle)
  366. {
  367. unsigned long startargs[4];
  368. pr_info("Booting CPU#%d...\n", cpu);
  369. /* startargs[] are initial PC, SP and GP for secondary CPU */
  370. startargs[0] = (unsigned long)&smp_bootstrap;
  371. startargs[1] = (unsigned long)__KSTK_TOS(idle);
  372. startargs[2] = (unsigned long)task_thread_info(idle);
  373. startargs[3] = 0;
  374. pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n",
  375. cpu, startargs[0], startargs[1], startargs[2]);
  376. loongson3_ipi_write64(startargs[3],
  377. (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x18));
  378. loongson3_ipi_write64(startargs[2],
  379. (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x10));
  380. loongson3_ipi_write64(startargs[1],
  381. (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x8));
  382. loongson3_ipi_write64(startargs[0],
  383. (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0));
  384. return 0;
  385. }
  386. #ifdef CONFIG_HOTPLUG_CPU
  387. static int loongson3_cpu_disable(void)
  388. {
  389. unsigned long flags;
  390. unsigned int cpu = smp_processor_id();
  391. if (cpu == 0)
  392. return -EBUSY;
  393. set_cpu_online(cpu, false);
  394. calculate_cpu_foreign_map();
  395. local_irq_save(flags);
  396. fixup_irqs();
  397. local_irq_restore(flags);
  398. local_flush_tlb_all();
  399. return 0;
  400. }
  401. static void loongson3_cpu_die(unsigned int cpu)
  402. {
  403. while (per_cpu(cpu_state, cpu) != CPU_DEAD)
  404. cpu_relax();
  405. mb();
  406. }
  407. /* To shutdown a core in Loongson 3, the target core should go to CKSEG1 and
  408. * flush all L1 entries at first. Then, another core (usually Core 0) can
  409. * safely disable the clock of the target core. loongson3_play_dead() is
  410. * called via CKSEG1 (uncached and unmmaped) */
  411. static void loongson3a_r1_play_dead(int *state_addr)
  412. {
  413. register int val;
  414. register long cpuid, core, node, count;
  415. register void *addr, *base, *initfunc;
  416. __asm__ __volatile__(
  417. " .set push \n"
  418. " .set noreorder \n"
  419. " li %[addr], 0x80000000 \n" /* KSEG0 */
  420. "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
  421. " cache 0, 1(%[addr]) \n"
  422. " cache 0, 2(%[addr]) \n"
  423. " cache 0, 3(%[addr]) \n"
  424. " cache 1, 0(%[addr]) \n" /* flush L1 DCache */
  425. " cache 1, 1(%[addr]) \n"
  426. " cache 1, 2(%[addr]) \n"
  427. " cache 1, 3(%[addr]) \n"
  428. " addiu %[sets], %[sets], -1 \n"
  429. " bnez %[sets], 1b \n"
  430. " addiu %[addr], %[addr], 0x20 \n"
  431. " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
  432. " sw %[val], (%[state_addr]) \n"
  433. " sync \n"
  434. " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
  435. " .set pop \n"
  436. : [addr] "=&r" (addr), [val] "=&r" (val)
  437. : [state_addr] "r" (state_addr),
  438. [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
  439. __asm__ __volatile__(
  440. " .set push \n"
  441. " .set noreorder \n"
  442. " .set mips64 \n"
  443. " mfc0 %[cpuid], $15, 1 \n"
  444. " andi %[cpuid], 0x3ff \n"
  445. " dli %[base], 0x900000003ff01000 \n"
  446. " andi %[core], %[cpuid], 0x3 \n"
  447. " sll %[core], 8 \n" /* get core id */
  448. " or %[base], %[base], %[core] \n"
  449. " andi %[node], %[cpuid], 0xc \n"
  450. " dsll %[node], 42 \n" /* get node id */
  451. " or %[base], %[base], %[node] \n"
  452. "1: li %[count], 0x100 \n" /* wait for init loop */
  453. "2: bnez %[count], 2b \n" /* limit mailbox access */
  454. " addiu %[count], -1 \n"
  455. " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
  456. " beqz %[initfunc], 1b \n"
  457. " nop \n"
  458. " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
  459. " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
  460. " ld $a1, 0x38(%[base]) \n"
  461. " jr %[initfunc] \n" /* jump to initial PC */
  462. " nop \n"
  463. " .set pop \n"
  464. : [core] "=&r" (core), [node] "=&r" (node),
  465. [base] "=&r" (base), [cpuid] "=&r" (cpuid),
  466. [count] "=&r" (count), [initfunc] "=&r" (initfunc)
  467. : /* No Input */
  468. : "a1");
  469. }
  470. static void loongson3a_r2r3_play_dead(int *state_addr)
  471. {
  472. register int val;
  473. register long cpuid, core, node, count;
  474. register void *addr, *base, *initfunc;
  475. __asm__ __volatile__(
  476. " .set push \n"
  477. " .set noreorder \n"
  478. " li %[addr], 0x80000000 \n" /* KSEG0 */
  479. "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
  480. " cache 0, 1(%[addr]) \n"
  481. " cache 0, 2(%[addr]) \n"
  482. " cache 0, 3(%[addr]) \n"
  483. " cache 1, 0(%[addr]) \n" /* flush L1 DCache */
  484. " cache 1, 1(%[addr]) \n"
  485. " cache 1, 2(%[addr]) \n"
  486. " cache 1, 3(%[addr]) \n"
  487. " addiu %[sets], %[sets], -1 \n"
  488. " bnez %[sets], 1b \n"
  489. " addiu %[addr], %[addr], 0x40 \n"
  490. " li %[addr], 0x80000000 \n" /* KSEG0 */
  491. "2: cache 2, 0(%[addr]) \n" /* flush L1 VCache */
  492. " cache 2, 1(%[addr]) \n"
  493. " cache 2, 2(%[addr]) \n"
  494. " cache 2, 3(%[addr]) \n"
  495. " cache 2, 4(%[addr]) \n"
  496. " cache 2, 5(%[addr]) \n"
  497. " cache 2, 6(%[addr]) \n"
  498. " cache 2, 7(%[addr]) \n"
  499. " cache 2, 8(%[addr]) \n"
  500. " cache 2, 9(%[addr]) \n"
  501. " cache 2, 10(%[addr]) \n"
  502. " cache 2, 11(%[addr]) \n"
  503. " cache 2, 12(%[addr]) \n"
  504. " cache 2, 13(%[addr]) \n"
  505. " cache 2, 14(%[addr]) \n"
  506. " cache 2, 15(%[addr]) \n"
  507. " addiu %[vsets], %[vsets], -1 \n"
  508. " bnez %[vsets], 2b \n"
  509. " addiu %[addr], %[addr], 0x40 \n"
  510. " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
  511. " sw %[val], (%[state_addr]) \n"
  512. " sync \n"
  513. " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
  514. " .set pop \n"
  515. : [addr] "=&r" (addr), [val] "=&r" (val)
  516. : [state_addr] "r" (state_addr),
  517. [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
  518. [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
  519. __asm__ __volatile__(
  520. " .set push \n"
  521. " .set noreorder \n"
  522. " .set mips64 \n"
  523. " mfc0 %[cpuid], $15, 1 \n"
  524. " andi %[cpuid], 0x3ff \n"
  525. " dli %[base], 0x900000003ff01000 \n"
  526. " andi %[core], %[cpuid], 0x3 \n"
  527. " sll %[core], 8 \n" /* get core id */
  528. " or %[base], %[base], %[core] \n"
  529. " andi %[node], %[cpuid], 0xc \n"
  530. " dsll %[node], 42 \n" /* get node id */
  531. " or %[base], %[base], %[node] \n"
  532. "1: li %[count], 0x100 \n" /* wait for init loop */
  533. "2: bnez %[count], 2b \n" /* limit mailbox access */
  534. " addiu %[count], -1 \n"
  535. " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
  536. " beqz %[initfunc], 1b \n"
  537. " nop \n"
  538. " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
  539. " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
  540. " ld $a1, 0x38(%[base]) \n"
  541. " jr %[initfunc] \n" /* jump to initial PC */
  542. " nop \n"
  543. " .set pop \n"
  544. : [core] "=&r" (core), [node] "=&r" (node),
  545. [base] "=&r" (base), [cpuid] "=&r" (cpuid),
  546. [count] "=&r" (count), [initfunc] "=&r" (initfunc)
  547. : /* No Input */
  548. : "a1");
  549. }
  550. static void loongson3b_play_dead(int *state_addr)
  551. {
  552. register int val;
  553. register long cpuid, core, node, count;
  554. register void *addr, *base, *initfunc;
  555. __asm__ __volatile__(
  556. " .set push \n"
  557. " .set noreorder \n"
  558. " li %[addr], 0x80000000 \n" /* KSEG0 */
  559. "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
  560. " cache 0, 1(%[addr]) \n"
  561. " cache 0, 2(%[addr]) \n"
  562. " cache 0, 3(%[addr]) \n"
  563. " cache 1, 0(%[addr]) \n" /* flush L1 DCache */
  564. " cache 1, 1(%[addr]) \n"
  565. " cache 1, 2(%[addr]) \n"
  566. " cache 1, 3(%[addr]) \n"
  567. " addiu %[sets], %[sets], -1 \n"
  568. " bnez %[sets], 1b \n"
  569. " addiu %[addr], %[addr], 0x20 \n"
  570. " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
  571. " sw %[val], (%[state_addr]) \n"
  572. " sync \n"
  573. " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
  574. " .set pop \n"
  575. : [addr] "=&r" (addr), [val] "=&r" (val)
  576. : [state_addr] "r" (state_addr),
  577. [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
  578. __asm__ __volatile__(
  579. " .set push \n"
  580. " .set noreorder \n"
  581. " .set mips64 \n"
  582. " mfc0 %[cpuid], $15, 1 \n"
  583. " andi %[cpuid], 0x3ff \n"
  584. " dli %[base], 0x900000003ff01000 \n"
  585. " andi %[core], %[cpuid], 0x3 \n"
  586. " sll %[core], 8 \n" /* get core id */
  587. " or %[base], %[base], %[core] \n"
  588. " andi %[node], %[cpuid], 0xc \n"
  589. " dsll %[node], 42 \n" /* get node id */
  590. " or %[base], %[base], %[node] \n"
  591. " dsrl %[node], 30 \n" /* 15:14 */
  592. " or %[base], %[base], %[node] \n"
  593. "1: li %[count], 0x100 \n" /* wait for init loop */
  594. "2: bnez %[count], 2b \n" /* limit mailbox access */
  595. " addiu %[count], -1 \n"
  596. " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
  597. " beqz %[initfunc], 1b \n"
  598. " nop \n"
  599. " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
  600. " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
  601. " ld $a1, 0x38(%[base]) \n"
  602. " jr %[initfunc] \n" /* jump to initial PC */
  603. " nop \n"
  604. " .set pop \n"
  605. : [core] "=&r" (core), [node] "=&r" (node),
  606. [base] "=&r" (base), [cpuid] "=&r" (cpuid),
  607. [count] "=&r" (count), [initfunc] "=&r" (initfunc)
  608. : /* No Input */
  609. : "a1");
  610. }
  611. void play_dead(void)
  612. {
  613. int *state_addr;
  614. unsigned int cpu = smp_processor_id();
  615. void (*play_dead_at_ckseg1)(int *);
  616. idle_task_exit();
  617. switch (read_c0_prid() & PRID_REV_MASK) {
  618. case PRID_REV_LOONGSON3A_R1:
  619. default:
  620. play_dead_at_ckseg1 =
  621. (void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
  622. break;
  623. case PRID_REV_LOONGSON3A_R2:
  624. case PRID_REV_LOONGSON3A_R3_0:
  625. case PRID_REV_LOONGSON3A_R3_1:
  626. play_dead_at_ckseg1 =
  627. (void *)CKSEG1ADDR((unsigned long)loongson3a_r2r3_play_dead);
  628. break;
  629. case PRID_REV_LOONGSON3B_R1:
  630. case PRID_REV_LOONGSON3B_R2:
  631. play_dead_at_ckseg1 =
  632. (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
  633. break;
  634. }
  635. state_addr = &per_cpu(cpu_state, cpu);
  636. mb();
  637. play_dead_at_ckseg1(state_addr);
  638. }
  639. static int loongson3_disable_clock(unsigned int cpu)
  640. {
  641. uint64_t core_id = cpu_core(&cpu_data[cpu]);
  642. uint64_t package_id = cpu_data[cpu].package;
  643. if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
  644. LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
  645. } else {
  646. if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
  647. LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
  648. }
  649. return 0;
  650. }
  651. static int loongson3_enable_clock(unsigned int cpu)
  652. {
  653. uint64_t core_id = cpu_core(&cpu_data[cpu]);
  654. uint64_t package_id = cpu_data[cpu].package;
  655. if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
  656. LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
  657. } else {
  658. if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
  659. LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
  660. }
  661. return 0;
  662. }
  663. static int register_loongson3_notifier(void)
  664. {
  665. return cpuhp_setup_state_nocalls(CPUHP_MIPS_SOC_PREPARE,
  666. "mips/loongson:prepare",
  667. loongson3_enable_clock,
  668. loongson3_disable_clock);
  669. }
  670. early_initcall(register_loongson3_notifier);
  671. #endif
  672. const struct plat_smp_ops loongson3_smp_ops = {
  673. .send_ipi_single = loongson3_send_ipi_single,
  674. .send_ipi_mask = loongson3_send_ipi_mask,
  675. .init_secondary = loongson3_init_secondary,
  676. .smp_finish = loongson3_smp_finish,
  677. .boot_secondary = loongson3_boot_secondary,
  678. .smp_setup = loongson3_smp_setup,
  679. .prepare_cpus = loongson3_prepare_cpus,
  680. #ifdef CONFIG_HOTPLUG_CPU
  681. .cpu_disable = loongson3_cpu_disable,
  682. .cpu_die = loongson3_cpu_die,
  683. #endif
  684. };