open_pic.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075
  1. /*
  2. * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
  3. *
  4. * Copyright (C) 1997 Geert Uytterhoeven
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file COPYING in the main directory of this archive
  8. * for more details.
  9. */
  10. #include <linux/config.h>
  11. #include <linux/types.h>
  12. #include <linux/kernel.h>
  13. #include <linux/sched.h>
  14. #include <linux/init.h>
  15. #include <linux/irq.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/sysdev.h>
  18. #include <linux/errno.h>
  19. #include <asm/ptrace.h>
  20. #include <asm/signal.h>
  21. #include <asm/io.h>
  22. #include <asm/irq.h>
  23. #include <asm/sections.h>
  24. #include <asm/open_pic.h>
  25. #include <asm/i8259.h>
  26. #include "open_pic_defs.h"
  27. #if defined(CONFIG_PRPMC800) || defined(CONFIG_85xx)
  28. #define OPENPIC_BIG_ENDIAN
  29. #endif
  30. void __iomem *OpenPIC_Addr;
  31. static volatile struct OpenPIC __iomem *OpenPIC = NULL;
  32. /*
  33. * We define OpenPIC_InitSenses table thusly:
  34. * bit 0x1: sense, 0 for edge and 1 for level.
  35. * bit 0x2: polarity, 0 for negative, 1 for positive.
  36. */
  37. u_int OpenPIC_NumInitSenses __initdata = 0;
  38. u_char *OpenPIC_InitSenses __initdata = NULL;
  39. extern int use_of_interrupt_tree;
  40. static u_int NumProcessors;
  41. static u_int NumSources;
  42. static int open_pic_irq_offset;
  43. static volatile OpenPIC_Source __iomem *ISR[NR_IRQS];
  44. static int openpic_cascade_irq = -1;
  45. static int (*openpic_cascade_fn)(struct pt_regs *);
  46. /* Global Operations */
  47. static void openpic_disable_8259_pass_through(void);
  48. static void openpic_set_spurious(u_int vector);
  49. #ifdef CONFIG_SMP
  50. /* Interprocessor Interrupts */
  51. static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
  52. static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *);
  53. #endif
  54. /* Timer Interrupts */
  55. static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
  56. static void openpic_maptimer(u_int timer, cpumask_t cpumask);
  57. /* Interrupt Sources */
  58. static void openpic_enable_irq(u_int irq);
  59. static void openpic_disable_irq(u_int irq);
  60. static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
  61. int is_level);
  62. static void openpic_mapirq(u_int irq, cpumask_t cpumask, cpumask_t keepmask);
  63. /*
  64. * These functions are not used but the code is kept here
  65. * for completeness and future reference.
  66. */
  67. #ifdef notused
  68. static void openpic_enable_8259_pass_through(void);
  69. static u_int openpic_get_spurious(void);
  70. static void openpic_set_sense(u_int irq, int sense);
  71. #endif /* notused */
  72. /*
  73. * Description of the openpic for the higher-level irq code
  74. */
  75. static void openpic_end_irq(unsigned int irq_nr);
  76. static void openpic_ack_irq(unsigned int irq_nr);
  77. static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
  78. struct hw_interrupt_type open_pic = {
  79. .typename = " OpenPIC ",
  80. .enable = openpic_enable_irq,
  81. .disable = openpic_disable_irq,
  82. .ack = openpic_ack_irq,
  83. .end = openpic_end_irq,
  84. .set_affinity = openpic_set_affinity,
  85. };
  86. #ifdef CONFIG_SMP
  87. static void openpic_end_ipi(unsigned int irq_nr);
  88. static void openpic_ack_ipi(unsigned int irq_nr);
  89. static void openpic_enable_ipi(unsigned int irq_nr);
  90. static void openpic_disable_ipi(unsigned int irq_nr);
  91. struct hw_interrupt_type open_pic_ipi = {
  92. .typename = " OpenPIC ",
  93. .enable = openpic_enable_ipi,
  94. .disable = openpic_disable_ipi,
  95. .ack = openpic_ack_ipi,
  96. .end = openpic_end_ipi,
  97. };
  98. #endif /* CONFIG_SMP */
  99. /*
  100. * Accesses to the current processor's openpic registers
  101. */
  102. #ifdef CONFIG_SMP
  103. #define THIS_CPU Processor[cpu]
  104. #define DECL_THIS_CPU int cpu = smp_hw_index[smp_processor_id()]
  105. #define CHECK_THIS_CPU check_arg_cpu(cpu)
  106. #else
  107. #define THIS_CPU Processor[0]
  108. #define DECL_THIS_CPU
  109. #define CHECK_THIS_CPU
  110. #endif /* CONFIG_SMP */
  111. #if 1
  112. #define check_arg_ipi(ipi) \
  113. if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
  114. printk("open_pic.c:%d: invalid ipi %d\n", __LINE__, ipi);
  115. #define check_arg_timer(timer) \
  116. if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
  117. printk("open_pic.c:%d: invalid timer %d\n", __LINE__, timer);
  118. #define check_arg_vec(vec) \
  119. if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
  120. printk("open_pic.c:%d: invalid vector %d\n", __LINE__, vec);
  121. #define check_arg_pri(pri) \
  122. if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
  123. printk("open_pic.c:%d: invalid priority %d\n", __LINE__, pri);
  124. /*
  125. * Print out a backtrace if it's out of range, since if it's larger than NR_IRQ's
  126. * data has probably been corrupted and we're going to panic or deadlock later
  127. * anyway --Troy
  128. */
  129. #define check_arg_irq(irq) \
  130. if (irq < open_pic_irq_offset || irq >= NumSources+open_pic_irq_offset \
  131. || ISR[irq - open_pic_irq_offset] == 0) { \
  132. printk("open_pic.c:%d: invalid irq %d\n", __LINE__, irq); \
  133. dump_stack(); }
  134. #define check_arg_cpu(cpu) \
  135. if (cpu < 0 || cpu >= NumProcessors){ \
  136. printk("open_pic.c:%d: invalid cpu %d\n", __LINE__, cpu); \
  137. dump_stack(); }
  138. #else
  139. #define check_arg_ipi(ipi) do {} while (0)
  140. #define check_arg_timer(timer) do {} while (0)
  141. #define check_arg_vec(vec) do {} while (0)
  142. #define check_arg_pri(pri) do {} while (0)
  143. #define check_arg_irq(irq) do {} while (0)
  144. #define check_arg_cpu(cpu) do {} while (0)
  145. #endif
  146. u_int openpic_read(volatile u_int __iomem *addr)
  147. {
  148. u_int val;
  149. #ifdef OPENPIC_BIG_ENDIAN
  150. val = in_be32(addr);
  151. #else
  152. val = in_le32(addr);
  153. #endif
  154. return val;
  155. }
  156. static inline void openpic_write(volatile u_int __iomem *addr, u_int val)
  157. {
  158. #ifdef OPENPIC_BIG_ENDIAN
  159. out_be32(addr, val);
  160. #else
  161. out_le32(addr, val);
  162. #endif
  163. }
  164. static inline u_int openpic_readfield(volatile u_int __iomem *addr, u_int mask)
  165. {
  166. u_int val = openpic_read(addr);
  167. return val & mask;
  168. }
  169. inline void openpic_writefield(volatile u_int __iomem *addr, u_int mask,
  170. u_int field)
  171. {
  172. u_int val = openpic_read(addr);
  173. openpic_write(addr, (val & ~mask) | (field & mask));
  174. }
  175. static inline void openpic_clearfield(volatile u_int __iomem *addr, u_int mask)
  176. {
  177. openpic_writefield(addr, mask, 0);
  178. }
  179. static inline void openpic_setfield(volatile u_int __iomem *addr, u_int mask)
  180. {
  181. openpic_writefield(addr, mask, mask);
  182. }
  183. static void openpic_safe_writefield(volatile u_int __iomem *addr, u_int mask,
  184. u_int field)
  185. {
  186. openpic_setfield(addr, OPENPIC_MASK);
  187. while (openpic_read(addr) & OPENPIC_ACTIVITY);
  188. openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
  189. }
  190. #ifdef CONFIG_SMP
  191. /* yes this is right ... bug, feature, you decide! -- tgall */
  192. u_int openpic_read_IPI(volatile u_int __iomem * addr)
  193. {
  194. u_int val = 0;
  195. #if defined(OPENPIC_BIG_ENDIAN) || defined(CONFIG_POWER3)
  196. val = in_be32(addr);
  197. #else
  198. val = in_le32(addr);
  199. #endif
  200. return val;
  201. }
  202. /* because of the power3 be / le above, this is needed */
  203. inline void openpic_writefield_IPI(volatile u_int __iomem * addr, u_int mask, u_int field)
  204. {
  205. u_int val = openpic_read_IPI(addr);
  206. openpic_write(addr, (val & ~mask) | (field & mask));
  207. }
  208. static inline void openpic_clearfield_IPI(volatile u_int __iomem *addr, u_int mask)
  209. {
  210. openpic_writefield_IPI(addr, mask, 0);
  211. }
  212. static inline void openpic_setfield_IPI(volatile u_int __iomem *addr, u_int mask)
  213. {
  214. openpic_writefield_IPI(addr, mask, mask);
  215. }
  216. static void openpic_safe_writefield_IPI(volatile u_int __iomem *addr, u_int mask, u_int field)
  217. {
  218. openpic_setfield_IPI(addr, OPENPIC_MASK);
  219. /* wait until it's not in use */
  220. /* BenH: Is this code really enough ? I would rather check the result
  221. * and eventually retry ...
  222. */
  223. while(openpic_read_IPI(addr) & OPENPIC_ACTIVITY);
  224. openpic_writefield_IPI(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
  225. }
  226. #endif /* CONFIG_SMP */
  227. #ifdef CONFIG_EPIC_SERIAL_MODE
  228. /* On platforms that may use EPIC serial mode, the default is enabled. */
  229. int epic_serial_mode = 1;
  230. static void __init openpic_eicr_set_clk(u_int clkval)
  231. {
  232. openpic_writefield(&OpenPIC->Global.Global_Configuration1,
  233. OPENPIC_EICR_S_CLK_MASK, (clkval << 28));
  234. }
  235. static void __init openpic_enable_sie(void)
  236. {
  237. openpic_setfield(&OpenPIC->Global.Global_Configuration1,
  238. OPENPIC_EICR_SIE);
  239. }
  240. #endif
  241. #if defined(CONFIG_EPIC_SERIAL_MODE)
  242. static void openpic_reset(void)
  243. {
  244. openpic_setfield(&OpenPIC->Global.Global_Configuration0,
  245. OPENPIC_CONFIG_RESET);
  246. while (openpic_readfield(&OpenPIC->Global.Global_Configuration0,
  247. OPENPIC_CONFIG_RESET))
  248. mb();
  249. }
  250. #endif
  251. void __init openpic_set_sources(int first_irq, int num_irqs, void __iomem *first_ISR)
  252. {
  253. volatile OpenPIC_Source __iomem *src = first_ISR;
  254. int i, last_irq;
  255. last_irq = first_irq + num_irqs;
  256. if (last_irq > NumSources)
  257. NumSources = last_irq;
  258. if (src == 0)
  259. src = &((struct OpenPIC __iomem *)OpenPIC_Addr)->Source[first_irq];
  260. for (i = first_irq; i < last_irq; ++i, ++src)
  261. ISR[i] = src;
  262. }
  263. /*
  264. * The `offset' parameter defines where the interrupts handled by the
  265. * OpenPIC start in the space of interrupt numbers that the kernel knows
  266. * about. In other words, the OpenPIC's IRQ0 is numbered `offset' in the
  267. * kernel's interrupt numbering scheme.
  268. * We assume there is only one OpenPIC.
  269. */
  270. void __init openpic_init(int offset)
  271. {
  272. u_int t, i;
  273. u_int timerfreq;
  274. const char *version;
  275. if (!OpenPIC_Addr) {
  276. printk("No OpenPIC found !\n");
  277. return;
  278. }
  279. OpenPIC = (volatile struct OpenPIC __iomem *)OpenPIC_Addr;
  280. #ifdef CONFIG_EPIC_SERIAL_MODE
  281. /* Have to start from ground zero.
  282. */
  283. openpic_reset();
  284. #endif
  285. if (ppc_md.progress) ppc_md.progress("openpic: enter", 0x122);
  286. t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
  287. switch (t & OPENPIC_FEATURE_VERSION_MASK) {
  288. case 1:
  289. version = "1.0";
  290. break;
  291. case 2:
  292. version = "1.2";
  293. break;
  294. case 3:
  295. version = "1.3";
  296. break;
  297. default:
  298. version = "?";
  299. break;
  300. }
  301. NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
  302. OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
  303. if (NumSources == 0)
  304. openpic_set_sources(0,
  305. ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
  306. OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1,
  307. NULL);
  308. printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n",
  309. version, NumProcessors, NumSources, OpenPIC);
  310. timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
  311. if (timerfreq)
  312. printk("OpenPIC timer frequency is %d.%06d MHz\n",
  313. timerfreq / 1000000, timerfreq % 1000000);
  314. open_pic_irq_offset = offset;
  315. /* Initialize timer interrupts */
  316. if ( ppc_md.progress ) ppc_md.progress("openpic: timer",0x3ba);
  317. for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
  318. /* Disabled, Priority 0 */
  319. openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+offset);
  320. /* No processor */
  321. openpic_maptimer(i, CPU_MASK_NONE);
  322. }
  323. #ifdef CONFIG_SMP
  324. /* Initialize IPI interrupts */
  325. if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb);
  326. for (i = 0; i < OPENPIC_NUM_IPI; i++) {
  327. /* Disabled, Priority 10..13 */
  328. openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset);
  329. /* IPIs are per-CPU */
  330. irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU;
  331. irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi;
  332. }
  333. #endif
  334. /* Initialize external interrupts */
  335. if (ppc_md.progress) ppc_md.progress("openpic: external",0x3bc);
  336. openpic_set_priority(0xf);
  337. /* Init all external sources, including possibly the cascade. */
  338. for (i = 0; i < NumSources; i++) {
  339. int sense;
  340. if (ISR[i] == 0)
  341. continue;
  342. /* the bootloader may have left it enabled (bad !) */
  343. openpic_disable_irq(i+offset);
  344. sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: \
  345. (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE);
  346. if (sense & IRQ_SENSE_MASK)
  347. irq_desc[i+offset].status = IRQ_LEVEL;
  348. /* Enabled, Priority 8 */
  349. openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK),
  350. (sense & IRQ_SENSE_MASK));
  351. /* Processor 0 */
  352. openpic_mapirq(i, CPU_MASK_CPU0, CPU_MASK_NONE);
  353. }
  354. /* Init descriptors */
  355. for (i = offset; i < NumSources + offset; i++)
  356. irq_desc[i].handler = &open_pic;
  357. /* Initialize the spurious interrupt */
  358. if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
  359. openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
  360. openpic_disable_8259_pass_through();
  361. #ifdef CONFIG_EPIC_SERIAL_MODE
  362. if (epic_serial_mode) {
  363. openpic_eicr_set_clk(7); /* Slowest value until we know better */
  364. openpic_enable_sie();
  365. }
  366. #endif
  367. openpic_set_priority(0);
  368. if (ppc_md.progress) ppc_md.progress("openpic: exit",0x222);
  369. }
  370. #ifdef notused
  371. static void openpic_enable_8259_pass_through(void)
  372. {
  373. openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
  374. OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
  375. }
  376. #endif /* notused */
  377. static void openpic_disable_8259_pass_through(void)
  378. {
  379. openpic_setfield(&OpenPIC->Global.Global_Configuration0,
  380. OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
  381. }
  382. /*
  383. * Find out the current interrupt
  384. */
  385. u_int openpic_irq(void)
  386. {
  387. u_int vec;
  388. DECL_THIS_CPU;
  389. CHECK_THIS_CPU;
  390. vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
  391. OPENPIC_VECTOR_MASK);
  392. return vec;
  393. }
  394. void openpic_eoi(void)
  395. {
  396. DECL_THIS_CPU;
  397. CHECK_THIS_CPU;
  398. openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
  399. /* Handle PCI write posting */
  400. (void)openpic_read(&OpenPIC->THIS_CPU.EOI);
  401. }
  402. u_int openpic_get_priority(void)
  403. {
  404. DECL_THIS_CPU;
  405. CHECK_THIS_CPU;
  406. return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
  407. OPENPIC_CURRENT_TASK_PRIORITY_MASK);
  408. }
  409. void openpic_set_priority(u_int pri)
  410. {
  411. DECL_THIS_CPU;
  412. CHECK_THIS_CPU;
  413. check_arg_pri(pri);
  414. openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
  415. OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
  416. }
  417. /*
  418. * Get/set the spurious vector
  419. */
  420. #ifdef notused
  421. static u_int openpic_get_spurious(void)
  422. {
  423. return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
  424. OPENPIC_VECTOR_MASK);
  425. }
  426. #endif /* notused */
  427. static void openpic_set_spurious(u_int vec)
  428. {
  429. check_arg_vec(vec);
  430. openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
  431. vec);
  432. }
  433. #ifdef CONFIG_SMP
  434. /*
  435. * Convert a cpu mask from logical to physical cpu numbers.
  436. */
  437. static inline cpumask_t physmask(cpumask_t cpumask)
  438. {
  439. int i;
  440. cpumask_t mask = CPU_MASK_NONE;
  441. cpus_and(cpumask, cpu_online_map, cpumask);
  442. for (i = 0; i < NR_CPUS; i++)
  443. if (cpu_isset(i, cpumask))
  444. cpu_set(smp_hw_index[i], mask);
  445. return mask;
  446. }
  447. #else
  448. #define physmask(cpumask) (cpumask)
  449. #endif
  450. void openpic_reset_processor_phys(u_int mask)
  451. {
  452. openpic_write(&OpenPIC->Global.Processor_Initialization, mask);
  453. }
  454. #if defined(CONFIG_SMP) || defined(CONFIG_PM)
  455. static DEFINE_SPINLOCK(openpic_setup_lock);
  456. #endif
  457. #ifdef CONFIG_SMP
  458. /*
  459. * Initialize an interprocessor interrupt (and disable it)
  460. *
  461. * ipi: OpenPIC interprocessor interrupt number
  462. * pri: interrupt source priority
  463. * vec: the vector it will produce
  464. */
  465. static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
  466. {
  467. check_arg_ipi(ipi);
  468. check_arg_pri(pri);
  469. check_arg_vec(vec);
  470. openpic_safe_writefield_IPI(&OpenPIC->Global.IPI_Vector_Priority(ipi),
  471. OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
  472. (pri << OPENPIC_PRIORITY_SHIFT) | vec);
  473. }
  474. /*
  475. * Send an IPI to one or more CPUs
  476. *
  477. * Externally called, however, it takes an IPI number (0...OPENPIC_NUM_IPI)
  478. * and not a system-wide interrupt number
  479. */
  480. void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
  481. {
  482. DECL_THIS_CPU;
  483. CHECK_THIS_CPU;
  484. check_arg_ipi(ipi);
  485. openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
  486. cpus_addr(physmask(cpumask))[0]);
  487. }
  488. void openpic_request_IPIs(void)
  489. {
  490. int i;
  491. /*
  492. * Make sure this matches what is defined in smp.c for
  493. * smp_message_{pass|recv}() or what shows up in
  494. * /proc/interrupts will be wrong!!! --Troy */
  495. if (OpenPIC == NULL)
  496. return;
  497. /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
  498. request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset,
  499. openpic_ipi_action, SA_INTERRUPT,
  500. "IPI0 (call function)", NULL);
  501. request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1,
  502. openpic_ipi_action, SA_INTERRUPT,
  503. "IPI1 (reschedule)", NULL);
  504. request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2,
  505. openpic_ipi_action, SA_INTERRUPT,
  506. "IPI2 (invalidate tlb)", NULL);
  507. request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3,
  508. openpic_ipi_action, SA_INTERRUPT,
  509. "IPI3 (xmon break)", NULL);
  510. for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
  511. openpic_enable_ipi(OPENPIC_VEC_IPI+open_pic_irq_offset+i);
  512. }
  513. /*
  514. * Do per-cpu setup for SMP systems.
  515. *
  516. * Get IPI's working and start taking interrupts.
  517. * -- Cort
  518. */
  519. void __devinit do_openpic_setup_cpu(void)
  520. {
  521. #ifdef CONFIG_IRQ_ALL_CPUS
  522. int i;
  523. cpumask_t msk = CPU_MASK_NONE;
  524. #endif
  525. spin_lock(&openpic_setup_lock);
  526. #ifdef CONFIG_IRQ_ALL_CPUS
  527. cpu_set(smp_hw_index[smp_processor_id()], msk);
  528. /* let the openpic know we want intrs. default affinity
  529. * is 0xffffffff until changed via /proc
  530. * That's how it's done on x86. If we want it differently, then
  531. * we should make sure we also change the default values of irq_affinity
  532. * in irq.c.
  533. */
  534. for (i = 0; i < NumSources; i++)
  535. openpic_mapirq(i, msk, CPU_MASK_ALL);
  536. #endif /* CONFIG_IRQ_ALL_CPUS */
  537. openpic_set_priority(0);
  538. spin_unlock(&openpic_setup_lock);
  539. }
  540. #endif /* CONFIG_SMP */
  541. /*
  542. * Initialize a timer interrupt (and disable it)
  543. *
  544. * timer: OpenPIC timer number
  545. * pri: interrupt source priority
  546. * vec: the vector it will produce
  547. */
  548. static void __init openpic_inittimer(u_int timer, u_int pri, u_int vec)
  549. {
  550. check_arg_timer(timer);
  551. check_arg_pri(pri);
  552. check_arg_vec(vec);
  553. openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
  554. OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
  555. (pri << OPENPIC_PRIORITY_SHIFT) | vec);
  556. }
  557. /*
  558. * Map a timer interrupt to one or more CPUs
  559. */
  560. static void __init openpic_maptimer(u_int timer, cpumask_t cpumask)
  561. {
  562. cpumask_t phys = physmask(cpumask);
  563. check_arg_timer(timer);
  564. openpic_write(&OpenPIC->Global.Timer[timer].Destination,
  565. cpus_addr(phys)[0]);
  566. }
  567. /*
  568. * Initalize the interrupt source which will generate an NMI.
  569. * This raises the interrupt's priority from 8 to 9.
  570. *
  571. * irq: The logical IRQ which generates an NMI.
  572. */
  573. void __init
  574. openpic_init_nmi_irq(u_int irq)
  575. {
  576. check_arg_irq(irq);
  577. openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
  578. OPENPIC_PRIORITY_MASK,
  579. 9 << OPENPIC_PRIORITY_SHIFT);
  580. }
  581. /*
  582. *
  583. * All functions below take an offset'ed irq argument
  584. *
  585. */
  586. /*
  587. * Hookup a cascade to the OpenPIC.
  588. */
  589. static struct irqaction openpic_cascade_irqaction = {
  590. .handler = no_action,
  591. .flags = SA_INTERRUPT,
  592. .mask = CPU_MASK_NONE,
  593. };
  594. void __init
  595. openpic_hookup_cascade(u_int irq, char *name,
  596. int (*cascade_fn)(struct pt_regs *))
  597. {
  598. openpic_cascade_irq = irq;
  599. openpic_cascade_fn = cascade_fn;
  600. if (setup_irq(irq, &openpic_cascade_irqaction))
  601. printk("Unable to get OpenPIC IRQ %d for cascade\n",
  602. irq - open_pic_irq_offset);
  603. }
  604. /*
  605. * Enable/disable an external interrupt source
  606. *
  607. * Externally called, irq is an offseted system-wide interrupt number
  608. */
  609. static void openpic_enable_irq(u_int irq)
  610. {
  611. volatile u_int __iomem *vpp;
  612. check_arg_irq(irq);
  613. vpp = &ISR[irq - open_pic_irq_offset]->Vector_Priority;
  614. openpic_clearfield(vpp, OPENPIC_MASK);
  615. /* make sure mask gets to controller before we return to user */
  616. do {
  617. mb(); /* sync is probably useless here */
  618. } while (openpic_readfield(vpp, OPENPIC_MASK));
  619. }
  620. static void openpic_disable_irq(u_int irq)
  621. {
  622. volatile u_int __iomem *vpp;
  623. u32 vp;
  624. check_arg_irq(irq);
  625. vpp = &ISR[irq - open_pic_irq_offset]->Vector_Priority;
  626. openpic_setfield(vpp, OPENPIC_MASK);
  627. /* make sure mask gets to controller before we return to user */
  628. do {
  629. mb(); /* sync is probably useless here */
  630. vp = openpic_readfield(vpp, OPENPIC_MASK | OPENPIC_ACTIVITY);
  631. } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
  632. }
  633. #ifdef CONFIG_SMP
  634. /*
  635. * Enable/disable an IPI interrupt source
  636. *
  637. * Externally called, irq is an offseted system-wide interrupt number
  638. */
  639. void openpic_enable_ipi(u_int irq)
  640. {
  641. irq -= (OPENPIC_VEC_IPI+open_pic_irq_offset);
  642. check_arg_ipi(irq);
  643. openpic_clearfield_IPI(&OpenPIC->Global.IPI_Vector_Priority(irq), OPENPIC_MASK);
  644. }
  645. void openpic_disable_ipi(u_int irq)
  646. {
  647. irq -= (OPENPIC_VEC_IPI+open_pic_irq_offset);
  648. check_arg_ipi(irq);
  649. openpic_setfield_IPI(&OpenPIC->Global.IPI_Vector_Priority(irq), OPENPIC_MASK);
  650. }
  651. #endif
  652. /*
  653. * Initialize an interrupt source (and disable it!)
  654. *
  655. * irq: OpenPIC interrupt number
  656. * pri: interrupt source priority
  657. * vec: the vector it will produce
  658. * pol: polarity (1 for positive, 0 for negative)
  659. * sense: 1 for level, 0 for edge
  660. */
  661. static void __init
  662. openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
  663. {
  664. openpic_safe_writefield(&ISR[irq]->Vector_Priority,
  665. OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
  666. OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
  667. (pri << OPENPIC_PRIORITY_SHIFT) | vec |
  668. (pol ? OPENPIC_POLARITY_POSITIVE :
  669. OPENPIC_POLARITY_NEGATIVE) |
  670. (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
  671. }
  672. /*
  673. * Map an interrupt source to one or more CPUs
  674. */
  675. static void openpic_mapirq(u_int irq, cpumask_t physmask, cpumask_t keepmask)
  676. {
  677. if (ISR[irq] == 0)
  678. return;
  679. if (!cpus_empty(keepmask)) {
  680. cpumask_t irqdest = { .bits[0] = openpic_read(&ISR[irq]->Destination) };
  681. cpus_and(irqdest, irqdest, keepmask);
  682. cpus_or(physmask, physmask, irqdest);
  683. }
  684. openpic_write(&ISR[irq]->Destination, cpus_addr(physmask)[0]);
  685. }
  686. #ifdef notused
  687. /*
  688. * Set the sense for an interrupt source (and disable it!)
  689. *
  690. * sense: 1 for level, 0 for edge
  691. */
  692. static void openpic_set_sense(u_int irq, int sense)
  693. {
  694. if (ISR[irq] != 0)
  695. openpic_safe_writefield(&ISR[irq]->Vector_Priority,
  696. OPENPIC_SENSE_LEVEL,
  697. (sense ? OPENPIC_SENSE_LEVEL : 0));
  698. }
  699. #endif /* notused */
  700. /* No spinlocks, should not be necessary with the OpenPIC
  701. * (1 register = 1 interrupt and we have the desc lock).
  702. */
  703. static void openpic_ack_irq(unsigned int irq_nr)
  704. {
  705. #ifdef __SLOW_VERSION__
  706. openpic_disable_irq(irq_nr);
  707. openpic_eoi();
  708. #else
  709. if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
  710. openpic_eoi();
  711. #endif
  712. }
  713. static void openpic_end_irq(unsigned int irq_nr)
  714. {
  715. #ifdef __SLOW_VERSION__
  716. if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
  717. && irq_desc[irq_nr].action)
  718. openpic_enable_irq(irq_nr);
  719. #else
  720. if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0)
  721. openpic_eoi();
  722. #endif
  723. }
  724. static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask)
  725. {
  726. openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask), CPU_MASK_NONE);
  727. }
  728. #ifdef CONFIG_SMP
  729. static void openpic_ack_ipi(unsigned int irq_nr)
  730. {
  731. openpic_eoi();
  732. }
  733. static void openpic_end_ipi(unsigned int irq_nr)
  734. {
  735. }
  736. static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
  737. {
  738. smp_message_recv(cpl-OPENPIC_VEC_IPI-open_pic_irq_offset, regs);
  739. return IRQ_HANDLED;
  740. }
  741. #endif /* CONFIG_SMP */
  742. int
  743. openpic_get_irq(struct pt_regs *regs)
  744. {
  745. int irq = openpic_irq();
  746. /*
  747. * Check for the cascade interrupt and call the cascaded
  748. * interrupt controller function (usually i8259_irq) if so.
  749. * This should move to irq.c eventually. -- paulus
  750. */
  751. if (irq == openpic_cascade_irq && openpic_cascade_fn != NULL) {
  752. int cirq = openpic_cascade_fn(regs);
  753. /* Allow for the cascade being shared with other devices */
  754. if (cirq != -1) {
  755. irq = cirq;
  756. openpic_eoi();
  757. }
  758. } else if (irq == OPENPIC_VEC_SPURIOUS)
  759. irq = -1;
  760. return irq;
  761. }
  762. #ifdef CONFIG_SMP
  763. void
  764. smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
  765. {
  766. cpumask_t mask = CPU_MASK_ALL;
  767. /* make sure we're sending something that translates to an IPI */
  768. if (msg > 0x3) {
  769. printk("SMP %d: smp_message_pass: unknown msg %d\n",
  770. smp_processor_id(), msg);
  771. return;
  772. }
  773. switch (target) {
  774. case MSG_ALL:
  775. openpic_cause_IPI(msg, mask);
  776. break;
  777. case MSG_ALL_BUT_SELF:
  778. cpu_clear(smp_processor_id(), mask);
  779. openpic_cause_IPI(msg, mask);
  780. break;
  781. default:
  782. openpic_cause_IPI(msg, cpumask_of_cpu(target));
  783. break;
  784. }
  785. }
  786. #endif /* CONFIG_SMP */
  787. #ifdef CONFIG_PM
  788. /*
  789. * We implement the IRQ controller as a sysdev and put it
  790. * to sleep at powerdown stage (the callback is named suspend,
  791. * but it's old semantics, for the Device Model, it's really
  792. * powerdown). The possible problem is that another sysdev that
  793. * happens to be suspend after this one will have interrupts off,
  794. * that may be an issue... For now, this isn't an issue on pmac
  795. * though...
  796. */
  797. static u32 save_ipi_vp[OPENPIC_NUM_IPI];
  798. static u32 save_irq_src_vp[OPENPIC_MAX_SOURCES];
  799. static u32 save_irq_src_dest[OPENPIC_MAX_SOURCES];
  800. static u32 save_cpu_task_pri[OPENPIC_MAX_PROCESSORS];
  801. static int openpic_suspend_count;
  802. static void openpic_cached_enable_irq(u_int irq)
  803. {
  804. check_arg_irq(irq);
  805. save_irq_src_vp[irq - open_pic_irq_offset] &= ~OPENPIC_MASK;
  806. }
  807. static void openpic_cached_disable_irq(u_int irq)
  808. {
  809. check_arg_irq(irq);
  810. save_irq_src_vp[irq - open_pic_irq_offset] |= OPENPIC_MASK;
  811. }
  812. /* WARNING: Can be called directly by the cpufreq code with NULL parameter,
  813. * we need something better to deal with that... Maybe switch to S1 for
  814. * cpufreq changes
  815. */
  816. int openpic_suspend(struct sys_device *sysdev, u32 state)
  817. {
  818. int i;
  819. unsigned long flags;
  820. spin_lock_irqsave(&openpic_setup_lock, flags);
  821. if (openpic_suspend_count++ > 0) {
  822. spin_unlock_irqrestore(&openpic_setup_lock, flags);
  823. return 0;
  824. }
  825. openpic_set_priority(0xf);
  826. open_pic.enable = openpic_cached_enable_irq;
  827. open_pic.disable = openpic_cached_disable_irq;
  828. for (i=0; i<NumProcessors; i++) {
  829. save_cpu_task_pri[i] = openpic_read(&OpenPIC->Processor[i].Current_Task_Priority);
  830. openpic_writefield(&OpenPIC->Processor[i].Current_Task_Priority,
  831. OPENPIC_CURRENT_TASK_PRIORITY_MASK, 0xf);
  832. }
  833. for (i=0; i<OPENPIC_NUM_IPI; i++)
  834. save_ipi_vp[i] = openpic_read(&OpenPIC->Global.IPI_Vector_Priority(i));
  835. for (i=0; i<NumSources; i++) {
  836. if (ISR[i] == 0)
  837. continue;
  838. save_irq_src_vp[i] = openpic_read(&ISR[i]->Vector_Priority) & ~OPENPIC_ACTIVITY;
  839. save_irq_src_dest[i] = openpic_read(&ISR[i]->Destination);
  840. }
  841. spin_unlock_irqrestore(&openpic_setup_lock, flags);
  842. return 0;
  843. }
  844. /* WARNING: Can be called directly by the cpufreq code with NULL parameter,
  845. * we need something better to deal with that... Maybe switch to S1 for
  846. * cpufreq changes
  847. */
  848. int openpic_resume(struct sys_device *sysdev)
  849. {
  850. int i;
  851. unsigned long flags;
  852. u32 vppmask = OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
  853. OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK |
  854. OPENPIC_MASK;
  855. spin_lock_irqsave(&openpic_setup_lock, flags);
  856. if ((--openpic_suspend_count) > 0) {
  857. spin_unlock_irqrestore(&openpic_setup_lock, flags);
  858. return 0;
  859. }
  860. /* OpenPIC sometimes seem to need some time to be fully back up... */
  861. do {
  862. openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
  863. } while(openpic_readfield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK)
  864. != OPENPIC_VEC_SPURIOUS);
  865. openpic_disable_8259_pass_through();
  866. for (i=0; i<OPENPIC_NUM_IPI; i++)
  867. openpic_write(&OpenPIC->Global.IPI_Vector_Priority(i),
  868. save_ipi_vp[i]);
  869. for (i=0; i<NumSources; i++) {
  870. if (ISR[i] == 0)
  871. continue;
  872. openpic_write(&ISR[i]->Destination, save_irq_src_dest[i]);
  873. openpic_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]);
  874. /* make sure mask gets to controller before we return to user */
  875. do {
  876. openpic_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]);
  877. } while (openpic_readfield(&ISR[i]->Vector_Priority, vppmask)
  878. != (save_irq_src_vp[i] & vppmask));
  879. }
  880. for (i=0; i<NumProcessors; i++)
  881. openpic_write(&OpenPIC->Processor[i].Current_Task_Priority,
  882. save_cpu_task_pri[i]);
  883. open_pic.enable = openpic_enable_irq;
  884. open_pic.disable = openpic_disable_irq;
  885. openpic_set_priority(0);
  886. spin_unlock_irqrestore(&openpic_setup_lock, flags);
  887. return 0;
  888. }
  889. #endif /* CONFIG_PM */
  890. static struct sysdev_class openpic_sysclass = {
  891. set_kset_name("openpic"),
  892. };
  893. static struct sys_device device_openpic = {
  894. .id = 0,
  895. .cls = &openpic_sysclass,
  896. };
  897. static struct sysdev_driver driver_openpic = {
  898. #ifdef CONFIG_PM
  899. .suspend = &openpic_suspend,
  900. .resume = &openpic_resume,
  901. #endif /* CONFIG_PM */
  902. };
  903. static int __init init_openpic_sysfs(void)
  904. {
  905. int rc;
  906. if (!OpenPIC_Addr)
  907. return -ENODEV;
  908. printk(KERN_DEBUG "Registering openpic with sysfs...\n");
  909. rc = sysdev_class_register(&openpic_sysclass);
  910. if (rc) {
  911. printk(KERN_ERR "Failed registering openpic sys class\n");
  912. return -ENODEV;
  913. }
  914. rc = sysdev_register(&device_openpic);
  915. if (rc) {
  916. printk(KERN_ERR "Failed registering openpic sys device\n");
  917. return -ENODEV;
  918. }
  919. rc = sysdev_driver_register(&openpic_sysclass, &driver_openpic);
  920. if (rc) {
  921. printk(KERN_ERR "Failed registering openpic sys driver\n");
  922. return -ENODEV;
  923. }
  924. return 0;
  925. }
  926. subsys_initcall(init_openpic_sysfs);