omap_intc.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. /*
  2. * TI OMAP interrupt controller emulation.
  3. *
  4. * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org>
  5. * Copyright (C) 2007-2008 Nokia Corporation
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 or
  10. * (at your option) version 3 of the License.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "qemu/osdep.h"
  21. #include "hw/irq.h"
  22. #include "hw/qdev-properties.h"
  23. #include "hw/arm/omap.h"
  24. #include "hw/sysbus.h"
  25. #include "qemu/error-report.h"
  26. #include "qemu/module.h"
  27. #include "qapi/error.h"
  28. /* Interrupt Handlers */
  29. struct omap_intr_handler_bank_s {
  30. uint32_t irqs;
  31. uint32_t inputs;
  32. uint32_t mask;
  33. uint32_t fiq;
  34. uint32_t sens_edge;
  35. uint32_t swi;
  36. unsigned char priority[32];
  37. };
  38. #define TYPE_OMAP_INTC "common-omap-intc"
  39. #define OMAP_INTC(obj) \
  40. OBJECT_CHECK(struct omap_intr_handler_s, (obj), TYPE_OMAP_INTC)
  41. struct omap_intr_handler_s {
  42. SysBusDevice parent_obj;
  43. qemu_irq *pins;
  44. qemu_irq parent_intr[2];
  45. MemoryRegion mmio;
  46. void *iclk;
  47. void *fclk;
  48. unsigned char nbanks;
  49. int level_only;
  50. uint32_t size;
  51. uint8_t revision;
  52. /* state */
  53. uint32_t new_agr[2];
  54. int sir_intr[2];
  55. int autoidle;
  56. uint32_t mask;
  57. struct omap_intr_handler_bank_s bank[3];
  58. };
  59. static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
  60. {
  61. int i, j, sir_intr, p_intr, p;
  62. uint32_t level;
  63. sir_intr = 0;
  64. p_intr = 255;
  65. /* Find the interrupt line with the highest dynamic priority.
  66. * Note: 0 denotes the hightest priority.
  67. * If all interrupts have the same priority, the default order is IRQ_N,
  68. * IRQ_N-1,...,IRQ_0. */
  69. for (j = 0; j < s->nbanks; ++j) {
  70. level = s->bank[j].irqs & ~s->bank[j].mask &
  71. (is_fiq ? s->bank[j].fiq : ~s->bank[j].fiq);
  72. while (level != 0) {
  73. i = ctz32(level);
  74. p = s->bank[j].priority[i];
  75. if (p <= p_intr) {
  76. p_intr = p;
  77. sir_intr = 32 * j + i;
  78. }
  79. level &= level - 1;
  80. }
  81. }
  82. s->sir_intr[is_fiq] = sir_intr;
  83. }
  84. static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
  85. {
  86. int i;
  87. uint32_t has_intr = 0;
  88. for (i = 0; i < s->nbanks; ++i)
  89. has_intr |= s->bank[i].irqs & ~s->bank[i].mask &
  90. (is_fiq ? s->bank[i].fiq : ~s->bank[i].fiq);
  91. if (s->new_agr[is_fiq] & has_intr & s->mask) {
  92. s->new_agr[is_fiq] = 0;
  93. omap_inth_sir_update(s, is_fiq);
  94. qemu_set_irq(s->parent_intr[is_fiq], 1);
  95. }
  96. }
  97. #define INT_FALLING_EDGE 0
  98. #define INT_LOW_LEVEL 1
  99. static void omap_set_intr(void *opaque, int irq, int req)
  100. {
  101. struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
  102. uint32_t rise;
  103. struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
  104. int n = irq & 31;
  105. if (req) {
  106. rise = ~bank->irqs & (1 << n);
  107. if (~bank->sens_edge & (1 << n))
  108. rise &= ~bank->inputs;
  109. bank->inputs |= (1 << n);
  110. if (rise) {
  111. bank->irqs |= rise;
  112. omap_inth_update(ih, 0);
  113. omap_inth_update(ih, 1);
  114. }
  115. } else {
  116. rise = bank->sens_edge & bank->irqs & (1 << n);
  117. bank->irqs &= ~rise;
  118. bank->inputs &= ~(1 << n);
  119. }
  120. }
  121. /* Simplified version with no edge detection */
  122. static void omap_set_intr_noedge(void *opaque, int irq, int req)
  123. {
  124. struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
  125. uint32_t rise;
  126. struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
  127. int n = irq & 31;
  128. if (req) {
  129. rise = ~bank->inputs & (1 << n);
  130. if (rise) {
  131. bank->irqs |= bank->inputs |= rise;
  132. omap_inth_update(ih, 0);
  133. omap_inth_update(ih, 1);
  134. }
  135. } else
  136. bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi;
  137. }
  138. static uint64_t omap_inth_read(void *opaque, hwaddr addr,
  139. unsigned size)
  140. {
  141. struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
  142. int i, offset = addr;
  143. int bank_no = offset >> 8;
  144. int line_no;
  145. struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
  146. offset &= 0xff;
  147. switch (offset) {
  148. case 0x00: /* ITR */
  149. return bank->irqs;
  150. case 0x04: /* MIR */
  151. return bank->mask;
  152. case 0x10: /* SIR_IRQ_CODE */
  153. case 0x14: /* SIR_FIQ_CODE */
  154. if (bank_no != 0)
  155. break;
  156. line_no = s->sir_intr[(offset - 0x10) >> 2];
  157. bank = &s->bank[line_no >> 5];
  158. i = line_no & 31;
  159. if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE)
  160. bank->irqs &= ~(1 << i);
  161. return line_no;
  162. case 0x18: /* CONTROL_REG */
  163. if (bank_no != 0)
  164. break;
  165. return 0;
  166. case 0x1c: /* ILR0 */
  167. case 0x20: /* ILR1 */
  168. case 0x24: /* ILR2 */
  169. case 0x28: /* ILR3 */
  170. case 0x2c: /* ILR4 */
  171. case 0x30: /* ILR5 */
  172. case 0x34: /* ILR6 */
  173. case 0x38: /* ILR7 */
  174. case 0x3c: /* ILR8 */
  175. case 0x40: /* ILR9 */
  176. case 0x44: /* ILR10 */
  177. case 0x48: /* ILR11 */
  178. case 0x4c: /* ILR12 */
  179. case 0x50: /* ILR13 */
  180. case 0x54: /* ILR14 */
  181. case 0x58: /* ILR15 */
  182. case 0x5c: /* ILR16 */
  183. case 0x60: /* ILR17 */
  184. case 0x64: /* ILR18 */
  185. case 0x68: /* ILR19 */
  186. case 0x6c: /* ILR20 */
  187. case 0x70: /* ILR21 */
  188. case 0x74: /* ILR22 */
  189. case 0x78: /* ILR23 */
  190. case 0x7c: /* ILR24 */
  191. case 0x80: /* ILR25 */
  192. case 0x84: /* ILR26 */
  193. case 0x88: /* ILR27 */
  194. case 0x8c: /* ILR28 */
  195. case 0x90: /* ILR29 */
  196. case 0x94: /* ILR30 */
  197. case 0x98: /* ILR31 */
  198. i = (offset - 0x1c) >> 2;
  199. return (bank->priority[i] << 2) |
  200. (((bank->sens_edge >> i) & 1) << 1) |
  201. ((bank->fiq >> i) & 1);
  202. case 0x9c: /* ISR */
  203. return 0x00000000;
  204. }
  205. OMAP_BAD_REG(addr);
  206. return 0;
  207. }
  208. static void omap_inth_write(void *opaque, hwaddr addr,
  209. uint64_t value, unsigned size)
  210. {
  211. struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
  212. int i, offset = addr;
  213. int bank_no = offset >> 8;
  214. struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
  215. offset &= 0xff;
  216. switch (offset) {
  217. case 0x00: /* ITR */
  218. /* Important: ignore the clearing if the IRQ is level-triggered and
  219. the input bit is 1 */
  220. bank->irqs &= value | (bank->inputs & bank->sens_edge);
  221. return;
  222. case 0x04: /* MIR */
  223. bank->mask = value;
  224. omap_inth_update(s, 0);
  225. omap_inth_update(s, 1);
  226. return;
  227. case 0x10: /* SIR_IRQ_CODE */
  228. case 0x14: /* SIR_FIQ_CODE */
  229. OMAP_RO_REG(addr);
  230. break;
  231. case 0x18: /* CONTROL_REG */
  232. if (bank_no != 0)
  233. break;
  234. if (value & 2) {
  235. qemu_set_irq(s->parent_intr[1], 0);
  236. s->new_agr[1] = ~0;
  237. omap_inth_update(s, 1);
  238. }
  239. if (value & 1) {
  240. qemu_set_irq(s->parent_intr[0], 0);
  241. s->new_agr[0] = ~0;
  242. omap_inth_update(s, 0);
  243. }
  244. return;
  245. case 0x1c: /* ILR0 */
  246. case 0x20: /* ILR1 */
  247. case 0x24: /* ILR2 */
  248. case 0x28: /* ILR3 */
  249. case 0x2c: /* ILR4 */
  250. case 0x30: /* ILR5 */
  251. case 0x34: /* ILR6 */
  252. case 0x38: /* ILR7 */
  253. case 0x3c: /* ILR8 */
  254. case 0x40: /* ILR9 */
  255. case 0x44: /* ILR10 */
  256. case 0x48: /* ILR11 */
  257. case 0x4c: /* ILR12 */
  258. case 0x50: /* ILR13 */
  259. case 0x54: /* ILR14 */
  260. case 0x58: /* ILR15 */
  261. case 0x5c: /* ILR16 */
  262. case 0x60: /* ILR17 */
  263. case 0x64: /* ILR18 */
  264. case 0x68: /* ILR19 */
  265. case 0x6c: /* ILR20 */
  266. case 0x70: /* ILR21 */
  267. case 0x74: /* ILR22 */
  268. case 0x78: /* ILR23 */
  269. case 0x7c: /* ILR24 */
  270. case 0x80: /* ILR25 */
  271. case 0x84: /* ILR26 */
  272. case 0x88: /* ILR27 */
  273. case 0x8c: /* ILR28 */
  274. case 0x90: /* ILR29 */
  275. case 0x94: /* ILR30 */
  276. case 0x98: /* ILR31 */
  277. i = (offset - 0x1c) >> 2;
  278. bank->priority[i] = (value >> 2) & 0x1f;
  279. bank->sens_edge &= ~(1 << i);
  280. bank->sens_edge |= ((value >> 1) & 1) << i;
  281. bank->fiq &= ~(1 << i);
  282. bank->fiq |= (value & 1) << i;
  283. return;
  284. case 0x9c: /* ISR */
  285. for (i = 0; i < 32; i ++)
  286. if (value & (1 << i)) {
  287. omap_set_intr(s, 32 * bank_no + i, 1);
  288. return;
  289. }
  290. return;
  291. }
  292. OMAP_BAD_REG(addr);
  293. }
  294. static const MemoryRegionOps omap_inth_mem_ops = {
  295. .read = omap_inth_read,
  296. .write = omap_inth_write,
  297. .endianness = DEVICE_NATIVE_ENDIAN,
  298. .valid = {
  299. .min_access_size = 4,
  300. .max_access_size = 4,
  301. },
  302. };
  303. static void omap_inth_reset(DeviceState *dev)
  304. {
  305. struct omap_intr_handler_s *s = OMAP_INTC(dev);
  306. int i;
  307. for (i = 0; i < s->nbanks; ++i){
  308. s->bank[i].irqs = 0x00000000;
  309. s->bank[i].mask = 0xffffffff;
  310. s->bank[i].sens_edge = 0x00000000;
  311. s->bank[i].fiq = 0x00000000;
  312. s->bank[i].inputs = 0x00000000;
  313. s->bank[i].swi = 0x00000000;
  314. memset(s->bank[i].priority, 0, sizeof(s->bank[i].priority));
  315. if (s->level_only)
  316. s->bank[i].sens_edge = 0xffffffff;
  317. }
  318. s->new_agr[0] = ~0;
  319. s->new_agr[1] = ~0;
  320. s->sir_intr[0] = 0;
  321. s->sir_intr[1] = 0;
  322. s->autoidle = 0;
  323. s->mask = ~0;
  324. qemu_set_irq(s->parent_intr[0], 0);
  325. qemu_set_irq(s->parent_intr[1], 0);
  326. }
  327. static void omap_intc_init(Object *obj)
  328. {
  329. DeviceState *dev = DEVICE(obj);
  330. struct omap_intr_handler_s *s = OMAP_INTC(obj);
  331. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  332. s->nbanks = 1;
  333. sysbus_init_irq(sbd, &s->parent_intr[0]);
  334. sysbus_init_irq(sbd, &s->parent_intr[1]);
  335. qdev_init_gpio_in(dev, omap_set_intr, s->nbanks * 32);
  336. memory_region_init_io(&s->mmio, obj, &omap_inth_mem_ops, s,
  337. "omap-intc", s->size);
  338. sysbus_init_mmio(sbd, &s->mmio);
  339. }
  340. static void omap_intc_realize(DeviceState *dev, Error **errp)
  341. {
  342. struct omap_intr_handler_s *s = OMAP_INTC(dev);
  343. if (!s->iclk) {
  344. error_setg(errp, "omap-intc: clk not connected");
  345. }
  346. }
  347. static Property omap_intc_properties[] = {
  348. DEFINE_PROP_UINT32("size", struct omap_intr_handler_s, size, 0x100),
  349. DEFINE_PROP_PTR("clk", struct omap_intr_handler_s, iclk),
  350. DEFINE_PROP_END_OF_LIST(),
  351. };
  352. static void omap_intc_class_init(ObjectClass *klass, void *data)
  353. {
  354. DeviceClass *dc = DEVICE_CLASS(klass);
  355. dc->reset = omap_inth_reset;
  356. dc->props = omap_intc_properties;
  357. /* Reason: pointer property "clk" */
  358. dc->user_creatable = false;
  359. dc->realize = omap_intc_realize;
  360. }
  361. static const TypeInfo omap_intc_info = {
  362. .name = "omap-intc",
  363. .parent = TYPE_OMAP_INTC,
  364. .instance_init = omap_intc_init,
  365. .class_init = omap_intc_class_init,
  366. };
  367. static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
  368. unsigned size)
  369. {
  370. struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
  371. int offset = addr;
  372. int bank_no, line_no;
  373. struct omap_intr_handler_bank_s *bank = NULL;
  374. if ((offset & 0xf80) == 0x80) {
  375. bank_no = (offset & 0x60) >> 5;
  376. if (bank_no < s->nbanks) {
  377. offset &= ~0x60;
  378. bank = &s->bank[bank_no];
  379. } else {
  380. OMAP_BAD_REG(addr);
  381. return 0;
  382. }
  383. }
  384. switch (offset) {
  385. case 0x00: /* INTC_REVISION */
  386. return s->revision;
  387. case 0x10: /* INTC_SYSCONFIG */
  388. return (s->autoidle >> 2) & 1;
  389. case 0x14: /* INTC_SYSSTATUS */
  390. return 1; /* RESETDONE */
  391. case 0x40: /* INTC_SIR_IRQ */
  392. return s->sir_intr[0];
  393. case 0x44: /* INTC_SIR_FIQ */
  394. return s->sir_intr[1];
  395. case 0x48: /* INTC_CONTROL */
  396. return (!s->mask) << 2; /* GLOBALMASK */
  397. case 0x4c: /* INTC_PROTECTION */
  398. return 0;
  399. case 0x50: /* INTC_IDLE */
  400. return s->autoidle & 3;
  401. /* Per-bank registers */
  402. case 0x80: /* INTC_ITR */
  403. return bank->inputs;
  404. case 0x84: /* INTC_MIR */
  405. return bank->mask;
  406. case 0x88: /* INTC_MIR_CLEAR */
  407. case 0x8c: /* INTC_MIR_SET */
  408. return 0;
  409. case 0x90: /* INTC_ISR_SET */
  410. return bank->swi;
  411. case 0x94: /* INTC_ISR_CLEAR */
  412. return 0;
  413. case 0x98: /* INTC_PENDING_IRQ */
  414. return bank->irqs & ~bank->mask & ~bank->fiq;
  415. case 0x9c: /* INTC_PENDING_FIQ */
  416. return bank->irqs & ~bank->mask & bank->fiq;
  417. /* Per-line registers */
  418. case 0x100 ... 0x300: /* INTC_ILR */
  419. bank_no = (offset - 0x100) >> 7;
  420. if (bank_no > s->nbanks)
  421. break;
  422. bank = &s->bank[bank_no];
  423. line_no = (offset & 0x7f) >> 2;
  424. return (bank->priority[line_no] << 2) |
  425. ((bank->fiq >> line_no) & 1);
  426. }
  427. OMAP_BAD_REG(addr);
  428. return 0;
  429. }
  430. static void omap2_inth_write(void *opaque, hwaddr addr,
  431. uint64_t value, unsigned size)
  432. {
  433. struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
  434. int offset = addr;
  435. int bank_no, line_no;
  436. struct omap_intr_handler_bank_s *bank = NULL;
  437. if ((offset & 0xf80) == 0x80) {
  438. bank_no = (offset & 0x60) >> 5;
  439. if (bank_no < s->nbanks) {
  440. offset &= ~0x60;
  441. bank = &s->bank[bank_no];
  442. } else {
  443. OMAP_BAD_REG(addr);
  444. return;
  445. }
  446. }
  447. switch (offset) {
  448. case 0x10: /* INTC_SYSCONFIG */
  449. s->autoidle &= 4;
  450. s->autoidle |= (value & 1) << 2;
  451. if (value & 2) { /* SOFTRESET */
  452. omap_inth_reset(DEVICE(s));
  453. }
  454. return;
  455. case 0x48: /* INTC_CONTROL */
  456. s->mask = (value & 4) ? 0 : ~0; /* GLOBALMASK */
  457. if (value & 2) { /* NEWFIQAGR */
  458. qemu_set_irq(s->parent_intr[1], 0);
  459. s->new_agr[1] = ~0;
  460. omap_inth_update(s, 1);
  461. }
  462. if (value & 1) { /* NEWIRQAGR */
  463. qemu_set_irq(s->parent_intr[0], 0);
  464. s->new_agr[0] = ~0;
  465. omap_inth_update(s, 0);
  466. }
  467. return;
  468. case 0x4c: /* INTC_PROTECTION */
  469. /* TODO: Make a bitmap (or sizeof(char)map) of access privileges
  470. * for every register, see Chapter 3 and 4 for privileged mode. */
  471. if (value & 1)
  472. fprintf(stderr, "%s: protection mode enable attempt\n",
  473. __func__);
  474. return;
  475. case 0x50: /* INTC_IDLE */
  476. s->autoidle &= ~3;
  477. s->autoidle |= value & 3;
  478. return;
  479. /* Per-bank registers */
  480. case 0x84: /* INTC_MIR */
  481. bank->mask = value;
  482. omap_inth_update(s, 0);
  483. omap_inth_update(s, 1);
  484. return;
  485. case 0x88: /* INTC_MIR_CLEAR */
  486. bank->mask &= ~value;
  487. omap_inth_update(s, 0);
  488. omap_inth_update(s, 1);
  489. return;
  490. case 0x8c: /* INTC_MIR_SET */
  491. bank->mask |= value;
  492. return;
  493. case 0x90: /* INTC_ISR_SET */
  494. bank->irqs |= bank->swi |= value;
  495. omap_inth_update(s, 0);
  496. omap_inth_update(s, 1);
  497. return;
  498. case 0x94: /* INTC_ISR_CLEAR */
  499. bank->swi &= ~value;
  500. bank->irqs = bank->swi & bank->inputs;
  501. return;
  502. /* Per-line registers */
  503. case 0x100 ... 0x300: /* INTC_ILR */
  504. bank_no = (offset - 0x100) >> 7;
  505. if (bank_no > s->nbanks)
  506. break;
  507. bank = &s->bank[bank_no];
  508. line_no = (offset & 0x7f) >> 2;
  509. bank->priority[line_no] = (value >> 2) & 0x3f;
  510. bank->fiq &= ~(1 << line_no);
  511. bank->fiq |= (value & 1) << line_no;
  512. return;
  513. case 0x00: /* INTC_REVISION */
  514. case 0x14: /* INTC_SYSSTATUS */
  515. case 0x40: /* INTC_SIR_IRQ */
  516. case 0x44: /* INTC_SIR_FIQ */
  517. case 0x80: /* INTC_ITR */
  518. case 0x98: /* INTC_PENDING_IRQ */
  519. case 0x9c: /* INTC_PENDING_FIQ */
  520. OMAP_RO_REG(addr);
  521. return;
  522. }
  523. OMAP_BAD_REG(addr);
  524. }
  525. static const MemoryRegionOps omap2_inth_mem_ops = {
  526. .read = omap2_inth_read,
  527. .write = omap2_inth_write,
  528. .endianness = DEVICE_NATIVE_ENDIAN,
  529. .valid = {
  530. .min_access_size = 4,
  531. .max_access_size = 4,
  532. },
  533. };
  534. static void omap2_intc_init(Object *obj)
  535. {
  536. DeviceState *dev = DEVICE(obj);
  537. struct omap_intr_handler_s *s = OMAP_INTC(obj);
  538. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  539. s->level_only = 1;
  540. s->nbanks = 3;
  541. sysbus_init_irq(sbd, &s->parent_intr[0]);
  542. sysbus_init_irq(sbd, &s->parent_intr[1]);
  543. qdev_init_gpio_in(dev, omap_set_intr_noedge, s->nbanks * 32);
  544. memory_region_init_io(&s->mmio, obj, &omap2_inth_mem_ops, s,
  545. "omap2-intc", 0x1000);
  546. sysbus_init_mmio(sbd, &s->mmio);
  547. }
  548. static void omap2_intc_realize(DeviceState *dev, Error **errp)
  549. {
  550. struct omap_intr_handler_s *s = OMAP_INTC(dev);
  551. if (!s->iclk) {
  552. error_setg(errp, "omap2-intc: iclk not connected");
  553. return;
  554. }
  555. if (!s->fclk) {
  556. error_setg(errp, "omap2-intc: fclk not connected");
  557. return;
  558. }
  559. }
  560. static Property omap2_intc_properties[] = {
  561. DEFINE_PROP_UINT8("revision", struct omap_intr_handler_s,
  562. revision, 0x21),
  563. DEFINE_PROP_PTR("iclk", struct omap_intr_handler_s, iclk),
  564. DEFINE_PROP_PTR("fclk", struct omap_intr_handler_s, fclk),
  565. DEFINE_PROP_END_OF_LIST(),
  566. };
  567. static void omap2_intc_class_init(ObjectClass *klass, void *data)
  568. {
  569. DeviceClass *dc = DEVICE_CLASS(klass);
  570. dc->reset = omap_inth_reset;
  571. dc->props = omap2_intc_properties;
  572. /* Reason: pointer property "iclk", "fclk" */
  573. dc->user_creatable = false;
  574. dc->realize = omap2_intc_realize;
  575. }
  576. static const TypeInfo omap2_intc_info = {
  577. .name = "omap2-intc",
  578. .parent = TYPE_OMAP_INTC,
  579. .instance_init = omap2_intc_init,
  580. .class_init = omap2_intc_class_init,
  581. };
  582. static const TypeInfo omap_intc_type_info = {
  583. .name = TYPE_OMAP_INTC,
  584. .parent = TYPE_SYS_BUS_DEVICE,
  585. .instance_size = sizeof(struct omap_intr_handler_s),
  586. .abstract = true,
  587. };
  588. static void omap_intc_register_types(void)
  589. {
  590. type_register_static(&omap_intc_type_info);
  591. type_register_static(&omap_intc_info);
  592. type_register_static(&omap2_intc_info);
  593. }
  594. type_init(omap_intc_register_types)