irq-s3c24xx.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356
  1. /*
  2. * S3C24XX IRQ handling
  3. *
  4. * Copyright (c) 2003-2004 Simtec Electronics
  5. * Ben Dooks <ben@simtec.co.uk>
  6. * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.de>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. */
  18. #include <linux/init.h>
  19. #include <linux/slab.h>
  20. #include <linux/module.h>
  21. #include <linux/io.h>
  22. #include <linux/err.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/ioport.h>
  25. #include <linux/device.h>
  26. #include <linux/irqdomain.h>
  27. #include <linux/irqchip/chained_irq.h>
  28. #include <linux/of.h>
  29. #include <linux/of_irq.h>
  30. #include <linux/of_address.h>
  31. #include <asm/exception.h>
  32. #include <asm/mach/irq.h>
  33. #include <mach/regs-irq.h>
  34. #include <mach/regs-gpio.h>
  35. #include <plat/cpu.h>
  36. #include <plat/regs-irqtype.h>
  37. #include <plat/pm.h>
  38. #include "irqchip.h"
  39. #define S3C_IRQTYPE_NONE 0
  40. #define S3C_IRQTYPE_EINT 1
  41. #define S3C_IRQTYPE_EDGE 2
  42. #define S3C_IRQTYPE_LEVEL 3
  43. struct s3c_irq_data {
  44. unsigned int type;
  45. unsigned long offset;
  46. unsigned long parent_irq;
  47. /* data gets filled during init */
  48. struct s3c_irq_intc *intc;
  49. unsigned long sub_bits;
  50. struct s3c_irq_intc *sub_intc;
  51. };
  52. /*
  53. * Sructure holding the controller data
  54. * @reg_pending register holding pending irqs
  55. * @reg_intpnd special register intpnd in main intc
  56. * @reg_mask mask register
  57. * @domain irq_domain of the controller
  58. * @parent parent controller for ext and sub irqs
  59. * @irqs irq-data, always s3c_irq_data[32]
  60. */
  61. struct s3c_irq_intc {
  62. void __iomem *reg_pending;
  63. void __iomem *reg_intpnd;
  64. void __iomem *reg_mask;
  65. struct irq_domain *domain;
  66. struct s3c_irq_intc *parent;
  67. struct s3c_irq_data *irqs;
  68. };
  69. /*
  70. * Array holding pointers to the global controller structs
  71. * [0] ... main_intc
  72. * [1] ... sub_intc
  73. * [2] ... main_intc2 on s3c2416
  74. */
  75. static struct s3c_irq_intc *s3c_intc[3];
  76. static void s3c_irq_mask(struct irq_data *data)
  77. {
  78. struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
  79. struct s3c_irq_intc *intc = irq_data->intc;
  80. struct s3c_irq_intc *parent_intc = intc->parent;
  81. struct s3c_irq_data *parent_data;
  82. unsigned long mask;
  83. unsigned int irqno;
  84. mask = __raw_readl(intc->reg_mask);
  85. mask |= (1UL << irq_data->offset);
  86. __raw_writel(mask, intc->reg_mask);
  87. if (parent_intc) {
  88. parent_data = &parent_intc->irqs[irq_data->parent_irq];
  89. /* check to see if we need to mask the parent IRQ
  90. * The parent_irq is always in main_intc, so the hwirq
  91. * for find_mapping does not need an offset in any case.
  92. */
  93. if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
  94. irqno = irq_find_mapping(parent_intc->domain,
  95. irq_data->parent_irq);
  96. s3c_irq_mask(irq_get_irq_data(irqno));
  97. }
  98. }
  99. }
  100. static void s3c_irq_unmask(struct irq_data *data)
  101. {
  102. struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
  103. struct s3c_irq_intc *intc = irq_data->intc;
  104. struct s3c_irq_intc *parent_intc = intc->parent;
  105. unsigned long mask;
  106. unsigned int irqno;
  107. mask = __raw_readl(intc->reg_mask);
  108. mask &= ~(1UL << irq_data->offset);
  109. __raw_writel(mask, intc->reg_mask);
  110. if (parent_intc) {
  111. irqno = irq_find_mapping(parent_intc->domain,
  112. irq_data->parent_irq);
  113. s3c_irq_unmask(irq_get_irq_data(irqno));
  114. }
  115. }
  116. static inline void s3c_irq_ack(struct irq_data *data)
  117. {
  118. struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
  119. struct s3c_irq_intc *intc = irq_data->intc;
  120. unsigned long bitval = 1UL << irq_data->offset;
  121. __raw_writel(bitval, intc->reg_pending);
  122. if (intc->reg_intpnd)
  123. __raw_writel(bitval, intc->reg_intpnd);
  124. }
  125. static int s3c_irq_type(struct irq_data *data, unsigned int type)
  126. {
  127. switch (type) {
  128. case IRQ_TYPE_NONE:
  129. break;
  130. case IRQ_TYPE_EDGE_RISING:
  131. case IRQ_TYPE_EDGE_FALLING:
  132. case IRQ_TYPE_EDGE_BOTH:
  133. irq_set_handler(data->irq, handle_edge_irq);
  134. break;
  135. case IRQ_TYPE_LEVEL_LOW:
  136. case IRQ_TYPE_LEVEL_HIGH:
  137. irq_set_handler(data->irq, handle_level_irq);
  138. break;
  139. default:
  140. pr_err("No such irq type %d", type);
  141. return -EINVAL;
  142. }
  143. return 0;
  144. }
  145. static int s3c_irqext_type_set(void __iomem *gpcon_reg,
  146. void __iomem *extint_reg,
  147. unsigned long gpcon_offset,
  148. unsigned long extint_offset,
  149. unsigned int type)
  150. {
  151. unsigned long newvalue = 0, value;
  152. /* Set the GPIO to external interrupt mode */
  153. value = __raw_readl(gpcon_reg);
  154. value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
  155. __raw_writel(value, gpcon_reg);
  156. /* Set the external interrupt to pointed trigger type */
  157. switch (type)
  158. {
  159. case IRQ_TYPE_NONE:
  160. pr_warn("No edge setting!\n");
  161. break;
  162. case IRQ_TYPE_EDGE_RISING:
  163. newvalue = S3C2410_EXTINT_RISEEDGE;
  164. break;
  165. case IRQ_TYPE_EDGE_FALLING:
  166. newvalue = S3C2410_EXTINT_FALLEDGE;
  167. break;
  168. case IRQ_TYPE_EDGE_BOTH:
  169. newvalue = S3C2410_EXTINT_BOTHEDGE;
  170. break;
  171. case IRQ_TYPE_LEVEL_LOW:
  172. newvalue = S3C2410_EXTINT_LOWLEV;
  173. break;
  174. case IRQ_TYPE_LEVEL_HIGH:
  175. newvalue = S3C2410_EXTINT_HILEV;
  176. break;
  177. default:
  178. pr_err("No such irq type %d", type);
  179. return -EINVAL;
  180. }
  181. value = __raw_readl(extint_reg);
  182. value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
  183. __raw_writel(value, extint_reg);
  184. return 0;
  185. }
  186. static int s3c_irqext_type(struct irq_data *data, unsigned int type)
  187. {
  188. void __iomem *extint_reg;
  189. void __iomem *gpcon_reg;
  190. unsigned long gpcon_offset, extint_offset;
  191. if ((data->hwirq >= 4) && (data->hwirq <= 7)) {
  192. gpcon_reg = S3C2410_GPFCON;
  193. extint_reg = S3C24XX_EXTINT0;
  194. gpcon_offset = (data->hwirq) * 2;
  195. extint_offset = (data->hwirq) * 4;
  196. } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) {
  197. gpcon_reg = S3C2410_GPGCON;
  198. extint_reg = S3C24XX_EXTINT1;
  199. gpcon_offset = (data->hwirq - 8) * 2;
  200. extint_offset = (data->hwirq - 8) * 4;
  201. } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) {
  202. gpcon_reg = S3C2410_GPGCON;
  203. extint_reg = S3C24XX_EXTINT2;
  204. gpcon_offset = (data->hwirq - 8) * 2;
  205. extint_offset = (data->hwirq - 16) * 4;
  206. } else {
  207. return -EINVAL;
  208. }
  209. return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
  210. extint_offset, type);
  211. }
  212. static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
  213. {
  214. void __iomem *extint_reg;
  215. void __iomem *gpcon_reg;
  216. unsigned long gpcon_offset, extint_offset;
  217. if ((data->hwirq >= 0) && (data->hwirq <= 3)) {
  218. gpcon_reg = S3C2410_GPFCON;
  219. extint_reg = S3C24XX_EXTINT0;
  220. gpcon_offset = (data->hwirq) * 2;
  221. extint_offset = (data->hwirq) * 4;
  222. } else {
  223. return -EINVAL;
  224. }
  225. return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
  226. extint_offset, type);
  227. }
  228. static struct irq_chip s3c_irq_chip = {
  229. .name = "s3c",
  230. .irq_ack = s3c_irq_ack,
  231. .irq_mask = s3c_irq_mask,
  232. .irq_unmask = s3c_irq_unmask,
  233. .irq_set_type = s3c_irq_type,
  234. .irq_set_wake = s3c_irq_wake
  235. };
  236. static struct irq_chip s3c_irq_level_chip = {
  237. .name = "s3c-level",
  238. .irq_mask = s3c_irq_mask,
  239. .irq_unmask = s3c_irq_unmask,
  240. .irq_ack = s3c_irq_ack,
  241. .irq_set_type = s3c_irq_type,
  242. };
  243. static struct irq_chip s3c_irqext_chip = {
  244. .name = "s3c-ext",
  245. .irq_mask = s3c_irq_mask,
  246. .irq_unmask = s3c_irq_unmask,
  247. .irq_ack = s3c_irq_ack,
  248. .irq_set_type = s3c_irqext_type,
  249. .irq_set_wake = s3c_irqext_wake
  250. };
  251. static struct irq_chip s3c_irq_eint0t4 = {
  252. .name = "s3c-ext0",
  253. .irq_ack = s3c_irq_ack,
  254. .irq_mask = s3c_irq_mask,
  255. .irq_unmask = s3c_irq_unmask,
  256. .irq_set_wake = s3c_irq_wake,
  257. .irq_set_type = s3c_irqext0_type,
  258. };
  259. static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
  260. {
  261. struct irq_chip *chip = irq_desc_get_chip(desc);
  262. struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
  263. struct s3c_irq_intc *intc = irq_data->intc;
  264. struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
  265. unsigned long src;
  266. unsigned long msk;
  267. unsigned int n;
  268. unsigned int offset;
  269. /* we're using individual domains for the non-dt case
  270. * and one big domain for the dt case where the subintc
  271. * starts at hwirq number 32.
  272. */
  273. offset = (intc->domain->of_node) ? 32 : 0;
  274. chained_irq_enter(chip, desc);
  275. src = __raw_readl(sub_intc->reg_pending);
  276. msk = __raw_readl(sub_intc->reg_mask);
  277. src &= ~msk;
  278. src &= irq_data->sub_bits;
  279. while (src) {
  280. n = __ffs(src);
  281. src &= ~(1 << n);
  282. irq = irq_find_mapping(sub_intc->domain, offset + n);
  283. generic_handle_irq(irq);
  284. }
  285. chained_irq_exit(chip, desc);
  286. }
  287. static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
  288. struct pt_regs *regs, int intc_offset)
  289. {
  290. int pnd;
  291. int offset;
  292. int irq;
  293. pnd = __raw_readl(intc->reg_intpnd);
  294. if (!pnd)
  295. return false;
  296. /* non-dt machines use individual domains */
  297. if (!intc->domain->of_node)
  298. intc_offset = 0;
  299. /* We have a problem that the INTOFFSET register does not always
  300. * show one interrupt. Occasionally we get two interrupts through
  301. * the prioritiser, and this causes the INTOFFSET register to show
  302. * what looks like the logical-or of the two interrupt numbers.
  303. *
  304. * Thanks to Klaus, Shannon, et al for helping to debug this problem
  305. */
  306. offset = __raw_readl(intc->reg_intpnd + 4);
  307. /* Find the bit manually, when the offset is wrong.
  308. * The pending register only ever contains the one bit of the next
  309. * interrupt to handle.
  310. */
  311. if (!(pnd & (1 << offset)))
  312. offset = __ffs(pnd);
  313. irq = irq_find_mapping(intc->domain, intc_offset + offset);
  314. handle_IRQ(irq, regs);
  315. return true;
  316. }
  317. asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs)
  318. {
  319. do {
  320. if (likely(s3c_intc[0]))
  321. if (s3c24xx_handle_intc(s3c_intc[0], regs, 0))
  322. continue;
  323. if (s3c_intc[2])
  324. if (s3c24xx_handle_intc(s3c_intc[2], regs, 64))
  325. continue;
  326. break;
  327. } while (1);
  328. }
  329. #ifdef CONFIG_FIQ
  330. /**
  331. * s3c24xx_set_fiq - set the FIQ routing
  332. * @irq: IRQ number to route to FIQ on processor.
  333. * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing.
  334. *
  335. * Change the state of the IRQ to FIQ routing depending on @irq and @on. If
  336. * @on is true, the @irq is checked to see if it can be routed and the
  337. * interrupt controller updated to route the IRQ. If @on is false, the FIQ
  338. * routing is cleared, regardless of which @irq is specified.
  339. */
  340. int s3c24xx_set_fiq(unsigned int irq, bool on)
  341. {
  342. u32 intmod;
  343. unsigned offs;
  344. if (on) {
  345. offs = irq - FIQ_START;
  346. if (offs > 31)
  347. return -EINVAL;
  348. intmod = 1 << offs;
  349. } else {
  350. intmod = 0;
  351. }
  352. __raw_writel(intmod, S3C2410_INTMOD);
  353. return 0;
  354. }
  355. EXPORT_SYMBOL_GPL(s3c24xx_set_fiq);
  356. #endif
  357. static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
  358. irq_hw_number_t hw)
  359. {
  360. struct s3c_irq_intc *intc = h->host_data;
  361. struct s3c_irq_data *irq_data = &intc->irqs[hw];
  362. struct s3c_irq_intc *parent_intc;
  363. struct s3c_irq_data *parent_irq_data;
  364. unsigned int irqno;
  365. /* attach controller pointer to irq_data */
  366. irq_data->intc = intc;
  367. irq_data->offset = hw;
  368. parent_intc = intc->parent;
  369. /* set handler and flags */
  370. switch (irq_data->type) {
  371. case S3C_IRQTYPE_NONE:
  372. return 0;
  373. case S3C_IRQTYPE_EINT:
  374. /* On the S3C2412, the EINT0to3 have a parent irq
  375. * but need the s3c_irq_eint0t4 chip
  376. */
  377. if (parent_intc && (!soc_is_s3c2412() || hw >= 4))
  378. irq_set_chip_and_handler(virq, &s3c_irqext_chip,
  379. handle_edge_irq);
  380. else
  381. irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
  382. handle_edge_irq);
  383. break;
  384. case S3C_IRQTYPE_EDGE:
  385. if (parent_intc || intc->reg_pending == S3C2416_SRCPND2)
  386. irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
  387. handle_edge_irq);
  388. else
  389. irq_set_chip_and_handler(virq, &s3c_irq_chip,
  390. handle_edge_irq);
  391. break;
  392. case S3C_IRQTYPE_LEVEL:
  393. if (parent_intc)
  394. irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
  395. handle_level_irq);
  396. else
  397. irq_set_chip_and_handler(virq, &s3c_irq_chip,
  398. handle_level_irq);
  399. break;
  400. default:
  401. pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
  402. return -EINVAL;
  403. }
  404. irq_set_chip_data(virq, irq_data);
  405. set_irq_flags(virq, IRQF_VALID);
  406. if (parent_intc && irq_data->type != S3C_IRQTYPE_NONE) {
  407. if (irq_data->parent_irq > 31) {
  408. pr_err("irq-s3c24xx: parent irq %lu is out of range\n",
  409. irq_data->parent_irq);
  410. goto err;
  411. }
  412. parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
  413. parent_irq_data->sub_intc = intc;
  414. parent_irq_data->sub_bits |= (1UL << hw);
  415. /* attach the demuxer to the parent irq */
  416. irqno = irq_find_mapping(parent_intc->domain,
  417. irq_data->parent_irq);
  418. if (!irqno) {
  419. pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
  420. irq_data->parent_irq);
  421. goto err;
  422. }
  423. irq_set_chained_handler(irqno, s3c_irq_demux);
  424. }
  425. return 0;
  426. err:
  427. set_irq_flags(virq, 0);
  428. /* the only error can result from bad mapping data*/
  429. return -EINVAL;
  430. }
  431. static struct irq_domain_ops s3c24xx_irq_ops = {
  432. .map = s3c24xx_irq_map,
  433. .xlate = irq_domain_xlate_twocell,
  434. };
  435. static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
  436. {
  437. void __iomem *reg_source;
  438. unsigned long pend;
  439. unsigned long last;
  440. int i;
  441. /* if intpnd is set, read the next pending irq from there */
  442. reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending;
  443. last = 0;
  444. for (i = 0; i < 4; i++) {
  445. pend = __raw_readl(reg_source);
  446. if (pend == 0 || pend == last)
  447. break;
  448. __raw_writel(pend, intc->reg_pending);
  449. if (intc->reg_intpnd)
  450. __raw_writel(pend, intc->reg_intpnd);
  451. pr_info("irq: clearing pending status %08x\n", (int)pend);
  452. last = pend;
  453. }
  454. }
  455. static struct s3c_irq_intc * __init s3c24xx_init_intc(struct device_node *np,
  456. struct s3c_irq_data *irq_data,
  457. struct s3c_irq_intc *parent,
  458. unsigned long address)
  459. {
  460. struct s3c_irq_intc *intc;
  461. void __iomem *base = (void *)0xf6000000; /* static mapping */
  462. int irq_num;
  463. int irq_start;
  464. int ret;
  465. intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
  466. if (!intc)
  467. return ERR_PTR(-ENOMEM);
  468. intc->irqs = irq_data;
  469. if (parent)
  470. intc->parent = parent;
  471. /* select the correct data for the controller.
  472. * Need to hard code the irq num start and offset
  473. * to preserve the static mapping for now
  474. */
  475. switch (address) {
  476. case 0x4a000000:
  477. pr_debug("irq: found main intc\n");
  478. intc->reg_pending = base;
  479. intc->reg_mask = base + 0x08;
  480. intc->reg_intpnd = base + 0x10;
  481. irq_num = 32;
  482. irq_start = S3C2410_IRQ(0);
  483. break;
  484. case 0x4a000018:
  485. pr_debug("irq: found subintc\n");
  486. intc->reg_pending = base + 0x18;
  487. intc->reg_mask = base + 0x1c;
  488. irq_num = 29;
  489. irq_start = S3C2410_IRQSUB(0);
  490. break;
  491. case 0x4a000040:
  492. pr_debug("irq: found intc2\n");
  493. intc->reg_pending = base + 0x40;
  494. intc->reg_mask = base + 0x48;
  495. intc->reg_intpnd = base + 0x50;
  496. irq_num = 8;
  497. irq_start = S3C2416_IRQ(0);
  498. break;
  499. case 0x560000a4:
  500. pr_debug("irq: found eintc\n");
  501. base = (void *)0xfd000000;
  502. intc->reg_mask = base + 0xa4;
  503. intc->reg_pending = base + 0xa8;
  504. irq_num = 24;
  505. irq_start = S3C2410_IRQ(32);
  506. break;
  507. default:
  508. pr_err("irq: unsupported controller address\n");
  509. ret = -EINVAL;
  510. goto err;
  511. }
  512. /* now that all the data is complete, init the irq-domain */
  513. s3c24xx_clear_intc(intc);
  514. intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
  515. 0, &s3c24xx_irq_ops,
  516. intc);
  517. if (!intc->domain) {
  518. pr_err("irq: could not create irq-domain\n");
  519. ret = -EINVAL;
  520. goto err;
  521. }
  522. set_handle_irq(s3c24xx_handle_irq);
  523. return intc;
  524. err:
  525. kfree(intc);
  526. return ERR_PTR(ret);
  527. }
  528. static struct s3c_irq_data init_eint[32] = {
  529. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  530. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  531. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  532. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  533. { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
  534. { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
  535. { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
  536. { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
  537. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
  538. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
  539. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
  540. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
  541. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
  542. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
  543. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
  544. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
  545. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
  546. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
  547. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
  548. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
  549. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
  550. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
  551. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
  552. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
  553. };
  554. #ifdef CONFIG_CPU_S3C2410
  555. static struct s3c_irq_data init_s3c2410base[32] = {
  556. { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
  557. { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
  558. { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
  559. { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
  560. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
  561. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
  562. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  563. { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
  564. { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
  565. { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
  566. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
  567. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
  568. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
  569. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
  570. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
  571. { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
  572. { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
  573. { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
  574. { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
  575. { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
  576. { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
  577. { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
  578. { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
  579. { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
  580. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  581. { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
  582. { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
  583. { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
  584. { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
  585. { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
  586. { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
  587. { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
  588. };
  589. static struct s3c_irq_data init_s3c2410subint[32] = {
  590. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
  591. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
  592. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
  593. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
  594. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
  595. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
  596. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
  597. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
  598. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
  599. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
  600. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
  601. };
  602. void __init s3c2410_init_irq(void)
  603. {
  604. #ifdef CONFIG_FIQ
  605. init_FIQ(FIQ_START);
  606. #endif
  607. s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2410base[0], NULL,
  608. 0x4a000000);
  609. if (IS_ERR(s3c_intc[0])) {
  610. pr_err("irq: could not create main interrupt controller\n");
  611. return;
  612. }
  613. s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2410subint[0],
  614. s3c_intc[0], 0x4a000018);
  615. s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
  616. }
  617. #endif
  618. #ifdef CONFIG_CPU_S3C2412
  619. static struct s3c_irq_data init_s3c2412base[32] = {
  620. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT0 */
  621. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT1 */
  622. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT2 */
  623. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT3 */
  624. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
  625. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
  626. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  627. { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
  628. { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
  629. { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
  630. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
  631. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
  632. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
  633. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
  634. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
  635. { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
  636. { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
  637. { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
  638. { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
  639. { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
  640. { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
  641. { .type = S3C_IRQTYPE_LEVEL, }, /* SDI/CF */
  642. { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
  643. { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
  644. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  645. { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
  646. { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
  647. { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
  648. { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
  649. { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
  650. { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
  651. { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
  652. };
  653. static struct s3c_irq_data init_s3c2412eint[32] = {
  654. { .type = S3C_IRQTYPE_EINT, .parent_irq = 0 }, /* EINT0 */
  655. { .type = S3C_IRQTYPE_EINT, .parent_irq = 1 }, /* EINT1 */
  656. { .type = S3C_IRQTYPE_EINT, .parent_irq = 2 }, /* EINT2 */
  657. { .type = S3C_IRQTYPE_EINT, .parent_irq = 3 }, /* EINT3 */
  658. { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
  659. { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
  660. { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
  661. { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
  662. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
  663. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
  664. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
  665. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
  666. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
  667. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
  668. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
  669. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
  670. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
  671. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
  672. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
  673. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
  674. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
  675. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
  676. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
  677. { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
  678. };
  679. static struct s3c_irq_data init_s3c2412subint[32] = {
  680. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
  681. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
  682. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
  683. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
  684. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
  685. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
  686. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
  687. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
  688. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
  689. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
  690. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
  691. { .type = S3C_IRQTYPE_NONE, },
  692. { .type = S3C_IRQTYPE_NONE, },
  693. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* SDI */
  694. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */
  695. };
  696. void __init s3c2412_init_irq(void)
  697. {
  698. pr_info("S3C2412: IRQ Support\n");
  699. #ifdef CONFIG_FIQ
  700. init_FIQ(FIQ_START);
  701. #endif
  702. s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2412base[0], NULL,
  703. 0x4a000000);
  704. if (IS_ERR(s3c_intc[0])) {
  705. pr_err("irq: could not create main interrupt controller\n");
  706. return;
  707. }
  708. s3c24xx_init_intc(NULL, &init_s3c2412eint[0], s3c_intc[0], 0x560000a4);
  709. s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2412subint[0],
  710. s3c_intc[0], 0x4a000018);
  711. }
  712. #endif
  713. #ifdef CONFIG_CPU_S3C2416
  714. static struct s3c_irq_data init_s3c2416base[32] = {
  715. { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
  716. { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
  717. { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
  718. { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
  719. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
  720. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
  721. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  722. { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
  723. { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
  724. { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
  725. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
  726. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
  727. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
  728. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
  729. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
  730. { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
  731. { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
  732. { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
  733. { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
  734. { .type = S3C_IRQTYPE_NONE, }, /* reserved */
  735. { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
  736. { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
  737. { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
  738. { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
  739. { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
  740. { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
  741. { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
  742. { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
  743. { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
  744. { .type = S3C_IRQTYPE_NONE, },
  745. { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
  746. { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
  747. };
  748. static struct s3c_irq_data init_s3c2416subint[32] = {
  749. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
  750. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
  751. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
  752. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
  753. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
  754. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
  755. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
  756. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
  757. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
  758. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
  759. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
  760. { .type = S3C_IRQTYPE_NONE }, /* reserved */
  761. { .type = S3C_IRQTYPE_NONE }, /* reserved */
  762. { .type = S3C_IRQTYPE_NONE }, /* reserved */
  763. { .type = S3C_IRQTYPE_NONE }, /* reserved */
  764. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
  765. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
  766. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
  767. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
  768. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
  769. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
  770. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
  771. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
  772. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
  773. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
  774. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
  775. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
  776. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
  777. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
  778. };
  779. static struct s3c_irq_data init_s3c2416_second[32] = {
  780. { .type = S3C_IRQTYPE_EDGE }, /* 2D */
  781. { .type = S3C_IRQTYPE_NONE }, /* reserved */
  782. { .type = S3C_IRQTYPE_NONE }, /* reserved */
  783. { .type = S3C_IRQTYPE_NONE }, /* reserved */
  784. { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */
  785. { .type = S3C_IRQTYPE_NONE }, /* reserved */
  786. { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */
  787. };
  788. void __init s3c2416_init_irq(void)
  789. {
  790. pr_info("S3C2416: IRQ Support\n");
  791. #ifdef CONFIG_FIQ
  792. init_FIQ(FIQ_START);
  793. #endif
  794. s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL,
  795. 0x4a000000);
  796. if (IS_ERR(s3c_intc[0])) {
  797. pr_err("irq: could not create main interrupt controller\n");
  798. return;
  799. }
  800. s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
  801. s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2416subint[0],
  802. s3c_intc[0], 0x4a000018);
  803. s3c_intc[2] = s3c24xx_init_intc(NULL, &init_s3c2416_second[0],
  804. NULL, 0x4a000040);
  805. }
  806. #endif
  807. #ifdef CONFIG_CPU_S3C2440
  808. static struct s3c_irq_data init_s3c2440base[32] = {
  809. { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
  810. { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
  811. { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
  812. { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
  813. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
  814. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
  815. { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
  816. { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
  817. { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
  818. { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
  819. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
  820. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
  821. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
  822. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
  823. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
  824. { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
  825. { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
  826. { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
  827. { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
  828. { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
  829. { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
  830. { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
  831. { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
  832. { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
  833. { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
  834. { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
  835. { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
  836. { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
  837. { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
  838. { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
  839. { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
  840. { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
  841. };
  842. static struct s3c_irq_data init_s3c2440subint[32] = {
  843. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
  844. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
  845. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
  846. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
  847. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
  848. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
  849. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
  850. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
  851. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
  852. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
  853. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
  854. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
  855. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
  856. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
  857. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
  858. };
  859. void __init s3c2440_init_irq(void)
  860. {
  861. pr_info("S3C2440: IRQ Support\n");
  862. #ifdef CONFIG_FIQ
  863. init_FIQ(FIQ_START);
  864. #endif
  865. s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL,
  866. 0x4a000000);
  867. if (IS_ERR(s3c_intc[0])) {
  868. pr_err("irq: could not create main interrupt controller\n");
  869. return;
  870. }
  871. s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
  872. s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2440subint[0],
  873. s3c_intc[0], 0x4a000018);
  874. }
  875. #endif
  876. #ifdef CONFIG_CPU_S3C2442
  877. static struct s3c_irq_data init_s3c2442base[32] = {
  878. { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
  879. { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
  880. { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
  881. { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
  882. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
  883. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
  884. { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
  885. { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
  886. { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
  887. { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
  888. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
  889. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
  890. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
  891. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
  892. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
  893. { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
  894. { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
  895. { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
  896. { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
  897. { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
  898. { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
  899. { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
  900. { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
  901. { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
  902. { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
  903. { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
  904. { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
  905. { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
  906. { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
  907. { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
  908. { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
  909. { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
  910. };
  911. static struct s3c_irq_data init_s3c2442subint[32] = {
  912. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
  913. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
  914. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
  915. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
  916. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
  917. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
  918. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
  919. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
  920. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
  921. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
  922. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
  923. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
  924. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
  925. };
  926. void __init s3c2442_init_irq(void)
  927. {
  928. pr_info("S3C2442: IRQ Support\n");
  929. #ifdef CONFIG_FIQ
  930. init_FIQ(FIQ_START);
  931. #endif
  932. s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2442base[0], NULL,
  933. 0x4a000000);
  934. if (IS_ERR(s3c_intc[0])) {
  935. pr_err("irq: could not create main interrupt controller\n");
  936. return;
  937. }
  938. s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
  939. s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2442subint[0],
  940. s3c_intc[0], 0x4a000018);
  941. }
  942. #endif
  943. #ifdef CONFIG_CPU_S3C2443
  944. static struct s3c_irq_data init_s3c2443base[32] = {
  945. { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
  946. { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
  947. { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
  948. { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
  949. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
  950. { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
  951. { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
  952. { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
  953. { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
  954. { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
  955. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
  956. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
  957. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
  958. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
  959. { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
  960. { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
  961. { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
  962. { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
  963. { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
  964. { .type = S3C_IRQTYPE_EDGE, }, /* CFON */
  965. { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
  966. { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
  967. { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
  968. { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
  969. { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
  970. { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
  971. { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
  972. { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
  973. { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
  974. { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
  975. { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
  976. { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
  977. };
  978. static struct s3c_irq_data init_s3c2443subint[32] = {
  979. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
  980. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
  981. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
  982. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
  983. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
  984. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
  985. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
  986. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
  987. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
  988. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
  989. { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
  990. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
  991. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
  992. { .type = S3C_IRQTYPE_NONE }, /* reserved */
  993. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */
  994. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
  995. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
  996. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
  997. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
  998. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
  999. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
  1000. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
  1001. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
  1002. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
  1003. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
  1004. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
  1005. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
  1006. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
  1007. { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
  1008. };
  1009. void __init s3c2443_init_irq(void)
  1010. {
  1011. pr_info("S3C2443: IRQ Support\n");
  1012. #ifdef CONFIG_FIQ
  1013. init_FIQ(FIQ_START);
  1014. #endif
  1015. s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL,
  1016. 0x4a000000);
  1017. if (IS_ERR(s3c_intc[0])) {
  1018. pr_err("irq: could not create main interrupt controller\n");
  1019. return;
  1020. }
  1021. s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
  1022. s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2443subint[0],
  1023. s3c_intc[0], 0x4a000018);
  1024. }
  1025. #endif
  1026. #ifdef CONFIG_OF
  1027. static int s3c24xx_irq_map_of(struct irq_domain *h, unsigned int virq,
  1028. irq_hw_number_t hw)
  1029. {
  1030. unsigned int ctrl_num = hw / 32;
  1031. unsigned int intc_hw = hw % 32;
  1032. struct s3c_irq_intc *intc = s3c_intc[ctrl_num];
  1033. struct s3c_irq_intc *parent_intc = intc->parent;
  1034. struct s3c_irq_data *irq_data = &intc->irqs[intc_hw];
  1035. /* attach controller pointer to irq_data */
  1036. irq_data->intc = intc;
  1037. irq_data->offset = intc_hw;
  1038. if (!parent_intc)
  1039. irq_set_chip_and_handler(virq, &s3c_irq_chip, handle_edge_irq);
  1040. else
  1041. irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
  1042. handle_edge_irq);
  1043. irq_set_chip_data(virq, irq_data);
  1044. set_irq_flags(virq, IRQF_VALID);
  1045. return 0;
  1046. }
  1047. /* Translate our of irq notation
  1048. * format: <ctrl_num ctrl_irq parent_irq type>
  1049. */
  1050. static int s3c24xx_irq_xlate_of(struct irq_domain *d, struct device_node *n,
  1051. const u32 *intspec, unsigned int intsize,
  1052. irq_hw_number_t *out_hwirq, unsigned int *out_type)
  1053. {
  1054. struct s3c_irq_intc *intc;
  1055. struct s3c_irq_intc *parent_intc;
  1056. struct s3c_irq_data *irq_data;
  1057. struct s3c_irq_data *parent_irq_data;
  1058. int irqno;
  1059. if (WARN_ON(intsize < 4))
  1060. return -EINVAL;
  1061. if (intspec[0] > 2 || !s3c_intc[intspec[0]]) {
  1062. pr_err("controller number %d invalid\n", intspec[0]);
  1063. return -EINVAL;
  1064. }
  1065. intc = s3c_intc[intspec[0]];
  1066. *out_hwirq = intspec[0] * 32 + intspec[2];
  1067. *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
  1068. parent_intc = intc->parent;
  1069. if (parent_intc) {
  1070. irq_data = &intc->irqs[intspec[2]];
  1071. irq_data->parent_irq = intspec[1];
  1072. parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
  1073. parent_irq_data->sub_intc = intc;
  1074. parent_irq_data->sub_bits |= (1UL << intspec[2]);
  1075. /* parent_intc is always s3c_intc[0], so no offset */
  1076. irqno = irq_create_mapping(parent_intc->domain, intspec[1]);
  1077. if (irqno < 0) {
  1078. pr_err("irq: could not map parent interrupt\n");
  1079. return irqno;
  1080. }
  1081. irq_set_chained_handler(irqno, s3c_irq_demux);
  1082. }
  1083. return 0;
  1084. }
  1085. static struct irq_domain_ops s3c24xx_irq_ops_of = {
  1086. .map = s3c24xx_irq_map_of,
  1087. .xlate = s3c24xx_irq_xlate_of,
  1088. };
  1089. struct s3c24xx_irq_of_ctrl {
  1090. char *name;
  1091. unsigned long offset;
  1092. struct s3c_irq_intc **handle;
  1093. struct s3c_irq_intc **parent;
  1094. struct irq_domain_ops *ops;
  1095. };
  1096. static int __init s3c_init_intc_of(struct device_node *np,
  1097. struct device_node *interrupt_parent,
  1098. struct s3c24xx_irq_of_ctrl *s3c_ctrl, int num_ctrl)
  1099. {
  1100. struct s3c_irq_intc *intc;
  1101. struct s3c24xx_irq_of_ctrl *ctrl;
  1102. struct irq_domain *domain;
  1103. void __iomem *reg_base;
  1104. int i;
  1105. reg_base = of_iomap(np, 0);
  1106. if (!reg_base) {
  1107. pr_err("irq-s3c24xx: could not map irq registers\n");
  1108. return -EINVAL;
  1109. }
  1110. domain = irq_domain_add_linear(np, num_ctrl * 32,
  1111. &s3c24xx_irq_ops_of, NULL);
  1112. if (!domain) {
  1113. pr_err("irq: could not create irq-domain\n");
  1114. return -EINVAL;
  1115. }
  1116. for (i = 0; i < num_ctrl; i++) {
  1117. ctrl = &s3c_ctrl[i];
  1118. pr_debug("irq: found controller %s\n", ctrl->name);
  1119. intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
  1120. if (!intc)
  1121. return -ENOMEM;
  1122. intc->domain = domain;
  1123. intc->irqs = kzalloc(sizeof(struct s3c_irq_data) * 32,
  1124. GFP_KERNEL);
  1125. if (!intc->irqs) {
  1126. kfree(intc);
  1127. return -ENOMEM;
  1128. }
  1129. if (ctrl->parent) {
  1130. intc->reg_pending = reg_base + ctrl->offset;
  1131. intc->reg_mask = reg_base + ctrl->offset + 0x4;
  1132. if (*(ctrl->parent)) {
  1133. intc->parent = *(ctrl->parent);
  1134. } else {
  1135. pr_warn("irq: parent of %s missing\n",
  1136. ctrl->name);
  1137. kfree(intc->irqs);
  1138. kfree(intc);
  1139. continue;
  1140. }
  1141. } else {
  1142. intc->reg_pending = reg_base + ctrl->offset;
  1143. intc->reg_mask = reg_base + ctrl->offset + 0x08;
  1144. intc->reg_intpnd = reg_base + ctrl->offset + 0x10;
  1145. }
  1146. s3c24xx_clear_intc(intc);
  1147. s3c_intc[i] = intc;
  1148. }
  1149. set_handle_irq(s3c24xx_handle_irq);
  1150. return 0;
  1151. }
  1152. static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = {
  1153. {
  1154. .name = "intc",
  1155. .offset = 0,
  1156. }, {
  1157. .name = "subintc",
  1158. .offset = 0x18,
  1159. .parent = &s3c_intc[0],
  1160. }
  1161. };
  1162. int __init s3c2410_init_intc_of(struct device_node *np,
  1163. struct device_node *interrupt_parent,
  1164. struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
  1165. {
  1166. return s3c_init_intc_of(np, interrupt_parent,
  1167. s3c2410_ctrl, ARRAY_SIZE(s3c2410_ctrl));
  1168. }
  1169. IRQCHIP_DECLARE(s3c2410_irq, "samsung,s3c2410-irq", s3c2410_init_intc_of);
  1170. static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = {
  1171. {
  1172. .name = "intc",
  1173. .offset = 0,
  1174. }, {
  1175. .name = "subintc",
  1176. .offset = 0x18,
  1177. .parent = &s3c_intc[0],
  1178. }, {
  1179. .name = "intc2",
  1180. .offset = 0x40,
  1181. }
  1182. };
  1183. int __init s3c2416_init_intc_of(struct device_node *np,
  1184. struct device_node *interrupt_parent,
  1185. struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
  1186. {
  1187. return s3c_init_intc_of(np, interrupt_parent,
  1188. s3c2416_ctrl, ARRAY_SIZE(s3c2416_ctrl));
  1189. }
  1190. IRQCHIP_DECLARE(s3c2416_irq, "samsung,s3c2416-irq", s3c2416_init_intc_of);
  1191. #endif