smp.c 21 KB

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