open_pic2.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. /*
  2. * Copyright (C) 1997 Geert Uytterhoeven
  3. *
  4. * This file is subject to the terms and conditions of the GNU General Public
  5. * License. See the file COPYING in the main directory of this archive
  6. * for more details.
  7. *
  8. * This is a duplicate of open_pic.c that deals with U3s MPIC on
  9. * G5 PowerMacs. It's the same file except it's using big endian
  10. * register accesses
  11. */
  12. #include <linux/config.h>
  13. #include <linux/types.h>
  14. #include <linux/kernel.h>
  15. #include <linux/sched.h>
  16. #include <linux/init.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/sysdev.h>
  19. #include <linux/errno.h>
  20. #include <asm/ptrace.h>
  21. #include <asm/signal.h>
  22. #include <asm/io.h>
  23. #include <asm/irq.h>
  24. #include <asm/sections.h>
  25. #include <asm/open_pic.h>
  26. #include <asm/i8259.h>
  27. #include <asm/machdep.h>
  28. #include "open_pic_defs.h"
  29. void *OpenPIC2_Addr;
  30. static volatile struct OpenPIC *OpenPIC2 = NULL;
  31. /*
  32. * We define OpenPIC_InitSenses table thusly:
  33. * bit 0x1: sense, 0 for edge and 1 for level.
  34. * bit 0x2: polarity, 0 for negative, 1 for positive.
  35. */
  36. extern u_int OpenPIC_NumInitSenses;
  37. extern u_char *OpenPIC_InitSenses;
  38. extern int use_of_interrupt_tree;
  39. static u_int NumProcessors;
  40. static u_int NumSources;
  41. static int open_pic2_irq_offset;
  42. static volatile OpenPIC_Source *ISR[NR_IRQS];
  43. /* Global Operations */
  44. static void openpic2_disable_8259_pass_through(void);
  45. static void openpic2_set_priority(u_int pri);
  46. static void openpic2_set_spurious(u_int vector);
  47. /* Timer Interrupts */
  48. static void openpic2_inittimer(u_int timer, u_int pri, u_int vector);
  49. static void openpic2_maptimer(u_int timer, u_int cpumask);
  50. /* Interrupt Sources */
  51. static void openpic2_enable_irq(u_int irq);
  52. static void openpic2_disable_irq(u_int irq);
  53. static void openpic2_initirq(u_int irq, u_int pri, u_int vector, int polarity,
  54. int is_level);
  55. static void openpic2_mapirq(u_int irq, u_int cpumask, u_int keepmask);
  56. /*
  57. * These functions are not used but the code is kept here
  58. * for completeness and future reference.
  59. */
  60. static void openpic2_reset(void);
  61. #ifdef notused
  62. static void openpic2_enable_8259_pass_through(void);
  63. static u_int openpic2_get_priority(void);
  64. static u_int openpic2_get_spurious(void);
  65. static void openpic2_set_sense(u_int irq, int sense);
  66. #endif /* notused */
  67. /*
  68. * Description of the openpic for the higher-level irq code
  69. */
  70. static void openpic2_end_irq(unsigned int irq_nr);
  71. static void openpic2_ack_irq(unsigned int irq_nr);
  72. struct hw_interrupt_type open_pic2 = {
  73. .typename = " OpenPIC2 ",
  74. .enable = openpic2_enable_irq,
  75. .disable = openpic2_disable_irq,
  76. .ack = openpic2_ack_irq,
  77. .end = openpic2_end_irq,
  78. };
  79. /*
  80. * Accesses to the current processor's openpic registers
  81. * On cascaded controller, this is only CPU 0
  82. */
  83. #define THIS_CPU Processor[0]
  84. #define DECL_THIS_CPU
  85. #define CHECK_THIS_CPU
  86. #if 1
  87. #define check_arg_ipi(ipi) \
  88. if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
  89. printk("open_pic.c:%d: illegal ipi %d\n", __LINE__, ipi);
  90. #define check_arg_timer(timer) \
  91. if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
  92. printk("open_pic.c:%d: illegal timer %d\n", __LINE__, timer);
  93. #define check_arg_vec(vec) \
  94. if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
  95. printk("open_pic.c:%d: illegal vector %d\n", __LINE__, vec);
  96. #define check_arg_pri(pri) \
  97. if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
  98. printk("open_pic.c:%d: illegal priority %d\n", __LINE__, pri);
  99. /*
  100. * Print out a backtrace if it's out of range, since if it's larger than NR_IRQ's
  101. * data has probably been corrupted and we're going to panic or deadlock later
  102. * anyway --Troy
  103. */
  104. extern unsigned long* _get_SP(void);
  105. #define check_arg_irq(irq) \
  106. if (irq < open_pic2_irq_offset || irq >= NumSources+open_pic2_irq_offset \
  107. || ISR[irq - open_pic2_irq_offset] == 0) { \
  108. printk("open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \
  109. /*print_backtrace(_get_SP());*/ }
  110. #define check_arg_cpu(cpu) \
  111. if (cpu < 0 || cpu >= NumProcessors){ \
  112. printk("open_pic2.c:%d: illegal cpu %d\n", __LINE__, cpu); \
  113. /*print_backtrace(_get_SP());*/ }
  114. #else
  115. #define check_arg_ipi(ipi) do {} while (0)
  116. #define check_arg_timer(timer) do {} while (0)
  117. #define check_arg_vec(vec) do {} while (0)
  118. #define check_arg_pri(pri) do {} while (0)
  119. #define check_arg_irq(irq) do {} while (0)
  120. #define check_arg_cpu(cpu) do {} while (0)
  121. #endif
  122. static u_int openpic2_read(volatile u_int *addr)
  123. {
  124. u_int val;
  125. val = in_be32(addr);
  126. return val;
  127. }
  128. static inline void openpic2_write(volatile u_int *addr, u_int val)
  129. {
  130. out_be32(addr, val);
  131. }
  132. static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask)
  133. {
  134. u_int val = openpic2_read(addr);
  135. return val & mask;
  136. }
  137. inline void openpic2_writefield(volatile u_int *addr, u_int mask,
  138. u_int field)
  139. {
  140. u_int val = openpic2_read(addr);
  141. openpic2_write(addr, (val & ~mask) | (field & mask));
  142. }
  143. static inline void openpic2_clearfield(volatile u_int *addr, u_int mask)
  144. {
  145. openpic2_writefield(addr, mask, 0);
  146. }
  147. static inline void openpic2_setfield(volatile u_int *addr, u_int mask)
  148. {
  149. openpic2_writefield(addr, mask, mask);
  150. }
  151. static void openpic2_safe_writefield(volatile u_int *addr, u_int mask,
  152. u_int field)
  153. {
  154. openpic2_setfield(addr, OPENPIC_MASK);
  155. while (openpic2_read(addr) & OPENPIC_ACTIVITY);
  156. openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
  157. }
  158. static void openpic2_reset(void)
  159. {
  160. openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
  161. OPENPIC_CONFIG_RESET);
  162. while (openpic2_readfield(&OpenPIC2->Global.Global_Configuration0,
  163. OPENPIC_CONFIG_RESET))
  164. mb();
  165. }
  166. void __init openpic2_set_sources(int first_irq, int num_irqs, void *first_ISR)
  167. {
  168. volatile OpenPIC_Source *src = first_ISR;
  169. int i, last_irq;
  170. last_irq = first_irq + num_irqs;
  171. if (last_irq > NumSources)
  172. NumSources = last_irq;
  173. if (src == 0)
  174. src = &((struct OpenPIC *)OpenPIC2_Addr)->Source[first_irq];
  175. for (i = first_irq; i < last_irq; ++i, ++src)
  176. ISR[i] = src;
  177. }
  178. /*
  179. * The `offset' parameter defines where the interrupts handled by the
  180. * OpenPIC start in the space of interrupt numbers that the kernel knows
  181. * about. In other words, the OpenPIC's IRQ0 is numbered `offset' in the
  182. * kernel's interrupt numbering scheme.
  183. * We assume there is only one OpenPIC.
  184. */
  185. void __init openpic2_init(int offset)
  186. {
  187. u_int t, i;
  188. u_int timerfreq;
  189. const char *version;
  190. if (!OpenPIC2_Addr) {
  191. printk("No OpenPIC2 found !\n");
  192. return;
  193. }
  194. OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr;
  195. if (ppc_md.progress) ppc_md.progress("openpic: enter", 0x122);
  196. t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0);
  197. switch (t & OPENPIC_FEATURE_VERSION_MASK) {
  198. case 1:
  199. version = "1.0";
  200. break;
  201. case 2:
  202. version = "1.2";
  203. break;
  204. case 3:
  205. version = "1.3";
  206. break;
  207. default:
  208. version = "?";
  209. break;
  210. }
  211. NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
  212. OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
  213. if (NumSources == 0)
  214. openpic2_set_sources(0,
  215. ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
  216. OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1,
  217. NULL);
  218. printk("OpenPIC (2) Version %s (%d CPUs and %d IRQ sources) at %p\n",
  219. version, NumProcessors, NumSources, OpenPIC2);
  220. timerfreq = openpic2_read(&OpenPIC2->Global.Timer_Frequency);
  221. if (timerfreq)
  222. printk("OpenPIC timer frequency is %d.%06d MHz\n",
  223. timerfreq / 1000000, timerfreq % 1000000);
  224. open_pic2_irq_offset = offset;
  225. /* Initialize timer interrupts */
  226. if ( ppc_md.progress ) ppc_md.progress("openpic2: timer",0x3ba);
  227. for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
  228. /* Disabled, Priority 0 */
  229. openpic2_inittimer(i, 0, OPENPIC2_VEC_TIMER+i+offset);
  230. /* No processor */
  231. openpic2_maptimer(i, 0);
  232. }
  233. /* Initialize external interrupts */
  234. if (ppc_md.progress) ppc_md.progress("openpic2: external",0x3bc);
  235. openpic2_set_priority(0xf);
  236. /* Init all external sources, including possibly the cascade. */
  237. for (i = 0; i < NumSources; i++) {
  238. int sense;
  239. if (ISR[i] == 0)
  240. continue;
  241. /* the bootloader may have left it enabled (bad !) */
  242. openpic2_disable_irq(i+offset);
  243. sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: \
  244. (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE);
  245. if (sense & IRQ_SENSE_MASK)
  246. irq_desc[i+offset].status = IRQ_LEVEL;
  247. /* Enabled, Priority 8 */
  248. openpic2_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK),
  249. (sense & IRQ_SENSE_MASK));
  250. /* Processor 0 */
  251. openpic2_mapirq(i, 1<<0, 0);
  252. }
  253. /* Init descriptors */
  254. for (i = offset; i < NumSources + offset; i++)
  255. irq_desc[i].handler = &open_pic2;
  256. /* Initialize the spurious interrupt */
  257. if (ppc_md.progress) ppc_md.progress("openpic2: spurious",0x3bd);
  258. openpic2_set_spurious(OPENPIC2_VEC_SPURIOUS+offset);
  259. openpic2_disable_8259_pass_through();
  260. openpic2_set_priority(0);
  261. if (ppc_md.progress) ppc_md.progress("openpic2: exit",0x222);
  262. }
  263. #ifdef notused
  264. static void openpic2_enable_8259_pass_through(void)
  265. {
  266. openpic2_clearfield(&OpenPIC2->Global.Global_Configuration0,
  267. OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
  268. }
  269. #endif /* notused */
  270. /* This can't be __init, it is used in openpic_sleep_restore_intrs */
  271. static void openpic2_disable_8259_pass_through(void)
  272. {
  273. openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
  274. OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
  275. }
  276. /*
  277. * Find out the current interrupt
  278. */
  279. u_int openpic2_irq(void)
  280. {
  281. u_int vec;
  282. DECL_THIS_CPU;
  283. CHECK_THIS_CPU;
  284. vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge,
  285. OPENPIC_VECTOR_MASK);
  286. return vec;
  287. }
  288. void openpic2_eoi(void)
  289. {
  290. DECL_THIS_CPU;
  291. CHECK_THIS_CPU;
  292. openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0);
  293. /* Handle PCI write posting */
  294. (void)openpic2_read(&OpenPIC2->THIS_CPU.EOI);
  295. }
  296. #ifdef notused
  297. static u_int openpic2_get_priority(void)
  298. {
  299. DECL_THIS_CPU;
  300. CHECK_THIS_CPU;
  301. return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
  302. OPENPIC_CURRENT_TASK_PRIORITY_MASK);
  303. }
  304. #endif /* notused */
  305. static void __init openpic2_set_priority(u_int pri)
  306. {
  307. DECL_THIS_CPU;
  308. CHECK_THIS_CPU;
  309. check_arg_pri(pri);
  310. openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
  311. OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
  312. }
  313. /*
  314. * Get/set the spurious vector
  315. */
  316. #ifdef notused
  317. static u_int openpic2_get_spurious(void)
  318. {
  319. return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector,
  320. OPENPIC_VECTOR_MASK);
  321. }
  322. #endif /* notused */
  323. /* This can't be __init, it is used in openpic_sleep_restore_intrs */
  324. static void openpic2_set_spurious(u_int vec)
  325. {
  326. check_arg_vec(vec);
  327. openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
  328. vec);
  329. }
  330. static DEFINE_SPINLOCK(openpic2_setup_lock);
  331. /*
  332. * Initialize a timer interrupt (and disable it)
  333. *
  334. * timer: OpenPIC timer number
  335. * pri: interrupt source priority
  336. * vec: the vector it will produce
  337. */
  338. static void __init openpic2_inittimer(u_int timer, u_int pri, u_int vec)
  339. {
  340. check_arg_timer(timer);
  341. check_arg_pri(pri);
  342. check_arg_vec(vec);
  343. openpic2_safe_writefield(&OpenPIC2->Global.Timer[timer].Vector_Priority,
  344. OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
  345. (pri << OPENPIC_PRIORITY_SHIFT) | vec);
  346. }
  347. /*
  348. * Map a timer interrupt to one or more CPUs
  349. */
  350. static void __init openpic2_maptimer(u_int timer, u_int cpumask)
  351. {
  352. check_arg_timer(timer);
  353. openpic2_write(&OpenPIC2->Global.Timer[timer].Destination,
  354. cpumask);
  355. }
  356. /*
  357. * Initalize the interrupt source which will generate an NMI.
  358. * This raises the interrupt's priority from 8 to 9.
  359. *
  360. * irq: The logical IRQ which generates an NMI.
  361. */
  362. void __init
  363. openpic2_init_nmi_irq(u_int irq)
  364. {
  365. check_arg_irq(irq);
  366. openpic2_safe_writefield(&ISR[irq - open_pic2_irq_offset]->Vector_Priority,
  367. OPENPIC_PRIORITY_MASK,
  368. 9 << OPENPIC_PRIORITY_SHIFT);
  369. }
  370. /*
  371. *
  372. * All functions below take an offset'ed irq argument
  373. *
  374. */
  375. /*
  376. * Enable/disable an external interrupt source
  377. *
  378. * Externally called, irq is an offseted system-wide interrupt number
  379. */
  380. static void openpic2_enable_irq(u_int irq)
  381. {
  382. volatile u_int *vpp;
  383. check_arg_irq(irq);
  384. vpp = &ISR[irq - open_pic2_irq_offset]->Vector_Priority;
  385. openpic2_clearfield(vpp, OPENPIC_MASK);
  386. /* make sure mask gets to controller before we return to user */
  387. do {
  388. mb(); /* sync is probably useless here */
  389. } while (openpic2_readfield(vpp, OPENPIC_MASK));
  390. }
  391. static void openpic2_disable_irq(u_int irq)
  392. {
  393. volatile u_int *vpp;
  394. u32 vp;
  395. check_arg_irq(irq);
  396. vpp = &ISR[irq - open_pic2_irq_offset]->Vector_Priority;
  397. openpic2_setfield(vpp, OPENPIC_MASK);
  398. /* make sure mask gets to controller before we return to user */
  399. do {
  400. mb(); /* sync is probably useless here */
  401. vp = openpic2_readfield(vpp, OPENPIC_MASK | OPENPIC_ACTIVITY);
  402. } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
  403. }
  404. /*
  405. * Initialize an interrupt source (and disable it!)
  406. *
  407. * irq: OpenPIC interrupt number
  408. * pri: interrupt source priority
  409. * vec: the vector it will produce
  410. * pol: polarity (1 for positive, 0 for negative)
  411. * sense: 1 for level, 0 for edge
  412. */
  413. static void __init
  414. openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
  415. {
  416. openpic2_safe_writefield(&ISR[irq]->Vector_Priority,
  417. OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
  418. OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
  419. (pri << OPENPIC_PRIORITY_SHIFT) | vec |
  420. (pol ? OPENPIC_POLARITY_POSITIVE :
  421. OPENPIC_POLARITY_NEGATIVE) |
  422. (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
  423. }
  424. /*
  425. * Map an interrupt source to one or more CPUs
  426. */
  427. static void openpic2_mapirq(u_int irq, u_int physmask, u_int keepmask)
  428. {
  429. if (ISR[irq] == 0)
  430. return;
  431. if (keepmask != 0)
  432. physmask |= openpic2_read(&ISR[irq]->Destination) & keepmask;
  433. openpic2_write(&ISR[irq]->Destination, physmask);
  434. }
  435. #ifdef notused
  436. /*
  437. * Set the sense for an interrupt source (and disable it!)
  438. *
  439. * sense: 1 for level, 0 for edge
  440. */
  441. static void openpic2_set_sense(u_int irq, int sense)
  442. {
  443. if (ISR[irq] != 0)
  444. openpic2_safe_writefield(&ISR[irq]->Vector_Priority,
  445. OPENPIC_SENSE_LEVEL,
  446. (sense ? OPENPIC_SENSE_LEVEL : 0));
  447. }
  448. #endif /* notused */
  449. /* No spinlocks, should not be necessary with the OpenPIC
  450. * (1 register = 1 interrupt and we have the desc lock).
  451. */
  452. static void openpic2_ack_irq(unsigned int irq_nr)
  453. {
  454. openpic2_disable_irq(irq_nr);
  455. openpic2_eoi();
  456. }
  457. static void openpic2_end_irq(unsigned int irq_nr)
  458. {
  459. if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  460. openpic2_enable_irq(irq_nr);
  461. }
  462. int
  463. openpic2_get_irq(struct pt_regs *regs)
  464. {
  465. int irq = openpic2_irq();
  466. if (irq == (OPENPIC2_VEC_SPURIOUS + open_pic2_irq_offset))
  467. irq = -1;
  468. return irq;
  469. }
  470. #ifdef CONFIG_PM
  471. /*
  472. * We implement the IRQ controller as a sysdev and put it
  473. * to sleep at powerdown stage (the callback is named suspend,
  474. * but it's old semantics, for the Device Model, it's really
  475. * powerdown). The possible problem is that another sysdev that
  476. * happens to be suspend after this one will have interrupts off,
  477. * that may be an issue... For now, this isn't an issue on pmac
  478. * though...
  479. */
  480. static u32 save_ipi_vp[OPENPIC_NUM_IPI];
  481. static u32 save_irq_src_vp[OPENPIC_MAX_SOURCES];
  482. static u32 save_irq_src_dest[OPENPIC_MAX_SOURCES];
  483. static u32 save_cpu_task_pri[OPENPIC_MAX_PROCESSORS];
  484. static int openpic_suspend_count;
  485. static void openpic2_cached_enable_irq(u_int irq)
  486. {
  487. check_arg_irq(irq);
  488. save_irq_src_vp[irq - open_pic2_irq_offset] &= ~OPENPIC_MASK;
  489. }
  490. static void openpic2_cached_disable_irq(u_int irq)
  491. {
  492. check_arg_irq(irq);
  493. save_irq_src_vp[irq - open_pic2_irq_offset] |= OPENPIC_MASK;
  494. }
  495. /* WARNING: Can be called directly by the cpufreq code with NULL parameter,
  496. * we need something better to deal with that... Maybe switch to S1 for
  497. * cpufreq changes
  498. */
  499. int openpic2_suspend(struct sys_device *sysdev, pm_message_t state)
  500. {
  501. int i;
  502. unsigned long flags;
  503. spin_lock_irqsave(&openpic2_setup_lock, flags);
  504. if (openpic_suspend_count++ > 0) {
  505. spin_unlock_irqrestore(&openpic2_setup_lock, flags);
  506. return 0;
  507. }
  508. open_pic2.enable = openpic2_cached_enable_irq;
  509. open_pic2.disable = openpic2_cached_disable_irq;
  510. for (i=0; i<NumProcessors; i++) {
  511. save_cpu_task_pri[i] = openpic2_read(&OpenPIC2->Processor[i].Current_Task_Priority);
  512. openpic2_writefield(&OpenPIC2->Processor[i].Current_Task_Priority,
  513. OPENPIC_CURRENT_TASK_PRIORITY_MASK, 0xf);
  514. }
  515. for (i=0; i<OPENPIC_NUM_IPI; i++)
  516. save_ipi_vp[i] = openpic2_read(&OpenPIC2->Global.IPI_Vector_Priority(i));
  517. for (i=0; i<NumSources; i++) {
  518. if (ISR[i] == 0)
  519. continue;
  520. save_irq_src_vp[i] = openpic2_read(&ISR[i]->Vector_Priority) & ~OPENPIC_ACTIVITY;
  521. save_irq_src_dest[i] = openpic2_read(&ISR[i]->Destination);
  522. }
  523. spin_unlock_irqrestore(&openpic2_setup_lock, flags);
  524. return 0;
  525. }
  526. /* WARNING: Can be called directly by the cpufreq code with NULL parameter,
  527. * we need something better to deal with that... Maybe switch to S1 for
  528. * cpufreq changes
  529. */
  530. int openpic2_resume(struct sys_device *sysdev)
  531. {
  532. int i;
  533. unsigned long flags;
  534. u32 vppmask = OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
  535. OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK |
  536. OPENPIC_MASK;
  537. spin_lock_irqsave(&openpic2_setup_lock, flags);
  538. if ((--openpic_suspend_count) > 0) {
  539. spin_unlock_irqrestore(&openpic2_setup_lock, flags);
  540. return 0;
  541. }
  542. openpic2_reset();
  543. /* OpenPIC sometimes seem to need some time to be fully back up... */
  544. do {
  545. openpic2_set_spurious(OPENPIC2_VEC_SPURIOUS+open_pic2_irq_offset);
  546. } while(openpic2_readfield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK)
  547. != (OPENPIC2_VEC_SPURIOUS + open_pic2_irq_offset));
  548. openpic2_disable_8259_pass_through();
  549. for (i=0; i<OPENPIC_NUM_IPI; i++)
  550. openpic2_write(&OpenPIC2->Global.IPI_Vector_Priority(i),
  551. save_ipi_vp[i]);
  552. for (i=0; i<NumSources; i++) {
  553. if (ISR[i] == 0)
  554. continue;
  555. openpic2_write(&ISR[i]->Destination, save_irq_src_dest[i]);
  556. openpic2_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]);
  557. /* make sure mask gets to controller before we return to user */
  558. do {
  559. openpic2_write(&ISR[i]->Vector_Priority, save_irq_src_vp[i]);
  560. } while (openpic2_readfield(&ISR[i]->Vector_Priority, vppmask)
  561. != (save_irq_src_vp[i] & vppmask));
  562. }
  563. for (i=0; i<NumProcessors; i++)
  564. openpic2_write(&OpenPIC2->Processor[i].Current_Task_Priority,
  565. save_cpu_task_pri[i]);
  566. open_pic2.enable = openpic2_enable_irq;
  567. open_pic2.disable = openpic2_disable_irq;
  568. spin_unlock_irqrestore(&openpic2_setup_lock, flags);
  569. return 0;
  570. }
  571. #endif /* CONFIG_PM */
  572. /* HACK ALERT */
  573. static struct sysdev_class openpic2_sysclass = {
  574. set_kset_name("openpic2"),
  575. };
  576. static struct sys_device device_openpic2 = {
  577. .id = 0,
  578. .cls = &openpic2_sysclass,
  579. };
  580. static struct sysdev_driver driver_openpic2 = {
  581. #ifdef CONFIG_PM
  582. .suspend = &openpic2_suspend,
  583. .resume = &openpic2_resume,
  584. #endif /* CONFIG_PM */
  585. };
  586. static int __init init_openpic2_sysfs(void)
  587. {
  588. int rc;
  589. if (!OpenPIC2_Addr)
  590. return -ENODEV;
  591. printk(KERN_DEBUG "Registering openpic2 with sysfs...\n");
  592. rc = sysdev_class_register(&openpic2_sysclass);
  593. if (rc) {
  594. printk(KERN_ERR "Failed registering openpic sys class\n");
  595. return -ENODEV;
  596. }
  597. rc = sysdev_register(&device_openpic2);
  598. if (rc) {
  599. printk(KERN_ERR "Failed registering openpic sys device\n");
  600. return -ENODEV;
  601. }
  602. rc = sysdev_driver_register(&openpic2_sysclass, &driver_openpic2);
  603. if (rc) {
  604. printk(KERN_ERR "Failed registering openpic sys driver\n");
  605. return -ENODEV;
  606. }
  607. return 0;
  608. }
  609. subsys_initcall(init_openpic2_sysfs);