ipic.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. /*
  2. * include/asm-ppc/ipic.c
  3. *
  4. * IPIC routines implementations.
  5. *
  6. * Copyright 2005 Freescale Semiconductor, Inc.
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/init.h>
  15. #include <linux/errno.h>
  16. #include <linux/reboot.h>
  17. #include <linux/slab.h>
  18. #include <linux/stddef.h>
  19. #include <linux/sched.h>
  20. #include <linux/signal.h>
  21. #include <linux/sysdev.h>
  22. #include <asm/irq.h>
  23. #include <asm/io.h>
  24. #include <asm/ipic.h>
  25. #include <asm/mpc83xx.h>
  26. #include "ipic.h"
  27. static struct ipic p_ipic;
  28. static struct ipic * primary_ipic;
  29. static struct ipic_info ipic_info[] = {
  30. [9] = {
  31. .pend = IPIC_SIPNR_H,
  32. .mask = IPIC_SIMSR_H,
  33. .prio = IPIC_SIPRR_D,
  34. .force = IPIC_SIFCR_H,
  35. .bit = 24,
  36. .prio_mask = 0,
  37. },
  38. [10] = {
  39. .pend = IPIC_SIPNR_H,
  40. .mask = IPIC_SIMSR_H,
  41. .prio = IPIC_SIPRR_D,
  42. .force = IPIC_SIFCR_H,
  43. .bit = 25,
  44. .prio_mask = 1,
  45. },
  46. [11] = {
  47. .pend = IPIC_SIPNR_H,
  48. .mask = IPIC_SIMSR_H,
  49. .prio = IPIC_SIPRR_D,
  50. .force = IPIC_SIFCR_H,
  51. .bit = 26,
  52. .prio_mask = 2,
  53. },
  54. [14] = {
  55. .pend = IPIC_SIPNR_H,
  56. .mask = IPIC_SIMSR_H,
  57. .prio = IPIC_SIPRR_D,
  58. .force = IPIC_SIFCR_H,
  59. .bit = 29,
  60. .prio_mask = 5,
  61. },
  62. [15] = {
  63. .pend = IPIC_SIPNR_H,
  64. .mask = IPIC_SIMSR_H,
  65. .prio = IPIC_SIPRR_D,
  66. .force = IPIC_SIFCR_H,
  67. .bit = 30,
  68. .prio_mask = 6,
  69. },
  70. [16] = {
  71. .pend = IPIC_SIPNR_H,
  72. .mask = IPIC_SIMSR_H,
  73. .prio = IPIC_SIPRR_D,
  74. .force = IPIC_SIFCR_H,
  75. .bit = 31,
  76. .prio_mask = 7,
  77. },
  78. [17] = {
  79. .pend = IPIC_SEPNR,
  80. .mask = IPIC_SEMSR,
  81. .prio = IPIC_SMPRR_A,
  82. .force = IPIC_SEFCR,
  83. .bit = 1,
  84. .prio_mask = 5,
  85. },
  86. [18] = {
  87. .pend = IPIC_SEPNR,
  88. .mask = IPIC_SEMSR,
  89. .prio = IPIC_SMPRR_A,
  90. .force = IPIC_SEFCR,
  91. .bit = 2,
  92. .prio_mask = 6,
  93. },
  94. [19] = {
  95. .pend = IPIC_SEPNR,
  96. .mask = IPIC_SEMSR,
  97. .prio = IPIC_SMPRR_A,
  98. .force = IPIC_SEFCR,
  99. .bit = 3,
  100. .prio_mask = 7,
  101. },
  102. [20] = {
  103. .pend = IPIC_SEPNR,
  104. .mask = IPIC_SEMSR,
  105. .prio = IPIC_SMPRR_B,
  106. .force = IPIC_SEFCR,
  107. .bit = 4,
  108. .prio_mask = 4,
  109. },
  110. [21] = {
  111. .pend = IPIC_SEPNR,
  112. .mask = IPIC_SEMSR,
  113. .prio = IPIC_SMPRR_B,
  114. .force = IPIC_SEFCR,
  115. .bit = 5,
  116. .prio_mask = 5,
  117. },
  118. [22] = {
  119. .pend = IPIC_SEPNR,
  120. .mask = IPIC_SEMSR,
  121. .prio = IPIC_SMPRR_B,
  122. .force = IPIC_SEFCR,
  123. .bit = 6,
  124. .prio_mask = 6,
  125. },
  126. [23] = {
  127. .pend = IPIC_SEPNR,
  128. .mask = IPIC_SEMSR,
  129. .prio = IPIC_SMPRR_B,
  130. .force = IPIC_SEFCR,
  131. .bit = 7,
  132. .prio_mask = 7,
  133. },
  134. [32] = {
  135. .pend = IPIC_SIPNR_H,
  136. .mask = IPIC_SIMSR_H,
  137. .prio = IPIC_SIPRR_A,
  138. .force = IPIC_SIFCR_H,
  139. .bit = 0,
  140. .prio_mask = 0,
  141. },
  142. [33] = {
  143. .pend = IPIC_SIPNR_H,
  144. .mask = IPIC_SIMSR_H,
  145. .prio = IPIC_SIPRR_A,
  146. .force = IPIC_SIFCR_H,
  147. .bit = 1,
  148. .prio_mask = 1,
  149. },
  150. [34] = {
  151. .pend = IPIC_SIPNR_H,
  152. .mask = IPIC_SIMSR_H,
  153. .prio = IPIC_SIPRR_A,
  154. .force = IPIC_SIFCR_H,
  155. .bit = 2,
  156. .prio_mask = 2,
  157. },
  158. [35] = {
  159. .pend = IPIC_SIPNR_H,
  160. .mask = IPIC_SIMSR_H,
  161. .prio = IPIC_SIPRR_A,
  162. .force = IPIC_SIFCR_H,
  163. .bit = 3,
  164. .prio_mask = 3,
  165. },
  166. [36] = {
  167. .pend = IPIC_SIPNR_H,
  168. .mask = IPIC_SIMSR_H,
  169. .prio = IPIC_SIPRR_A,
  170. .force = IPIC_SIFCR_H,
  171. .bit = 4,
  172. .prio_mask = 4,
  173. },
  174. [37] = {
  175. .pend = IPIC_SIPNR_H,
  176. .mask = IPIC_SIMSR_H,
  177. .prio = IPIC_SIPRR_A,
  178. .force = IPIC_SIFCR_H,
  179. .bit = 5,
  180. .prio_mask = 5,
  181. },
  182. [38] = {
  183. .pend = IPIC_SIPNR_H,
  184. .mask = IPIC_SIMSR_H,
  185. .prio = IPIC_SIPRR_A,
  186. .force = IPIC_SIFCR_H,
  187. .bit = 6,
  188. .prio_mask = 6,
  189. },
  190. [39] = {
  191. .pend = IPIC_SIPNR_H,
  192. .mask = IPIC_SIMSR_H,
  193. .prio = IPIC_SIPRR_A,
  194. .force = IPIC_SIFCR_H,
  195. .bit = 7,
  196. .prio_mask = 7,
  197. },
  198. [48] = {
  199. .pend = IPIC_SEPNR,
  200. .mask = IPIC_SEMSR,
  201. .prio = IPIC_SMPRR_A,
  202. .force = IPIC_SEFCR,
  203. .bit = 0,
  204. .prio_mask = 4,
  205. },
  206. [64] = {
  207. .pend = IPIC_SIPNR_H,
  208. .mask = IPIC_SIMSR_L,
  209. .prio = IPIC_SMPRR_A,
  210. .force = IPIC_SIFCR_L,
  211. .bit = 0,
  212. .prio_mask = 0,
  213. },
  214. [65] = {
  215. .pend = IPIC_SIPNR_H,
  216. .mask = IPIC_SIMSR_L,
  217. .prio = IPIC_SMPRR_A,
  218. .force = IPIC_SIFCR_L,
  219. .bit = 1,
  220. .prio_mask = 1,
  221. },
  222. [66] = {
  223. .pend = IPIC_SIPNR_H,
  224. .mask = IPIC_SIMSR_L,
  225. .prio = IPIC_SMPRR_A,
  226. .force = IPIC_SIFCR_L,
  227. .bit = 2,
  228. .prio_mask = 2,
  229. },
  230. [67] = {
  231. .pend = IPIC_SIPNR_H,
  232. .mask = IPIC_SIMSR_L,
  233. .prio = IPIC_SMPRR_A,
  234. .force = IPIC_SIFCR_L,
  235. .bit = 3,
  236. .prio_mask = 3,
  237. },
  238. [68] = {
  239. .pend = IPIC_SIPNR_H,
  240. .mask = IPIC_SIMSR_L,
  241. .prio = IPIC_SMPRR_B,
  242. .force = IPIC_SIFCR_L,
  243. .bit = 4,
  244. .prio_mask = 0,
  245. },
  246. [69] = {
  247. .pend = IPIC_SIPNR_H,
  248. .mask = IPIC_SIMSR_L,
  249. .prio = IPIC_SMPRR_B,
  250. .force = IPIC_SIFCR_L,
  251. .bit = 5,
  252. .prio_mask = 1,
  253. },
  254. [70] = {
  255. .pend = IPIC_SIPNR_H,
  256. .mask = IPIC_SIMSR_L,
  257. .prio = IPIC_SMPRR_B,
  258. .force = IPIC_SIFCR_L,
  259. .bit = 6,
  260. .prio_mask = 2,
  261. },
  262. [71] = {
  263. .pend = IPIC_SIPNR_H,
  264. .mask = IPIC_SIMSR_L,
  265. .prio = IPIC_SMPRR_B,
  266. .force = IPIC_SIFCR_L,
  267. .bit = 7,
  268. .prio_mask = 3,
  269. },
  270. [72] = {
  271. .pend = IPIC_SIPNR_H,
  272. .mask = IPIC_SIMSR_L,
  273. .prio = 0,
  274. .force = IPIC_SIFCR_L,
  275. .bit = 8,
  276. },
  277. [73] = {
  278. .pend = IPIC_SIPNR_H,
  279. .mask = IPIC_SIMSR_L,
  280. .prio = 0,
  281. .force = IPIC_SIFCR_L,
  282. .bit = 9,
  283. },
  284. [74] = {
  285. .pend = IPIC_SIPNR_H,
  286. .mask = IPIC_SIMSR_L,
  287. .prio = 0,
  288. .force = IPIC_SIFCR_L,
  289. .bit = 10,
  290. },
  291. [75] = {
  292. .pend = IPIC_SIPNR_H,
  293. .mask = IPIC_SIMSR_L,
  294. .prio = 0,
  295. .force = IPIC_SIFCR_L,
  296. .bit = 11,
  297. },
  298. [76] = {
  299. .pend = IPIC_SIPNR_H,
  300. .mask = IPIC_SIMSR_L,
  301. .prio = 0,
  302. .force = IPIC_SIFCR_L,
  303. .bit = 12,
  304. },
  305. [77] = {
  306. .pend = IPIC_SIPNR_H,
  307. .mask = IPIC_SIMSR_L,
  308. .prio = 0,
  309. .force = IPIC_SIFCR_L,
  310. .bit = 13,
  311. },
  312. [78] = {
  313. .pend = IPIC_SIPNR_H,
  314. .mask = IPIC_SIMSR_L,
  315. .prio = 0,
  316. .force = IPIC_SIFCR_L,
  317. .bit = 14,
  318. },
  319. [79] = {
  320. .pend = IPIC_SIPNR_H,
  321. .mask = IPIC_SIMSR_L,
  322. .prio = 0,
  323. .force = IPIC_SIFCR_L,
  324. .bit = 15,
  325. },
  326. [80] = {
  327. .pend = IPIC_SIPNR_H,
  328. .mask = IPIC_SIMSR_L,
  329. .prio = 0,
  330. .force = IPIC_SIFCR_L,
  331. .bit = 16,
  332. },
  333. [84] = {
  334. .pend = IPIC_SIPNR_H,
  335. .mask = IPIC_SIMSR_L,
  336. .prio = 0,
  337. .force = IPIC_SIFCR_L,
  338. .bit = 20,
  339. },
  340. [85] = {
  341. .pend = IPIC_SIPNR_H,
  342. .mask = IPIC_SIMSR_L,
  343. .prio = 0,
  344. .force = IPIC_SIFCR_L,
  345. .bit = 21,
  346. },
  347. [90] = {
  348. .pend = IPIC_SIPNR_H,
  349. .mask = IPIC_SIMSR_L,
  350. .prio = 0,
  351. .force = IPIC_SIFCR_L,
  352. .bit = 26,
  353. },
  354. [91] = {
  355. .pend = IPIC_SIPNR_H,
  356. .mask = IPIC_SIMSR_L,
  357. .prio = 0,
  358. .force = IPIC_SIFCR_L,
  359. .bit = 27,
  360. },
  361. };
  362. static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
  363. {
  364. return in_be32(base + (reg >> 2));
  365. }
  366. static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
  367. {
  368. out_be32(base + (reg >> 2), value);
  369. }
  370. static inline struct ipic * ipic_from_irq(unsigned int irq)
  371. {
  372. return primary_ipic;
  373. }
  374. static void ipic_enable_irq(unsigned int irq)
  375. {
  376. struct ipic *ipic = ipic_from_irq(irq);
  377. unsigned int src = irq - ipic->irq_offset;
  378. u32 temp;
  379. temp = ipic_read(ipic->regs, ipic_info[src].mask);
  380. temp |= (1 << (31 - ipic_info[src].bit));
  381. ipic_write(ipic->regs, ipic_info[src].mask, temp);
  382. }
  383. static void ipic_disable_irq(unsigned int irq)
  384. {
  385. struct ipic *ipic = ipic_from_irq(irq);
  386. unsigned int src = irq - ipic->irq_offset;
  387. u32 temp;
  388. temp = ipic_read(ipic->regs, ipic_info[src].mask);
  389. temp &= ~(1 << (31 - ipic_info[src].bit));
  390. ipic_write(ipic->regs, ipic_info[src].mask, temp);
  391. }
  392. static void ipic_disable_irq_and_ack(unsigned int irq)
  393. {
  394. struct ipic *ipic = ipic_from_irq(irq);
  395. unsigned int src = irq - ipic->irq_offset;
  396. u32 temp;
  397. ipic_disable_irq(irq);
  398. temp = ipic_read(ipic->regs, ipic_info[src].pend);
  399. temp |= (1 << (31 - ipic_info[src].bit));
  400. ipic_write(ipic->regs, ipic_info[src].pend, temp);
  401. }
  402. static void ipic_end_irq(unsigned int irq)
  403. {
  404. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  405. ipic_enable_irq(irq);
  406. }
  407. struct hw_interrupt_type ipic = {
  408. .typename = " IPIC ",
  409. .enable = ipic_enable_irq,
  410. .disable = ipic_disable_irq,
  411. .ack = ipic_disable_irq_and_ack,
  412. .end = ipic_end_irq,
  413. };
  414. void __init ipic_init(phys_addr_t phys_addr,
  415. unsigned int flags,
  416. unsigned int irq_offset,
  417. unsigned char *senses,
  418. unsigned int senses_count)
  419. {
  420. u32 i, temp = 0;
  421. primary_ipic = &p_ipic;
  422. primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
  423. primary_ipic->irq_offset = irq_offset;
  424. ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
  425. /* default priority scheme is grouped. If spread mode is required
  426. * configure SICFR accordingly */
  427. if (flags & IPIC_SPREADMODE_GRP_A)
  428. temp |= SICFR_IPSA;
  429. if (flags & IPIC_SPREADMODE_GRP_D)
  430. temp |= SICFR_IPSD;
  431. if (flags & IPIC_SPREADMODE_MIX_A)
  432. temp |= SICFR_MPSA;
  433. if (flags & IPIC_SPREADMODE_MIX_B)
  434. temp |= SICFR_MPSB;
  435. ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
  436. /* handle MCP route */
  437. temp = 0;
  438. if (flags & IPIC_DISABLE_MCP_OUT)
  439. temp = SERCR_MCPR;
  440. ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
  441. /* handle routing of IRQ0 to MCP */
  442. temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
  443. if (flags & IPIC_IRQ0_MCP)
  444. temp |= SEMSR_SIRQ0;
  445. else
  446. temp &= ~SEMSR_SIRQ0;
  447. ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
  448. for (i = 0 ; i < NR_IPIC_INTS ; i++) {
  449. irq_desc[i+irq_offset].handler = &ipic;
  450. irq_desc[i+irq_offset].status = IRQ_LEVEL;
  451. }
  452. temp = 0;
  453. for (i = 0 ; i < senses_count ; i++) {
  454. if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
  455. temp |= 1 << (15 - i);
  456. if (i != 0)
  457. irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
  458. else
  459. irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
  460. }
  461. }
  462. ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
  463. printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
  464. senses_count, primary_ipic->regs);
  465. }
  466. int ipic_set_priority(unsigned int irq, unsigned int priority)
  467. {
  468. struct ipic *ipic = ipic_from_irq(irq);
  469. unsigned int src = irq - ipic->irq_offset;
  470. u32 temp;
  471. if (priority > 7)
  472. return -EINVAL;
  473. if (src > 127)
  474. return -EINVAL;
  475. if (ipic_info[src].prio == 0)
  476. return -EINVAL;
  477. temp = ipic_read(ipic->regs, ipic_info[src].prio);
  478. if (priority < 4) {
  479. temp &= ~(0x7 << (20 + (3 - priority) * 3));
  480. temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
  481. } else {
  482. temp &= ~(0x7 << (4 + (7 - priority) * 3));
  483. temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
  484. }
  485. ipic_write(ipic->regs, ipic_info[src].prio, temp);
  486. return 0;
  487. }
  488. void ipic_set_highest_priority(unsigned int irq)
  489. {
  490. struct ipic *ipic = ipic_from_irq(irq);
  491. unsigned int src = irq - ipic->irq_offset;
  492. u32 temp;
  493. temp = ipic_read(ipic->regs, IPIC_SICFR);
  494. /* clear and set HPI */
  495. temp &= 0x7f000000;
  496. temp |= (src & 0x7f) << 24;
  497. ipic_write(ipic->regs, IPIC_SICFR, temp);
  498. }
  499. void ipic_set_default_priority(void)
  500. {
  501. ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
  502. ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
  503. ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
  504. ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
  505. ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
  506. ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
  507. ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
  508. ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
  509. ipic_set_priority(MPC83xx_IRQ_UART1, 0);
  510. ipic_set_priority(MPC83xx_IRQ_UART2, 1);
  511. ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
  512. ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
  513. ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
  514. ipic_set_priority(MPC83xx_IRQ_SPI, 7);
  515. ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
  516. ipic_set_priority(MPC83xx_IRQ_PIT, 1);
  517. ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
  518. ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
  519. ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
  520. ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
  521. ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
  522. ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
  523. ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
  524. ipic_set_priority(MPC83xx_IRQ_MU, 1);
  525. ipic_set_priority(MPC83xx_IRQ_SBA, 2);
  526. ipic_set_priority(MPC83xx_IRQ_DMA, 3);
  527. ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
  528. ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
  529. ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
  530. ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
  531. }
  532. void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
  533. {
  534. struct ipic *ipic = primary_ipic;
  535. u32 temp;
  536. temp = ipic_read(ipic->regs, IPIC_SERMR);
  537. temp |= (1 << (31 - mcp_irq));
  538. ipic_write(ipic->regs, IPIC_SERMR, temp);
  539. }
  540. void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
  541. {
  542. struct ipic *ipic = primary_ipic;
  543. u32 temp;
  544. temp = ipic_read(ipic->regs, IPIC_SERMR);
  545. temp &= (1 << (31 - mcp_irq));
  546. ipic_write(ipic->regs, IPIC_SERMR, temp);
  547. }
  548. u32 ipic_get_mcp_status(void)
  549. {
  550. return ipic_read(primary_ipic->regs, IPIC_SERMR);
  551. }
  552. void ipic_clear_mcp_status(u32 mask)
  553. {
  554. ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
  555. }
  556. /* Return an interrupt vector or -1 if no interrupt is pending. */
  557. int ipic_get_irq(struct pt_regs *regs)
  558. {
  559. int irq;
  560. irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
  561. if (irq == 0) /* 0 --> no irq is pending */
  562. irq = -1;
  563. return irq;
  564. }
  565. static struct sysdev_class ipic_sysclass = {
  566. set_kset_name("ipic"),
  567. };
  568. static struct sys_device device_ipic = {
  569. .id = 0,
  570. .cls = &ipic_sysclass,
  571. };
  572. static int __init init_ipic_sysfs(void)
  573. {
  574. int rc;
  575. if (!primary_ipic->regs)
  576. return -ENODEV;
  577. printk(KERN_DEBUG "Registering ipic with sysfs...\n");
  578. rc = sysdev_class_register(&ipic_sysclass);
  579. if (rc) {
  580. printk(KERN_ERR "Failed registering ipic sys class\n");
  581. return -ENODEV;
  582. }
  583. rc = sysdev_register(&device_ipic);
  584. if (rc) {
  585. printk(KERN_ERR "Failed registering ipic sys device\n");
  586. return -ENODEV;
  587. }
  588. return 0;
  589. }
  590. subsys_initcall(init_ipic_sysfs);