pmac_smp.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:16k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: %F% %I% %G% %U% %#%
  3.  */
  4. /*
  5.  * SMP support for power macintosh.
  6.  *
  7.  * We support both the old "powersurge" SMP architecture
  8.  * and the current Core99 (G4 PowerMac) machines.
  9.  *
  10.  * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net)
  11.  * and Ben Herrenschmidt <benh@kernel.crashing.org>.
  12.  *
  13.  * Support for DayStar quad CPU cards
  14.  * Copyright (C) XLR8, Inc. 1994-2000
  15.  *
  16.  *  This program is free software; you can redistribute it and/or
  17.  *  modify it under the terms of the GNU General Public License
  18.  *  as published by the Free Software Foundation; either version
  19.  *  2 of the License, or (at your option) any later version.
  20.  */
  21. #include <linux/config.h>
  22. #include <linux/kernel.h>
  23. #include <linux/sched.h>
  24. #include <linux/smp.h>
  25. #include <linux/smp_lock.h>
  26. #include <linux/interrupt.h>
  27. #include <linux/kernel_stat.h>
  28. #include <linux/delay.h>
  29. #define __KERNEL_SYSCALLS__
  30. #include <linux/unistd.h>
  31. #include <linux/init.h>
  32. #include <linux/spinlock.h>
  33. #include <linux/stringify.h>
  34. #include <asm/ptrace.h>
  35. #include <asm/atomic.h>
  36. #include <asm/irq.h>
  37. #include <asm/page.h>
  38. #include <asm/pgtable.h>
  39. #include <asm/hardirq.h>
  40. #include <asm/softirq.h>
  41. #include <asm/sections.h>
  42. #include <asm/io.h>
  43. #include <asm/prom.h>
  44. #include <asm/smp.h>
  45. #include <asm/residual.h>
  46. #include <asm/machdep.h>
  47. #include <asm/pmac_feature.h>
  48. #include <asm/time.h>
  49. #include <asm/open_pic.h>
  50. #include <asm/processor.h>
  51. /*
  52.  * Powersurge (old powermac SMP) support.
  53.  */
  54. extern void __secondary_start_psurge(void);
  55. extern void __secondary_start_psurge2(void); /* Temporary horrible hack */
  56. extern void __secondary_start_psurge3(void); /* Temporary horrible hack */
  57. /* Addresses for powersurge registers */
  58. #define HAMMERHEAD_BASE 0xf8000000
  59. #define HHEAD_CONFIG 0x90
  60. #define HHEAD_SEC_INTR 0xc0
  61. /* register for interrupting the primary processor on the powersurge */
  62. /* N.B. this is actually the ethernet ROM! */
  63. #define PSURGE_PRI_INTR 0xf3019000
  64. /* register for storing the start address for the secondary processor */
  65. /* N.B. this is the PCI config space address register for the 1st bridge */
  66. #define PSURGE_START 0xf2800000
  67. /* Daystar/XLR8 4-CPU card */
  68. #define PSURGE_QUAD_REG_ADDR 0xf8800000
  69. #define PSURGE_QUAD_IRQ_SET 0
  70. #define PSURGE_QUAD_IRQ_CLR 1
  71. #define PSURGE_QUAD_IRQ_PRIMARY 2
  72. #define PSURGE_QUAD_CKSTOP_CTL 3
  73. #define PSURGE_QUAD_PRIMARY_ARB 4
  74. #define PSURGE_QUAD_BOARD_ID 6
  75. #define PSURGE_QUAD_WHICH_CPU 7
  76. #define PSURGE_QUAD_CKSTOP_RDBK 8
  77. #define PSURGE_QUAD_RESET_CTL 11
  78. #define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v)))
  79. #define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f)
  80. #define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
  81. #define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
  82. /* virtual addresses for the above */
  83. static volatile u8 *hhead_base;
  84. static volatile u8 *quad_base;
  85. static volatile u32 *psurge_pri_intr;
  86. static volatile u8 *psurge_sec_intr;
  87. static volatile u32 *psurge_start;
  88. /* what sort of powersurge board we have */
  89. static int psurge_type;
  90. /* values for psurge_type */
  91. #define PSURGE_DUAL 0
  92. #define PSURGE_QUAD_OKEE 1
  93. #define PSURGE_QUAD_COTTON 2
  94. #define PSURGE_QUAD_ICEGRASS 3
  95. volatile static long int core99_l2_cache;
  96. volatile static long int core99_l3_cache;
  97. static void __init
  98. core99_init_caches(void)
  99. {
  100. int cpu = smp_processor_id();
  101. if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
  102. return;
  103. if (cpu == 0){
  104. core99_l2_cache = _get_L2CR();
  105. printk("CPU0: L2CR is %lxn", core99_l2_cache);
  106. } else {
  107. printk("CPU%d: L2CR was %lxn", cpu, _get_L2CR());
  108. _set_L2CR(0);
  109. _set_L2CR(core99_l2_cache);
  110. printk("CPU%d: L2CR set to %lxn", cpu, core99_l2_cache);
  111. }
  112. if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
  113. return;
  114. if (cpu == 0){
  115. core99_l3_cache = _get_L3CR();
  116. printk("CPU0: L3CR is %lxn", core99_l3_cache);
  117. } else {
  118. printk("CPU%d: L3CR was %lxn", cpu, _get_L3CR());
  119. _set_L3CR(0);
  120. _set_L3CR(core99_l3_cache);
  121. printk("CPU%d: L3CR set to %lxn", cpu, core99_l3_cache);
  122. }
  123. }
  124. /* Some CPU registers have to be saved from the first CPU and
  125.  * applied to others. Note that we override what is setup by
  126.  * the cputable intentionally.
  127.  */
  128. #define reg_hid0 0
  129. #define reg_hid1 1
  130. #define reg_msscr0 2
  131. #define reg_msssr0 3
  132. #define reg_ictrl 4
  133. #define reg_ldstcr 5
  134. #define reg_ldstdb 6
  135. #define reg_count 7
  136. #define stringify __stringify
  137. static unsigned long cpu_regs[reg_count];
  138. static void __pmac
  139. cpu_setup_grab(void)
  140. {
  141. unsigned int pvers = mfspr(SPRN_PVR)>>16;
  142. /* Read cache setting of CPU 0 */
  143. core99_init_caches();
  144. /* 7400/7410/7450 */
  145. if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
  146. cpu_regs[reg_hid0] = mfspr(SPRN_HID0);
  147. cpu_regs[reg_msscr0] = mfspr(SPRN_MSSCR0);
  148. cpu_regs[reg_msssr0] = mfspr(SPRN_MSSSR0);
  149. }
  150. /* 7450 only */
  151. if (pvers == 0x8000) {
  152. cpu_regs[reg_hid1] = mfspr(SPRN_HID1);
  153. cpu_regs[reg_ictrl] = mfspr(SPRN_ICTRL);
  154. cpu_regs[reg_ldstcr] = mfspr(SPRN_LDSTCR);
  155. cpu_regs[reg_ldstdb] = mfspr(SPRN_LDSTDB);
  156. }
  157. flush_dcache_range((unsigned long)cpu_regs, (unsigned long)&cpu_regs[reg_count]);
  158. }
  159. static void __pmac
  160. cpu_setup_apply(int cpu_nr)
  161. {
  162. unsigned int pvers = mfspr(SPRN_PVR)>>16;
  163. /* Apply cache setting from CPU 0 */
  164. core99_init_caches();
  165. /* 7400/7410/7450 */
  166. if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
  167. unsigned long tmp;
  168. __asm__ __volatile__ (
  169. "lwz %0,4*"stringify(reg_hid0)"(%1)n"
  170. "syncn"
  171. "mtspr "stringify(SPRN_HID0)", %0n"
  172. "isync;syncn"
  173. "lwz %0, 4*"stringify(reg_msscr0)"(%1)n"
  174. "syncn"
  175. "mtspr "stringify(SPRN_MSSCR0)", %0n"
  176. "isync;syncn"
  177. // "lwz %0, "stringify(reg_msssr0)"(%1)n"
  178. // "syncn"
  179. // "mtspr "stringify(SPRN_MSSSR0)", %0n"
  180. // "isync;syncn"
  181. : "=&r" (tmp) : "r" (cpu_regs));
  182. }
  183. /* 7410 only */
  184. if (pvers == 0x800c) {
  185. unsigned long tmp;
  186. __asm__ __volatile__ (
  187. "li %0, 0n"
  188. "syncn"
  189. "mtspr "stringify(SPRN_L2CR2)", %0n"
  190. "isync;syncn"
  191. : "=&r" (tmp));
  192. }
  193. /* 7450 only */
  194. if (pvers == 0x8000) {
  195. unsigned long tmp;
  196. __asm__ __volatile__ (
  197. "lwz %0, 4*"stringify(reg_hid1)"(%1)n"
  198. "syncn"
  199. "mtspr "stringify(SPRN_HID1)", %0n"
  200. "isync;syncn"
  201. "lwz %0, 4*"stringify(reg_ictrl)"(%1)n"
  202. "syncn"
  203. "mtspr "stringify(SPRN_ICTRL)", %0n"
  204. "isync;syncn"
  205. "lwz %0, 4*"stringify(reg_ldstcr)"(%1)n"
  206. "syncn"
  207. "mtspr "stringify(SPRN_LDSTCR)", %0n"
  208. "isync;syncn"
  209. "lwz %0, 4*"stringify(reg_ldstdb)"(%1)n"
  210. "syncn"
  211. "mtspr "stringify(SPRN_LDSTDB)", %0n"
  212. "isync;syncn"
  213. : "=&r" (tmp) : "r" (cpu_regs));
  214. }
  215. }
  216. /*
  217.  * Set and clear IPIs for powersurge.
  218.  */
  219. static inline void psurge_set_ipi(int cpu)
  220. {
  221. if (cpu == 0)
  222. in_be32(psurge_pri_intr);
  223. else if (psurge_type == PSURGE_DUAL)
  224. out_8(psurge_sec_intr, 0);
  225. else
  226. PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
  227. }
  228. static inline void psurge_clr_ipi(int cpu)
  229. {
  230. if (cpu > 0) {
  231. if (psurge_type == PSURGE_DUAL)
  232. out_8(psurge_sec_intr, ~0);
  233. else
  234. PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
  235. }
  236. }
  237. /*
  238.  * On powersurge (old SMP powermac architecture) we don't have
  239.  * separate IPIs for separate messages like openpic does.  Instead
  240.  * we have a bitmap for each processor, where a 1 bit means that
  241.  * the corresponding message is pending for that processor.
  242.  * Ideally each cpu's entry would be in a different cache line.
  243.  *  -- paulus.
  244.  */
  245. static unsigned long psurge_smp_message[NR_CPUS];
  246. void __pmac
  247. psurge_smp_message_recv(struct pt_regs *regs)
  248. {
  249. int cpu = smp_processor_id();
  250. int msg;
  251. /* clear interrupt */
  252. psurge_clr_ipi(cpu);
  253. if (smp_num_cpus < 2)
  254. return;
  255. /* make sure there is a message there */
  256. for (msg = 0; msg < 4; msg++)
  257. if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
  258. smp_message_recv(msg, regs);
  259. }
  260. void __pmac
  261. psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
  262. {
  263. psurge_smp_message_recv(regs);
  264. }
  265. static void __pmac
  266. smp_psurge_message_pass(int target, int msg, unsigned long data, int wait)
  267. {
  268. int i;
  269. if (smp_num_cpus < 2)
  270. return;
  271. for (i = 0; i < smp_num_cpus; i++) {
  272. if (target == MSG_ALL
  273.     || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())
  274.     || target == i) {
  275. set_bit(msg, &psurge_smp_message[i]);
  276. psurge_set_ipi(i);
  277. }
  278. }
  279. }
  280. /*
  281.  * Determine a quad card presence. We read the board ID register, we
  282.  * force the data bus to change to something else, and we read it again.
  283.  * It it's stable, then the register probably exist (ugh !)
  284.  */
  285. static int __init psurge_quad_probe(void)
  286. {
  287. int type;
  288. unsigned int i;
  289. type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
  290. if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
  291.     || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
  292. return PSURGE_DUAL;
  293. /* looks OK, try a slightly more rigorous test */
  294. /* bogus is not necessarily cacheline-aligned,
  295.    though I don't suppose that really matters.  -- paulus */
  296. for (i = 0; i < 100; i++) {
  297. volatile u32 bogus[8];
  298. bogus[(0+i)%8] = 0x00000000;
  299. bogus[(1+i)%8] = 0x55555555;
  300. bogus[(2+i)%8] = 0xFFFFFFFF;
  301. bogus[(3+i)%8] = 0xAAAAAAAA;
  302. bogus[(4+i)%8] = 0x33333333;
  303. bogus[(5+i)%8] = 0xCCCCCCCC;
  304. bogus[(6+i)%8] = 0xCCCCCCCC;
  305. bogus[(7+i)%8] = 0x33333333;
  306. wmb();
  307. asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
  308. mb();
  309. if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
  310. return PSURGE_DUAL;
  311. }
  312. return type;
  313. }
  314. static void __init psurge_quad_init(void)
  315. {
  316. int procbits;
  317. if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
  318. procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
  319. if (psurge_type == PSURGE_QUAD_ICEGRASS)
  320. PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
  321. else
  322. PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
  323. mdelay(33);
  324. out_8(psurge_sec_intr, ~0);
  325. PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
  326. PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
  327. if (psurge_type != PSURGE_QUAD_ICEGRASS)
  328. PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
  329. PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
  330. mdelay(33);
  331. PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
  332. mdelay(33);
  333. PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
  334. mdelay(33);
  335. }
  336. static int __init smp_psurge_probe(void)
  337. {
  338. int i, ncpus;
  339. /* We don't do SMP on the PPC601 -- paulus */
  340. if (PVR_VER(mfspr(PVR)) == 1)
  341. return 1;
  342. /*
  343.  * The powersurge cpu board can be used in the generation
  344.  * of powermacs that have a socket for an upgradeable cpu card,
  345.  * including the 7500, 8500, 9500, 9600.
  346.  * The device tree doesn't tell you if you have 2 cpus because
  347.  * OF doesn't know anything about the 2nd processor.
  348.  * Instead we look for magic bits in magic registers,
  349.  * in the hammerhead memory controller in the case of the
  350.  * dual-cpu powersurge board.  -- paulus.
  351.  */
  352. if (find_devices("hammerhead") == NULL)
  353. return 1;
  354. hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
  355. quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
  356. psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
  357. psurge_type = psurge_quad_probe();
  358. if (psurge_type != PSURGE_DUAL) {
  359. psurge_quad_init();
  360. /* All released cards using this HW design have 4 CPUs */
  361. ncpus = 4;
  362. } else {
  363. iounmap((void *) quad_base);
  364. if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
  365. /* not a dual-cpu card */
  366. iounmap((void *) hhead_base);
  367. return 1;
  368. }
  369. ncpus = 2;
  370. }
  371. psurge_start = ioremap(PSURGE_START, 4);
  372. psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
  373. /* this is not actually strictly necessary -- paulus. */
  374. for (i = 1; i < ncpus; ++i)
  375. smp_hw_index[i] = i;
  376. if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
  377. return ncpus;
  378. }
  379. static void __init smp_psurge_kick_cpu(int nr)
  380. {
  381. void (*start)(void) = __secondary_start_psurge;
  382. unsigned long a;
  383. /* may need to flush here if secondary bats aren't setup */
  384. for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
  385. asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
  386. asm volatile("sync");
  387. if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
  388. /* setup entry point of secondary processor */
  389. switch (nr) {
  390. case 2:
  391. start = __secondary_start_psurge2;
  392. break;
  393. case 3:
  394. start = __secondary_start_psurge3;
  395. break;
  396. }
  397. out_be32(psurge_start, __pa(start));
  398. mb();
  399. psurge_set_ipi(nr);
  400. udelay(10);
  401. psurge_clr_ipi(nr);
  402. if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
  403. }
  404. /*
  405.  * With the dual-cpu powersurge board, the decrementers and timebases
  406.  * of both cpus are frozen after the secondary cpu is started up,
  407.  * until we give the secondary cpu another interrupt.  This routine
  408.  * uses this to get the timebases synchronized.
  409.  *  -- paulus.
  410.  */
  411. static void __init psurge_dual_sync_tb(int cpu_nr)
  412. {
  413. static volatile int sec_tb_reset = 0;
  414. int t;
  415. set_dec(tb_ticks_per_jiffy);
  416. set_tb(0, 0);
  417. last_jiffy_stamp(cpu_nr) = 0;
  418. if (cpu_nr > 0) {
  419. mb();
  420. sec_tb_reset = 1;
  421. return;
  422. }
  423. /* wait for the secondary to have reset its TB before proceeding */
  424. for (t = 10000000; t > 0 && !sec_tb_reset; --t)
  425. ;
  426. /* now interrupt the secondary, starting both TBs */
  427. psurge_set_ipi(1);
  428. smp_tb_synchronized = 1;
  429. }
  430. static void __init
  431. smp_psurge_setup_cpu(int cpu_nr)
  432. {
  433. if (cpu_nr == 0) {
  434. if (smp_num_cpus < 2)
  435. return;
  436. /* reset the entry point so if we get another intr we won't
  437.  * try to startup again */
  438. out_be32(psurge_start, 0x100);
  439. if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0))
  440. printk(KERN_ERR "Couldn't get primary IPI interrupt");
  441. }
  442. if (psurge_type == PSURGE_DUAL)
  443. psurge_dual_sync_tb(cpu_nr);
  444. }
  445. static int __init
  446. smp_core99_probe(void)
  447. {
  448. struct device_node *cpus;
  449. int i, ncpus = 1;
  450. extern int powersave_nap;
  451. if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
  452. cpus = find_type_devices("cpu");
  453. if (cpus)
  454. while ((cpus = cpus->next) != NULL)
  455. ++ncpus;
  456. printk("smp_core99_probe: found %d cpusn", ncpus);
  457. if (ncpus > 1) {
  458. openpic_request_IPIs();
  459. for (i = 1; i < ncpus; ++i)
  460. smp_hw_index[i] = i;
  461. powersave_nap = 0;
  462. cpu_setup_grab();
  463. }
  464. return ncpus;
  465. }
  466. static void __init
  467. smp_core99_kick_cpu(int nr)
  468. {
  469. unsigned long save_vector, new_vector;
  470. unsigned long flags;
  471. volatile unsigned long *vector
  472.  = ((volatile unsigned long *)(KERNELBASE+0x100));
  473. if (nr < 1 || nr > 3)
  474. return;
  475. if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
  476. local_irq_save(flags);
  477. local_irq_disable();
  478. /* Save reset vector */
  479. save_vector = *vector;
  480. /* Setup fake reset vector that does   
  481.  *   b __secondary_start_psurge - KERNELBASE
  482.  */  
  483. switch(nr) {
  484. case 1:
  485. new_vector = (unsigned long)__secondary_start_psurge;
  486. break;
  487. case 2:
  488. new_vector = (unsigned long)__secondary_start_psurge2;
  489. break;
  490. case 3:
  491. new_vector = (unsigned long)__secondary_start_psurge3;
  492. break;
  493. }
  494. *vector = 0x48000002 + new_vector - KERNELBASE;
  495. /* flush data cache and inval instruction cache */
  496. flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
  497. /* Put some life in our friend */
  498. pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
  499. /* FIXME: We wait a bit for the CPU to take the exception, I should
  500.  * instead wait for the entry code to set something for me. Well,
  501.  * ideally, all that crap will be done in prom.c and the CPU left
  502.  * in a RAM-based wait loop like CHRP.
  503.  */
  504. mdelay(1);
  505. /* Restore our exception vector */
  506. *vector = save_vector;
  507. flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
  508. local_irq_restore(flags);
  509. if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
  510. }
  511. static void __init
  512. smp_core99_setup_cpu(int cpu_nr)
  513. {
  514. /* Setup some registers */
  515. if (cpu_nr != 0)
  516. cpu_setup_apply(cpu_nr);
  517. /* Setup openpic */
  518. do_openpic_setup_cpu();
  519. /* Setup L2/L3 */
  520. if (cpu_nr == 0)
  521. if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
  522. }
  523. /* PowerSurge-style Macs */
  524. struct smp_ops_t psurge_smp_ops __pmacdata = {
  525. smp_psurge_message_pass,
  526. smp_psurge_probe,
  527. smp_psurge_kick_cpu,
  528. smp_psurge_setup_cpu,
  529. };
  530. /* Core99 Macs (dual G4s) */
  531. struct smp_ops_t core99_smp_ops __pmacdata = {
  532. smp_openpic_message_pass,
  533. smp_core99_probe,
  534. smp_core99_kick_cpu,
  535. smp_core99_setup_cpu,
  536. };