icu.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. /*
  2. * icu.c, Interrupt Control Unit routines for the NEC VR4100 series.
  3. *
  4. * Copyright (C) 2001-2002 MontaVista Software Inc.
  5. * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
  6. * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  7. * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. */
  23. /*
  24. * Changes:
  25. * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
  26. * - New creation, NEC VR4122 and VR4131 are supported.
  27. * - Added support for NEC VR4111 and VR4121.
  28. *
  29. * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  30. * - Coped with INTASSIGN of NEC VR4133.
  31. */
  32. #include <linux/errno.h>
  33. #include <linux/init.h>
  34. #include <linux/interrupt.h>
  35. #include <linux/irq.h>
  36. #include <linux/module.h>
  37. #include <linux/smp.h>
  38. #include <linux/types.h>
  39. #include <asm/cpu.h>
  40. #include <asm/io.h>
  41. #include <asm/irq.h>
  42. #include <asm/irq_cpu.h>
  43. #include <asm/vr41xx/vr41xx.h>
  44. extern asmlinkage void vr41xx_handle_interrupt(void);
  45. extern void init_vr41xx_giuint_irq(void);
  46. extern void giuint_irq_dispatch(struct pt_regs *regs);
  47. static uint32_t icu1_base;
  48. static uint32_t icu2_base;
  49. static struct irqaction icu_cascade = {
  50. .handler = no_action,
  51. .mask = CPU_MASK_NONE,
  52. .name = "cascade",
  53. };
  54. static unsigned char sysint1_assign[16] = {
  55. 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  56. static unsigned char sysint2_assign[16] = {
  57. 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  58. #define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080)
  59. #define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200)
  60. #define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080)
  61. #define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0)
  62. #define SYSINT1REG 0x00
  63. #define PIUINTREG 0x02
  64. #define INTASSIGN0 0x04
  65. #define INTASSIGN1 0x06
  66. #define GIUINTLREG 0x08
  67. #define DSIUINTREG 0x0a
  68. #define MSYSINT1REG 0x0c
  69. #define MPIUINTREG 0x0e
  70. #define MAIUINTREG 0x10
  71. #define MKIUINTREG 0x12
  72. #define MGIUINTLREG 0x14
  73. #define MDSIUINTREG 0x16
  74. #define NMIREG 0x18
  75. #define SOFTREG 0x1a
  76. #define INTASSIGN2 0x1c
  77. #define INTASSIGN3 0x1e
  78. #define SYSINT2REG 0x00
  79. #define GIUINTHREG 0x02
  80. #define FIRINTREG 0x04
  81. #define MSYSINT2REG 0x06
  82. #define MGIUINTHREG 0x08
  83. #define MFIRINTREG 0x0a
  84. #define PCIINTREG 0x0c
  85. #define PCIINT0 0x0001
  86. #define SCUINTREG 0x0e
  87. #define SCUINT0 0x0001
  88. #define CSIINTREG 0x10
  89. #define MPCIINTREG 0x12
  90. #define MSCUINTREG 0x14
  91. #define MCSIINTREG 0x16
  92. #define BCUINTREG 0x18
  93. #define BCUINTR 0x0001
  94. #define MBCUINTREG 0x1a
  95. #define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */
  96. #define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */
  97. #define read_icu1(offset) readw(icu1_base + (offset))
  98. #define write_icu1(val, offset) writew((val), icu1_base + (offset))
  99. #define read_icu2(offset) readw(icu2_base + (offset))
  100. #define write_icu2(val, offset) writew((val), icu2_base + (offset))
  101. #define INTASSIGN_MAX 4
  102. #define INTASSIGN_MASK 0x0007
  103. static inline uint16_t set_icu1(uint8_t offset, uint16_t set)
  104. {
  105. uint16_t res;
  106. res = read_icu1(offset);
  107. res |= set;
  108. write_icu1(res, offset);
  109. return res;
  110. }
  111. static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear)
  112. {
  113. uint16_t res;
  114. res = read_icu1(offset);
  115. res &= ~clear;
  116. write_icu1(res, offset);
  117. return res;
  118. }
  119. static inline uint16_t set_icu2(uint8_t offset, uint16_t set)
  120. {
  121. uint16_t res;
  122. res = read_icu2(offset);
  123. res |= set;
  124. write_icu2(res, offset);
  125. return res;
  126. }
  127. static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear)
  128. {
  129. uint16_t res;
  130. res = read_icu2(offset);
  131. res &= ~clear;
  132. write_icu2(res, offset);
  133. return res;
  134. }
  135. /*=======================================================================*/
  136. void vr41xx_enable_piuint(uint16_t mask)
  137. {
  138. irq_desc_t *desc = irq_desc + PIU_IRQ;
  139. unsigned long flags;
  140. if (current_cpu_data.cputype == CPU_VR4111 ||
  141. current_cpu_data.cputype == CPU_VR4121) {
  142. spin_lock_irqsave(&desc->lock, flags);
  143. set_icu1(MPIUINTREG, mask);
  144. spin_unlock_irqrestore(&desc->lock, flags);
  145. }
  146. }
  147. EXPORT_SYMBOL(vr41xx_enable_piuint);
  148. void vr41xx_disable_piuint(uint16_t mask)
  149. {
  150. irq_desc_t *desc = irq_desc + PIU_IRQ;
  151. unsigned long flags;
  152. if (current_cpu_data.cputype == CPU_VR4111 ||
  153. current_cpu_data.cputype == CPU_VR4121) {
  154. spin_lock_irqsave(&desc->lock, flags);
  155. clear_icu1(MPIUINTREG, mask);
  156. spin_unlock_irqrestore(&desc->lock, flags);
  157. }
  158. }
  159. EXPORT_SYMBOL(vr41xx_disable_piuint);
  160. void vr41xx_enable_aiuint(uint16_t mask)
  161. {
  162. irq_desc_t *desc = irq_desc + AIU_IRQ;
  163. unsigned long flags;
  164. if (current_cpu_data.cputype == CPU_VR4111 ||
  165. current_cpu_data.cputype == CPU_VR4121) {
  166. spin_lock_irqsave(&desc->lock, flags);
  167. set_icu1(MAIUINTREG, mask);
  168. spin_unlock_irqrestore(&desc->lock, flags);
  169. }
  170. }
  171. EXPORT_SYMBOL(vr41xx_enable_aiuint);
  172. void vr41xx_disable_aiuint(uint16_t mask)
  173. {
  174. irq_desc_t *desc = irq_desc + AIU_IRQ;
  175. unsigned long flags;
  176. if (current_cpu_data.cputype == CPU_VR4111 ||
  177. current_cpu_data.cputype == CPU_VR4121) {
  178. spin_lock_irqsave(&desc->lock, flags);
  179. clear_icu1(MAIUINTREG, mask);
  180. spin_unlock_irqrestore(&desc->lock, flags);
  181. }
  182. }
  183. EXPORT_SYMBOL(vr41xx_disable_aiuint);
  184. void vr41xx_enable_kiuint(uint16_t mask)
  185. {
  186. irq_desc_t *desc = irq_desc + KIU_IRQ;
  187. unsigned long flags;
  188. if (current_cpu_data.cputype == CPU_VR4111 ||
  189. current_cpu_data.cputype == CPU_VR4121) {
  190. spin_lock_irqsave(&desc->lock, flags);
  191. set_icu1(MKIUINTREG, mask);
  192. spin_unlock_irqrestore(&desc->lock, flags);
  193. }
  194. }
  195. EXPORT_SYMBOL(vr41xx_enable_kiuint);
  196. void vr41xx_disable_kiuint(uint16_t mask)
  197. {
  198. irq_desc_t *desc = irq_desc + KIU_IRQ;
  199. unsigned long flags;
  200. if (current_cpu_data.cputype == CPU_VR4111 ||
  201. current_cpu_data.cputype == CPU_VR4121) {
  202. spin_lock_irqsave(&desc->lock, flags);
  203. clear_icu1(MKIUINTREG, mask);
  204. spin_unlock_irqrestore(&desc->lock, flags);
  205. }
  206. }
  207. EXPORT_SYMBOL(vr41xx_disable_kiuint);
  208. void vr41xx_enable_dsiuint(uint16_t mask)
  209. {
  210. irq_desc_t *desc = irq_desc + DSIU_IRQ;
  211. unsigned long flags;
  212. spin_lock_irqsave(&desc->lock, flags);
  213. set_icu1(MDSIUINTREG, mask);
  214. spin_unlock_irqrestore(&desc->lock, flags);
  215. }
  216. EXPORT_SYMBOL(vr41xx_enable_dsiuint);
  217. void vr41xx_disable_dsiuint(uint16_t mask)
  218. {
  219. irq_desc_t *desc = irq_desc + DSIU_IRQ;
  220. unsigned long flags;
  221. spin_lock_irqsave(&desc->lock, flags);
  222. clear_icu1(MDSIUINTREG, mask);
  223. spin_unlock_irqrestore(&desc->lock, flags);
  224. }
  225. EXPORT_SYMBOL(vr41xx_disable_dsiuint);
  226. void vr41xx_enable_firint(uint16_t mask)
  227. {
  228. irq_desc_t *desc = irq_desc + FIR_IRQ;
  229. unsigned long flags;
  230. spin_lock_irqsave(&desc->lock, flags);
  231. set_icu2(MFIRINTREG, mask);
  232. spin_unlock_irqrestore(&desc->lock, flags);
  233. }
  234. EXPORT_SYMBOL(vr41xx_enable_firint);
  235. void vr41xx_disable_firint(uint16_t mask)
  236. {
  237. irq_desc_t *desc = irq_desc + FIR_IRQ;
  238. unsigned long flags;
  239. spin_lock_irqsave(&desc->lock, flags);
  240. clear_icu2(MFIRINTREG, mask);
  241. spin_unlock_irqrestore(&desc->lock, flags);
  242. }
  243. EXPORT_SYMBOL(vr41xx_disable_firint);
  244. void vr41xx_enable_pciint(void)
  245. {
  246. irq_desc_t *desc = irq_desc + PCI_IRQ;
  247. unsigned long flags;
  248. if (current_cpu_data.cputype == CPU_VR4122 ||
  249. current_cpu_data.cputype == CPU_VR4131 ||
  250. current_cpu_data.cputype == CPU_VR4133) {
  251. spin_lock_irqsave(&desc->lock, flags);
  252. write_icu2(PCIINT0, MPCIINTREG);
  253. spin_unlock_irqrestore(&desc->lock, flags);
  254. }
  255. }
  256. EXPORT_SYMBOL(vr41xx_enable_pciint);
  257. void vr41xx_disable_pciint(void)
  258. {
  259. irq_desc_t *desc = irq_desc + PCI_IRQ;
  260. unsigned long flags;
  261. if (current_cpu_data.cputype == CPU_VR4122 ||
  262. current_cpu_data.cputype == CPU_VR4131 ||
  263. current_cpu_data.cputype == CPU_VR4133) {
  264. spin_lock_irqsave(&desc->lock, flags);
  265. write_icu2(0, MPCIINTREG);
  266. spin_unlock_irqrestore(&desc->lock, flags);
  267. }
  268. }
  269. EXPORT_SYMBOL(vr41xx_disable_pciint);
  270. void vr41xx_enable_scuint(void)
  271. {
  272. irq_desc_t *desc = irq_desc + SCU_IRQ;
  273. unsigned long flags;
  274. if (current_cpu_data.cputype == CPU_VR4122 ||
  275. current_cpu_data.cputype == CPU_VR4131 ||
  276. current_cpu_data.cputype == CPU_VR4133) {
  277. spin_lock_irqsave(&desc->lock, flags);
  278. write_icu2(SCUINT0, MSCUINTREG);
  279. spin_unlock_irqrestore(&desc->lock, flags);
  280. }
  281. }
  282. EXPORT_SYMBOL(vr41xx_enable_scuint);
  283. void vr41xx_disable_scuint(void)
  284. {
  285. irq_desc_t *desc = irq_desc + SCU_IRQ;
  286. unsigned long flags;
  287. if (current_cpu_data.cputype == CPU_VR4122 ||
  288. current_cpu_data.cputype == CPU_VR4131 ||
  289. current_cpu_data.cputype == CPU_VR4133) {
  290. spin_lock_irqsave(&desc->lock, flags);
  291. write_icu2(0, MSCUINTREG);
  292. spin_unlock_irqrestore(&desc->lock, flags);
  293. }
  294. }
  295. EXPORT_SYMBOL(vr41xx_disable_scuint);
  296. void vr41xx_enable_csiint(uint16_t mask)
  297. {
  298. irq_desc_t *desc = irq_desc + CSI_IRQ;
  299. unsigned long flags;
  300. if (current_cpu_data.cputype == CPU_VR4122 ||
  301. current_cpu_data.cputype == CPU_VR4131 ||
  302. current_cpu_data.cputype == CPU_VR4133) {
  303. spin_lock_irqsave(&desc->lock, flags);
  304. set_icu2(MCSIINTREG, mask);
  305. spin_unlock_irqrestore(&desc->lock, flags);
  306. }
  307. }
  308. EXPORT_SYMBOL(vr41xx_enable_csiint);
  309. void vr41xx_disable_csiint(uint16_t mask)
  310. {
  311. irq_desc_t *desc = irq_desc + CSI_IRQ;
  312. unsigned long flags;
  313. if (current_cpu_data.cputype == CPU_VR4122 ||
  314. current_cpu_data.cputype == CPU_VR4131 ||
  315. current_cpu_data.cputype == CPU_VR4133) {
  316. spin_lock_irqsave(&desc->lock, flags);
  317. clear_icu2(MCSIINTREG, mask);
  318. spin_unlock_irqrestore(&desc->lock, flags);
  319. }
  320. }
  321. EXPORT_SYMBOL(vr41xx_disable_csiint);
  322. void vr41xx_enable_bcuint(void)
  323. {
  324. irq_desc_t *desc = irq_desc + BCU_IRQ;
  325. unsigned long flags;
  326. if (current_cpu_data.cputype == CPU_VR4122 ||
  327. current_cpu_data.cputype == CPU_VR4131 ||
  328. current_cpu_data.cputype == CPU_VR4133) {
  329. spin_lock_irqsave(&desc->lock, flags);
  330. write_icu2(BCUINTR, MBCUINTREG);
  331. spin_unlock_irqrestore(&desc->lock, flags);
  332. }
  333. }
  334. EXPORT_SYMBOL(vr41xx_enable_bcuint);
  335. void vr41xx_disable_bcuint(void)
  336. {
  337. irq_desc_t *desc = irq_desc + BCU_IRQ;
  338. unsigned long flags;
  339. if (current_cpu_data.cputype == CPU_VR4122 ||
  340. current_cpu_data.cputype == CPU_VR4131 ||
  341. current_cpu_data.cputype == CPU_VR4133) {
  342. spin_lock_irqsave(&desc->lock, flags);
  343. write_icu2(0, MBCUINTREG);
  344. spin_unlock_irqrestore(&desc->lock, flags);
  345. }
  346. }
  347. EXPORT_SYMBOL(vr41xx_disable_bcuint);
  348. /*=======================================================================*/
  349. static unsigned int startup_sysint1_irq(unsigned int irq)
  350. {
  351. set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
  352. return 0; /* never anything pending */
  353. }
  354. static void shutdown_sysint1_irq(unsigned int irq)
  355. {
  356. clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
  357. }
  358. static void enable_sysint1_irq(unsigned int irq)
  359. {
  360. set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
  361. }
  362. #define disable_sysint1_irq shutdown_sysint1_irq
  363. #define ack_sysint1_irq shutdown_sysint1_irq
  364. static void end_sysint1_irq(unsigned int irq)
  365. {
  366. if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
  367. set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
  368. }
  369. static struct hw_interrupt_type sysint1_irq_type = {
  370. .typename = "SYSINT1",
  371. .startup = startup_sysint1_irq,
  372. .shutdown = shutdown_sysint1_irq,
  373. .enable = enable_sysint1_irq,
  374. .disable = disable_sysint1_irq,
  375. .ack = ack_sysint1_irq,
  376. .end = end_sysint1_irq,
  377. };
  378. /*=======================================================================*/
  379. static unsigned int startup_sysint2_irq(unsigned int irq)
  380. {
  381. set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
  382. return 0; /* never anything pending */
  383. }
  384. static void shutdown_sysint2_irq(unsigned int irq)
  385. {
  386. clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
  387. }
  388. static void enable_sysint2_irq(unsigned int irq)
  389. {
  390. set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
  391. }
  392. #define disable_sysint2_irq shutdown_sysint2_irq
  393. #define ack_sysint2_irq shutdown_sysint2_irq
  394. static void end_sysint2_irq(unsigned int irq)
  395. {
  396. if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
  397. set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
  398. }
  399. static struct hw_interrupt_type sysint2_irq_type = {
  400. .typename = "SYSINT2",
  401. .startup = startup_sysint2_irq,
  402. .shutdown = shutdown_sysint2_irq,
  403. .enable = enable_sysint2_irq,
  404. .disable = disable_sysint2_irq,
  405. .ack = ack_sysint2_irq,
  406. .end = end_sysint2_irq,
  407. };
  408. /*=======================================================================*/
  409. static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
  410. {
  411. irq_desc_t *desc = irq_desc + irq;
  412. uint16_t intassign0, intassign1;
  413. unsigned int pin;
  414. pin = SYSINT1_IRQ_TO_PIN(irq);
  415. spin_lock_irq(&desc->lock);
  416. intassign0 = read_icu1(INTASSIGN0);
  417. intassign1 = read_icu1(INTASSIGN1);
  418. switch (pin) {
  419. case 0:
  420. intassign0 &= ~INTASSIGN_MASK;
  421. intassign0 |= (uint16_t)assign;
  422. break;
  423. case 1:
  424. intassign0 &= ~(INTASSIGN_MASK << 3);
  425. intassign0 |= (uint16_t)assign << 3;
  426. break;
  427. case 2:
  428. intassign0 &= ~(INTASSIGN_MASK << 6);
  429. intassign0 |= (uint16_t)assign << 6;
  430. break;
  431. case 3:
  432. intassign0 &= ~(INTASSIGN_MASK << 9);
  433. intassign0 |= (uint16_t)assign << 9;
  434. break;
  435. case 8:
  436. intassign0 &= ~(INTASSIGN_MASK << 12);
  437. intassign0 |= (uint16_t)assign << 12;
  438. break;
  439. case 9:
  440. intassign1 &= ~INTASSIGN_MASK;
  441. intassign1 |= (uint16_t)assign;
  442. break;
  443. case 11:
  444. intassign1 &= ~(INTASSIGN_MASK << 6);
  445. intassign1 |= (uint16_t)assign << 6;
  446. break;
  447. case 12:
  448. intassign1 &= ~(INTASSIGN_MASK << 9);
  449. intassign1 |= (uint16_t)assign << 9;
  450. break;
  451. default:
  452. return -EINVAL;
  453. }
  454. sysint1_assign[pin] = assign;
  455. write_icu1(intassign0, INTASSIGN0);
  456. write_icu1(intassign1, INTASSIGN1);
  457. spin_unlock_irq(&desc->lock);
  458. return 0;
  459. }
  460. static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
  461. {
  462. irq_desc_t *desc = irq_desc + irq;
  463. uint16_t intassign2, intassign3;
  464. unsigned int pin;
  465. pin = SYSINT2_IRQ_TO_PIN(irq);
  466. spin_lock_irq(&desc->lock);
  467. intassign2 = read_icu1(INTASSIGN2);
  468. intassign3 = read_icu1(INTASSIGN3);
  469. switch (pin) {
  470. case 0:
  471. intassign2 &= ~INTASSIGN_MASK;
  472. intassign2 |= (uint16_t)assign;
  473. break;
  474. case 1:
  475. intassign2 &= ~(INTASSIGN_MASK << 3);
  476. intassign2 |= (uint16_t)assign << 3;
  477. break;
  478. case 3:
  479. intassign2 &= ~(INTASSIGN_MASK << 6);
  480. intassign2 |= (uint16_t)assign << 6;
  481. break;
  482. case 4:
  483. intassign2 &= ~(INTASSIGN_MASK << 9);
  484. intassign2 |= (uint16_t)assign << 9;
  485. break;
  486. case 5:
  487. intassign2 &= ~(INTASSIGN_MASK << 12);
  488. intassign2 |= (uint16_t)assign << 12;
  489. break;
  490. case 6:
  491. intassign3 &= ~INTASSIGN_MASK;
  492. intassign3 |= (uint16_t)assign;
  493. break;
  494. case 7:
  495. intassign3 &= ~(INTASSIGN_MASK << 3);
  496. intassign3 |= (uint16_t)assign << 3;
  497. break;
  498. case 8:
  499. intassign3 &= ~(INTASSIGN_MASK << 6);
  500. intassign3 |= (uint16_t)assign << 6;
  501. break;
  502. case 9:
  503. intassign3 &= ~(INTASSIGN_MASK << 9);
  504. intassign3 |= (uint16_t)assign << 9;
  505. break;
  506. case 10:
  507. intassign3 &= ~(INTASSIGN_MASK << 12);
  508. intassign3 |= (uint16_t)assign << 12;
  509. break;
  510. default:
  511. return -EINVAL;
  512. }
  513. sysint2_assign[pin] = assign;
  514. write_icu1(intassign2, INTASSIGN2);
  515. write_icu1(intassign3, INTASSIGN3);
  516. spin_unlock_irq(&desc->lock);
  517. return 0;
  518. }
  519. int vr41xx_set_intassign(unsigned int irq, unsigned char intassign)
  520. {
  521. int retval = -EINVAL;
  522. if (current_cpu_data.cputype != CPU_VR4133)
  523. return -EINVAL;
  524. if (intassign > INTASSIGN_MAX)
  525. return -EINVAL;
  526. if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST)
  527. retval = set_sysint1_assign(irq, intassign);
  528. else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST)
  529. retval = set_sysint2_assign(irq, intassign);
  530. return retval;
  531. }
  532. EXPORT_SYMBOL(vr41xx_set_intassign);
  533. /*=======================================================================*/
  534. asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs)
  535. {
  536. uint16_t pend1, pend2;
  537. uint16_t mask1, mask2;
  538. int i;
  539. pend1 = read_icu1(SYSINT1REG);
  540. mask1 = read_icu1(MSYSINT1REG);
  541. pend2 = read_icu2(SYSINT2REG);
  542. mask2 = read_icu2(MSYSINT2REG);
  543. mask1 &= pend1;
  544. mask2 &= pend2;
  545. if (mask1) {
  546. for (i = 0; i < 16; i++) {
  547. if (intnum == sysint1_assign[i] &&
  548. (mask1 & ((uint16_t)1 << i))) {
  549. if (i == 8)
  550. giuint_irq_dispatch(regs);
  551. else
  552. do_IRQ(SYSINT1_IRQ(i), regs);
  553. return;
  554. }
  555. }
  556. }
  557. if (mask2) {
  558. for (i = 0; i < 16; i++) {
  559. if (intnum == sysint2_assign[i] &&
  560. (mask2 & ((uint16_t)1 << i))) {
  561. do_IRQ(SYSINT2_IRQ(i), regs);
  562. return;
  563. }
  564. }
  565. }
  566. printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2);
  567. atomic_inc(&irq_err_count);
  568. }
  569. /*=======================================================================*/
  570. static int __init vr41xx_icu_init(void)
  571. {
  572. switch (current_cpu_data.cputype) {
  573. case CPU_VR4111:
  574. case CPU_VR4121:
  575. icu1_base = SYSINT1REG_TYPE1;
  576. icu2_base = SYSINT2REG_TYPE1;
  577. break;
  578. case CPU_VR4122:
  579. case CPU_VR4131:
  580. case CPU_VR4133:
  581. icu1_base = SYSINT1REG_TYPE2;
  582. icu2_base = SYSINT2REG_TYPE2;
  583. break;
  584. default:
  585. printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n");
  586. return -EINVAL;
  587. }
  588. write_icu1(0, MSYSINT1REG);
  589. write_icu1(0xffff, MGIUINTLREG);
  590. write_icu2(0, MSYSINT2REG);
  591. write_icu2(0xffff, MGIUINTHREG);
  592. return 0;
  593. }
  594. early_initcall(vr41xx_icu_init);
  595. /*=======================================================================*/
  596. static inline void init_vr41xx_icu_irq(void)
  597. {
  598. int i;
  599. for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++)
  600. irq_desc[i].handler = &sysint1_irq_type;
  601. for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++)
  602. irq_desc[i].handler = &sysint2_irq_type;
  603. setup_irq(INT0_CASCADE_IRQ, &icu_cascade);
  604. setup_irq(INT1_CASCADE_IRQ, &icu_cascade);
  605. setup_irq(INT2_CASCADE_IRQ, &icu_cascade);
  606. setup_irq(INT3_CASCADE_IRQ, &icu_cascade);
  607. setup_irq(INT4_CASCADE_IRQ, &icu_cascade);
  608. }
  609. void __init arch_init_irq(void)
  610. {
  611. mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
  612. init_vr41xx_icu_irq();
  613. init_vr41xx_giuint_irq();
  614. set_except_vector(0, vr41xx_handle_interrupt);
  615. }