aspeed_intc.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /*
  2. * ASPEED INTC Controller
  3. *
  4. * Copyright (C) 2024 ASPEED Technology Inc.
  5. *
  6. * SPDX-License-Identifier: GPL-2.0-or-later
  7. */
  8. #include "qemu/osdep.h"
  9. #include "hw/intc/aspeed_intc.h"
  10. #include "hw/irq.h"
  11. #include "qemu/log.h"
  12. #include "trace.h"
  13. #include "hw/registerfields.h"
  14. #include "qapi/error.h"
  15. /*
  16. * INTC Registers
  17. *
  18. * values below are offset by - 0x1000 from datasheet
  19. * because its memory region is start at 0x1000
  20. *
  21. */
  22. REG32(GICINT128_EN, 0x000)
  23. REG32(GICINT128_STATUS, 0x004)
  24. REG32(GICINT129_EN, 0x100)
  25. REG32(GICINT129_STATUS, 0x104)
  26. REG32(GICINT130_EN, 0x200)
  27. REG32(GICINT130_STATUS, 0x204)
  28. REG32(GICINT131_EN, 0x300)
  29. REG32(GICINT131_STATUS, 0x304)
  30. REG32(GICINT132_EN, 0x400)
  31. REG32(GICINT132_STATUS, 0x404)
  32. REG32(GICINT133_EN, 0x500)
  33. REG32(GICINT133_STATUS, 0x504)
  34. REG32(GICINT134_EN, 0x600)
  35. REG32(GICINT134_STATUS, 0x604)
  36. REG32(GICINT135_EN, 0x700)
  37. REG32(GICINT135_STATUS, 0x704)
  38. REG32(GICINT136_EN, 0x800)
  39. REG32(GICINT136_STATUS, 0x804)
  40. REG32(GICINT192_201_EN, 0xB00)
  41. REG32(GICINT192_201_STATUS, 0xB04)
  42. /*
  43. * INTCIO Registers
  44. *
  45. * values below are offset by - 0x100 from datasheet
  46. * because its memory region is start at 0x100
  47. *
  48. */
  49. REG32(GICINT192_EN, 0x00)
  50. REG32(GICINT192_STATUS, 0x04)
  51. REG32(GICINT193_EN, 0x10)
  52. REG32(GICINT193_STATUS, 0x14)
  53. REG32(GICINT194_EN, 0x20)
  54. REG32(GICINT194_STATUS, 0x24)
  55. REG32(GICINT195_EN, 0x30)
  56. REG32(GICINT195_STATUS, 0x34)
  57. REG32(GICINT196_EN, 0x40)
  58. REG32(GICINT196_STATUS, 0x44)
  59. REG32(GICINT197_EN, 0x50)
  60. REG32(GICINT197_STATUS, 0x54)
  61. static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic,
  62. uint32_t reg)
  63. {
  64. int i;
  65. for (i = 0; i < aic->irq_table_count; i++) {
  66. if (aic->irq_table[i].enable_reg == reg ||
  67. aic->irq_table[i].status_reg == reg) {
  68. return &aic->irq_table[i];
  69. }
  70. }
  71. /*
  72. * Invalid reg.
  73. */
  74. g_assert_not_reached();
  75. }
  76. /*
  77. * Update the state of an interrupt controller pin by setting
  78. * the specified output pin to the given level.
  79. * The input pin index should be between 0 and the number of input pins.
  80. * The output pin index should be between 0 and the number of output pins.
  81. */
  82. static void aspeed_intc_update(AspeedINTCState *s, int inpin_idx,
  83. int outpin_idx, int level)
  84. {
  85. AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
  86. const char *name = object_get_typename(OBJECT(s));
  87. assert((outpin_idx < aic->num_outpins) && (inpin_idx < aic->num_inpins));
  88. trace_aspeed_intc_update_irq(name, inpin_idx, outpin_idx, level);
  89. qemu_set_irq(s->output_pins[outpin_idx], level);
  90. }
  91. static void aspeed_intc_set_irq_handler(AspeedINTCState *s,
  92. const AspeedINTCIRQ *intc_irq,
  93. uint32_t select)
  94. {
  95. const char *name = object_get_typename(OBJECT(s));
  96. uint32_t status_reg;
  97. int outpin_idx;
  98. int inpin_idx;
  99. status_reg = intc_irq->status_reg;
  100. outpin_idx = intc_irq->outpin_idx;
  101. inpin_idx = intc_irq->inpin_idx;
  102. if ((s->mask[inpin_idx] & select) || (s->regs[status_reg] & select)) {
  103. /*
  104. * a. mask is not 0 means in ISR mode
  105. * sources interrupt routine are executing.
  106. * b. status register value is not 0 means previous
  107. * source interrupt does not be executed, yet.
  108. *
  109. * save source interrupt to pending variable.
  110. */
  111. s->pending[inpin_idx] |= select;
  112. trace_aspeed_intc_pending_irq(name, inpin_idx, s->pending[inpin_idx]);
  113. } else {
  114. /*
  115. * notify firmware which source interrupt are coming
  116. * by setting status register
  117. */
  118. s->regs[status_reg] = select;
  119. trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
  120. s->regs[status_reg]);
  121. aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
  122. }
  123. }
  124. static void aspeed_intc_set_irq_handler_multi_outpins(AspeedINTCState *s,
  125. const AspeedINTCIRQ *intc_irq, uint32_t select)
  126. {
  127. const char *name = object_get_typename(OBJECT(s));
  128. uint32_t status_reg;
  129. int num_outpins;
  130. int outpin_idx;
  131. int inpin_idx;
  132. int i;
  133. num_outpins = intc_irq->num_outpins;
  134. status_reg = intc_irq->status_reg;
  135. outpin_idx = intc_irq->outpin_idx;
  136. inpin_idx = intc_irq->inpin_idx;
  137. for (i = 0; i < num_outpins; i++) {
  138. if (select & BIT(i)) {
  139. if (s->mask[inpin_idx] & BIT(i) ||
  140. s->regs[status_reg] & BIT(i)) {
  141. /*
  142. * a. mask bit is not 0 means in ISR mode sources interrupt
  143. * routine are executing.
  144. * b. status bit is not 0 means previous source interrupt
  145. * does not be executed, yet.
  146. *
  147. * save source interrupt to pending bit.
  148. */
  149. s->pending[inpin_idx] |= BIT(i);
  150. trace_aspeed_intc_pending_irq(name, inpin_idx,
  151. s->pending[inpin_idx]);
  152. } else {
  153. /*
  154. * notify firmware which source interrupt are coming
  155. * by setting status bit
  156. */
  157. s->regs[status_reg] |= BIT(i);
  158. trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i,
  159. s->regs[status_reg]);
  160. aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1);
  161. }
  162. }
  163. }
  164. }
  165. /*
  166. * GICINT192_201 maps 1:10 to input IRQ 0 and output IRQs 0 to 9.
  167. * GICINT128 to GICINT136 map 1:1 to input IRQs 1 to 9 and output
  168. * IRQs 10 to 18. The value of input IRQ should be between 0 and
  169. * the number of input pins.
  170. */
  171. static void aspeed_intc_set_irq(void *opaque, int irq, int level)
  172. {
  173. AspeedINTCState *s = (AspeedINTCState *)opaque;
  174. AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
  175. const char *name = object_get_typename(OBJECT(s));
  176. const AspeedINTCIRQ *intc_irq;
  177. uint32_t select = 0;
  178. uint32_t enable;
  179. int num_outpins;
  180. int inpin_idx;
  181. int i;
  182. assert(irq < aic->num_inpins);
  183. intc_irq = &aic->irq_table[irq];
  184. num_outpins = intc_irq->num_outpins;
  185. inpin_idx = intc_irq->inpin_idx;
  186. trace_aspeed_intc_set_irq(name, inpin_idx, level);
  187. enable = s->enable[inpin_idx];
  188. if (!level) {
  189. return;
  190. }
  191. for (i = 0; i < aic->num_lines; i++) {
  192. if (s->orgates[inpin_idx].levels[i]) {
  193. if (enable & BIT(i)) {
  194. select |= BIT(i);
  195. }
  196. }
  197. }
  198. if (!select) {
  199. return;
  200. }
  201. trace_aspeed_intc_select(name, select);
  202. if (num_outpins > 1) {
  203. aspeed_intc_set_irq_handler_multi_outpins(s, intc_irq, select);
  204. } else {
  205. aspeed_intc_set_irq_handler(s, intc_irq, select);
  206. }
  207. }
  208. static void aspeed_intc_enable_handler(AspeedINTCState *s, hwaddr offset,
  209. uint64_t data)
  210. {
  211. AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
  212. const char *name = object_get_typename(OBJECT(s));
  213. const AspeedINTCIRQ *intc_irq;
  214. uint32_t reg = offset >> 2;
  215. uint32_t old_enable;
  216. uint32_t change;
  217. int inpin_idx;
  218. intc_irq = aspeed_intc_get_irq(aic, reg);
  219. inpin_idx = intc_irq->inpin_idx;
  220. assert(inpin_idx < aic->num_inpins);
  221. /*
  222. * The enable registers are used to enable source interrupts.
  223. * They also handle masking and unmasking of source interrupts
  224. * during the execution of the source ISR.
  225. */
  226. /* disable all source interrupt */
  227. if (!data && !s->enable[inpin_idx]) {
  228. s->regs[reg] = data;
  229. return;
  230. }
  231. old_enable = s->enable[inpin_idx];
  232. s->enable[inpin_idx] |= data;
  233. /* enable new source interrupt */
  234. if (old_enable != s->enable[inpin_idx]) {
  235. trace_aspeed_intc_enable(name, s->enable[inpin_idx]);
  236. s->regs[reg] = data;
  237. return;
  238. }
  239. /* mask and unmask source interrupt */
  240. change = s->regs[reg] ^ data;
  241. if (change & data) {
  242. s->mask[inpin_idx] &= ~change;
  243. trace_aspeed_intc_unmask(name, change, s->mask[inpin_idx]);
  244. } else {
  245. s->mask[inpin_idx] |= change;
  246. trace_aspeed_intc_mask(name, change, s->mask[inpin_idx]);
  247. }
  248. s->regs[reg] = data;
  249. }
  250. static void aspeed_intc_status_handler(AspeedINTCState *s, hwaddr offset,
  251. uint64_t data)
  252. {
  253. AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
  254. const char *name = object_get_typename(OBJECT(s));
  255. const AspeedINTCIRQ *intc_irq;
  256. uint32_t reg = offset >> 2;
  257. int outpin_idx;
  258. int inpin_idx;
  259. if (!data) {
  260. qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
  261. return;
  262. }
  263. intc_irq = aspeed_intc_get_irq(aic, reg);
  264. outpin_idx = intc_irq->outpin_idx;
  265. inpin_idx = intc_irq->inpin_idx;
  266. assert(inpin_idx < aic->num_inpins);
  267. /* clear status */
  268. s->regs[reg] &= ~data;
  269. /*
  270. * These status registers are used for notify sources ISR are executed.
  271. * If one source ISR is executed, it will clear one bit.
  272. * If it clear all bits, it means to initialize this register status
  273. * rather than sources ISR are executed.
  274. */
  275. if (data == 0xffffffff) {
  276. return;
  277. }
  278. /* All source ISR execution are done */
  279. if (!s->regs[reg]) {
  280. trace_aspeed_intc_all_isr_done(name, inpin_idx);
  281. if (s->pending[inpin_idx]) {
  282. /*
  283. * handle pending source interrupt
  284. * notify firmware which source interrupt are pending
  285. * by setting status register
  286. */
  287. s->regs[reg] = s->pending[inpin_idx];
  288. s->pending[inpin_idx] = 0;
  289. trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx,
  290. s->regs[reg]);
  291. aspeed_intc_update(s, inpin_idx, outpin_idx, 1);
  292. } else {
  293. /* clear irq */
  294. trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx, 0);
  295. aspeed_intc_update(s, inpin_idx, outpin_idx, 0);
  296. }
  297. }
  298. }
  299. static void aspeed_intc_status_handler_multi_outpins(AspeedINTCState *s,
  300. hwaddr offset, uint64_t data)
  301. {
  302. const char *name = object_get_typename(OBJECT(s));
  303. AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
  304. const AspeedINTCIRQ *intc_irq;
  305. uint32_t reg = offset >> 2;
  306. int num_outpins;
  307. int outpin_idx;
  308. int inpin_idx;
  309. int i;
  310. if (!data) {
  311. qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid data 0\n", __func__);
  312. return;
  313. }
  314. intc_irq = aspeed_intc_get_irq(aic, reg);
  315. num_outpins = intc_irq->num_outpins;
  316. outpin_idx = intc_irq->outpin_idx;
  317. inpin_idx = intc_irq->inpin_idx;
  318. assert(inpin_idx < aic->num_inpins);
  319. /* clear status */
  320. s->regs[reg] &= ~data;
  321. /*
  322. * The status registers are used for notify sources ISR are executed.
  323. * If one source ISR is executed, it will clear one bit.
  324. * If it clear all bits, it means to initialize this register status
  325. * rather than sources ISR are executed.
  326. */
  327. if (data == 0xffffffff) {
  328. return;
  329. }
  330. for (i = 0; i < num_outpins; i++) {
  331. /* All source ISR executions are done from a specific bit */
  332. if (data & BIT(i)) {
  333. trace_aspeed_intc_all_isr_done_bit(name, inpin_idx, i);
  334. if (s->pending[inpin_idx] & BIT(i)) {
  335. /*
  336. * Handle pending source interrupt.
  337. * Notify firmware which source interrupt is pending
  338. * by setting the status bit.
  339. */
  340. s->regs[reg] |= BIT(i);
  341. s->pending[inpin_idx] &= ~BIT(i);
  342. trace_aspeed_intc_trigger_irq(name, inpin_idx, outpin_idx + i,
  343. s->regs[reg]);
  344. aspeed_intc_update(s, inpin_idx, outpin_idx + i, 1);
  345. } else {
  346. /* clear irq for the specific bit */
  347. trace_aspeed_intc_clear_irq(name, inpin_idx, outpin_idx + i, 0);
  348. aspeed_intc_update(s, inpin_idx, outpin_idx + i, 0);
  349. }
  350. }
  351. }
  352. }
  353. static uint64_t aspeed_intc_read(void *opaque, hwaddr offset, unsigned int size)
  354. {
  355. AspeedINTCState *s = ASPEED_INTC(opaque);
  356. const char *name = object_get_typename(OBJECT(s));
  357. uint32_t reg = offset >> 2;
  358. uint32_t value = 0;
  359. value = s->regs[reg];
  360. trace_aspeed_intc_read(name, offset, size, value);
  361. return value;
  362. }
  363. static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
  364. unsigned size)
  365. {
  366. AspeedINTCState *s = ASPEED_INTC(opaque);
  367. const char *name = object_get_typename(OBJECT(s));
  368. uint32_t reg = offset >> 2;
  369. trace_aspeed_intc_write(name, offset, size, data);
  370. switch (reg) {
  371. case R_GICINT128_EN:
  372. case R_GICINT129_EN:
  373. case R_GICINT130_EN:
  374. case R_GICINT131_EN:
  375. case R_GICINT132_EN:
  376. case R_GICINT133_EN:
  377. case R_GICINT134_EN:
  378. case R_GICINT135_EN:
  379. case R_GICINT136_EN:
  380. case R_GICINT192_201_EN:
  381. aspeed_intc_enable_handler(s, offset, data);
  382. break;
  383. case R_GICINT128_STATUS:
  384. case R_GICINT129_STATUS:
  385. case R_GICINT130_STATUS:
  386. case R_GICINT131_STATUS:
  387. case R_GICINT132_STATUS:
  388. case R_GICINT133_STATUS:
  389. case R_GICINT134_STATUS:
  390. case R_GICINT135_STATUS:
  391. case R_GICINT136_STATUS:
  392. aspeed_intc_status_handler(s, offset, data);
  393. break;
  394. case R_GICINT192_201_STATUS:
  395. aspeed_intc_status_handler_multi_outpins(s, offset, data);
  396. break;
  397. default:
  398. s->regs[reg] = data;
  399. break;
  400. }
  401. return;
  402. }
  403. static uint64_t aspeed_intcio_read(void *opaque, hwaddr offset,
  404. unsigned int size)
  405. {
  406. AspeedINTCState *s = ASPEED_INTC(opaque);
  407. const char *name = object_get_typename(OBJECT(s));
  408. uint32_t reg = offset >> 2;
  409. uint32_t value = 0;
  410. value = s->regs[reg];
  411. trace_aspeed_intc_read(name, offset, size, value);
  412. return value;
  413. }
  414. static void aspeed_intcio_write(void *opaque, hwaddr offset, uint64_t data,
  415. unsigned size)
  416. {
  417. AspeedINTCState *s = ASPEED_INTC(opaque);
  418. const char *name = object_get_typename(OBJECT(s));
  419. uint32_t reg = offset >> 2;
  420. trace_aspeed_intc_write(name, offset, size, data);
  421. switch (reg) {
  422. case R_GICINT192_EN:
  423. case R_GICINT193_EN:
  424. case R_GICINT194_EN:
  425. case R_GICINT195_EN:
  426. case R_GICINT196_EN:
  427. case R_GICINT197_EN:
  428. aspeed_intc_enable_handler(s, offset, data);
  429. break;
  430. case R_GICINT192_STATUS:
  431. case R_GICINT193_STATUS:
  432. case R_GICINT194_STATUS:
  433. case R_GICINT195_STATUS:
  434. case R_GICINT196_STATUS:
  435. case R_GICINT197_STATUS:
  436. aspeed_intc_status_handler(s, offset, data);
  437. break;
  438. default:
  439. s->regs[reg] = data;
  440. break;
  441. }
  442. return;
  443. }
  444. static const MemoryRegionOps aspeed_intc_ops = {
  445. .read = aspeed_intc_read,
  446. .write = aspeed_intc_write,
  447. .endianness = DEVICE_LITTLE_ENDIAN,
  448. .valid = {
  449. .min_access_size = 4,
  450. .max_access_size = 4,
  451. }
  452. };
  453. static const MemoryRegionOps aspeed_intcio_ops = {
  454. .read = aspeed_intcio_read,
  455. .write = aspeed_intcio_write,
  456. .endianness = DEVICE_LITTLE_ENDIAN,
  457. .valid = {
  458. .min_access_size = 4,
  459. .max_access_size = 4,
  460. }
  461. };
  462. static void aspeed_intc_instance_init(Object *obj)
  463. {
  464. AspeedINTCState *s = ASPEED_INTC(obj);
  465. AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
  466. int i;
  467. assert(aic->num_inpins <= ASPEED_INTC_MAX_INPINS);
  468. for (i = 0; i < aic->num_inpins; i++) {
  469. object_initialize_child(obj, "intc-orgates[*]", &s->orgates[i],
  470. TYPE_OR_IRQ);
  471. object_property_set_int(OBJECT(&s->orgates[i]), "num-lines",
  472. aic->num_lines, &error_abort);
  473. }
  474. }
  475. static void aspeed_intc_reset(DeviceState *dev)
  476. {
  477. AspeedINTCState *s = ASPEED_INTC(dev);
  478. AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
  479. memset(s->regs, 0, aic->nr_regs << 2);
  480. memset(s->enable, 0, sizeof(s->enable));
  481. memset(s->mask, 0, sizeof(s->mask));
  482. memset(s->pending, 0, sizeof(s->pending));
  483. }
  484. static void aspeed_intc_realize(DeviceState *dev, Error **errp)
  485. {
  486. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  487. AspeedINTCState *s = ASPEED_INTC(dev);
  488. AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
  489. int i;
  490. memory_region_init(&s->iomem_container, OBJECT(s),
  491. TYPE_ASPEED_INTC ".container", aic->mem_size);
  492. sysbus_init_mmio(sbd, &s->iomem_container);
  493. s->regs = g_new(uint32_t, aic->nr_regs);
  494. memory_region_init_io(&s->iomem, OBJECT(s), aic->reg_ops, s,
  495. TYPE_ASPEED_INTC ".regs", aic->nr_regs << 2);
  496. memory_region_add_subregion(&s->iomem_container, aic->reg_offset,
  497. &s->iomem);
  498. qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_inpins);
  499. for (i = 0; i < aic->num_inpins; i++) {
  500. if (!qdev_realize(DEVICE(&s->orgates[i]), NULL, errp)) {
  501. return;
  502. }
  503. }
  504. for (i = 0; i < aic->num_outpins; i++) {
  505. sysbus_init_irq(sbd, &s->output_pins[i]);
  506. }
  507. }
  508. static void aspeed_intc_unrealize(DeviceState *dev)
  509. {
  510. AspeedINTCState *s = ASPEED_INTC(dev);
  511. g_free(s->regs);
  512. s->regs = NULL;
  513. }
  514. static void aspeed_intc_class_init(ObjectClass *klass, void *data)
  515. {
  516. DeviceClass *dc = DEVICE_CLASS(klass);
  517. AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
  518. dc->desc = "ASPEED INTC Controller";
  519. dc->realize = aspeed_intc_realize;
  520. dc->unrealize = aspeed_intc_unrealize;
  521. device_class_set_legacy_reset(dc, aspeed_intc_reset);
  522. dc->vmsd = NULL;
  523. aic->reg_ops = &aspeed_intc_ops;
  524. }
  525. static const TypeInfo aspeed_intc_info = {
  526. .name = TYPE_ASPEED_INTC,
  527. .parent = TYPE_SYS_BUS_DEVICE,
  528. .instance_init = aspeed_intc_instance_init,
  529. .instance_size = sizeof(AspeedINTCState),
  530. .class_init = aspeed_intc_class_init,
  531. .class_size = sizeof(AspeedINTCClass),
  532. .abstract = true,
  533. };
  534. static AspeedINTCIRQ aspeed_2700_intc_irqs[ASPEED_INTC_MAX_INPINS] = {
  535. {0, 0, 10, R_GICINT192_201_EN, R_GICINT192_201_STATUS},
  536. {1, 10, 1, R_GICINT128_EN, R_GICINT128_STATUS},
  537. {2, 11, 1, R_GICINT129_EN, R_GICINT129_STATUS},
  538. {3, 12, 1, R_GICINT130_EN, R_GICINT130_STATUS},
  539. {4, 13, 1, R_GICINT131_EN, R_GICINT131_STATUS},
  540. {5, 14, 1, R_GICINT132_EN, R_GICINT132_STATUS},
  541. {6, 15, 1, R_GICINT133_EN, R_GICINT133_STATUS},
  542. {7, 16, 1, R_GICINT134_EN, R_GICINT134_STATUS},
  543. {8, 17, 1, R_GICINT135_EN, R_GICINT135_STATUS},
  544. {9, 18, 1, R_GICINT136_EN, R_GICINT136_STATUS},
  545. };
  546. static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data)
  547. {
  548. DeviceClass *dc = DEVICE_CLASS(klass);
  549. AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
  550. dc->desc = "ASPEED 2700 INTC Controller";
  551. aic->num_lines = 32;
  552. aic->num_inpins = 10;
  553. aic->num_outpins = 19;
  554. aic->mem_size = 0x4000;
  555. aic->nr_regs = 0xB08 >> 2;
  556. aic->reg_offset = 0x1000;
  557. aic->irq_table = aspeed_2700_intc_irqs;
  558. aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intc_irqs);
  559. }
  560. static const TypeInfo aspeed_2700_intc_info = {
  561. .name = TYPE_ASPEED_2700_INTC,
  562. .parent = TYPE_ASPEED_INTC,
  563. .class_init = aspeed_2700_intc_class_init,
  564. };
  565. static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = {
  566. {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS},
  567. {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS},
  568. {2, 2, 1, R_GICINT194_EN, R_GICINT194_STATUS},
  569. {3, 3, 1, R_GICINT195_EN, R_GICINT195_STATUS},
  570. {4, 4, 1, R_GICINT196_EN, R_GICINT196_STATUS},
  571. {5, 5, 1, R_GICINT197_EN, R_GICINT197_STATUS},
  572. };
  573. static void aspeed_2700_intcio_class_init(ObjectClass *klass, void *data)
  574. {
  575. DeviceClass *dc = DEVICE_CLASS(klass);
  576. AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
  577. dc->desc = "ASPEED 2700 INTC IO Controller";
  578. aic->num_lines = 32;
  579. aic->num_inpins = 6;
  580. aic->num_outpins = 6;
  581. aic->mem_size = 0x400;
  582. aic->nr_regs = 0x58 >> 2;
  583. aic->reg_offset = 0x100;
  584. aic->reg_ops = &aspeed_intcio_ops;
  585. aic->irq_table = aspeed_2700_intcio_irqs;
  586. aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcio_irqs);
  587. }
  588. static const TypeInfo aspeed_2700_intcio_info = {
  589. .name = TYPE_ASPEED_2700_INTCIO,
  590. .parent = TYPE_ASPEED_INTC,
  591. .class_init = aspeed_2700_intcio_class_init,
  592. };
  593. static void aspeed_intc_register_types(void)
  594. {
  595. type_register_static(&aspeed_intc_info);
  596. type_register_static(&aspeed_2700_intc_info);
  597. type_register_static(&aspeed_2700_intcio_info);
  598. }
  599. type_init(aspeed_intc_register_types);