smp.c 20 KB

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