2
0

aspeed_vic.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. * ASPEED Interrupt Controller (New)
  3. *
  4. * Andrew Jeffery <andrew@aj.id.au>
  5. *
  6. * Copyright 2015, 2016 IBM Corp.
  7. *
  8. * This code is licensed under the GPL version 2 or later. See
  9. * the COPYING file in the top-level directory.
  10. */
  11. /* The hardware exposes two register sets, a legacy set and a 'new' set. The
  12. * model implements the 'new' register set, and logs warnings on accesses to
  13. * the legacy IO space.
  14. *
  15. * The hardware uses 32bit registers to manage 51 IRQs, with low and high
  16. * registers for each conceptual register. The device model's implementation
  17. * uses 64bit data types to store both low and high register values (in the one
  18. * member), but must cope with access offset values in multiples of 4 passed to
  19. * the callbacks. As such the read() and write() implementations process the
  20. * provided offset to understand whether the access is requesting the lower or
  21. * upper 32 bits of the 64bit member.
  22. *
  23. * Additionally, the "Interrupt Enable", "Edge Status" and "Software Interrupt"
  24. * fields have separate "enable"/"status" and "clear" registers, where set bits
  25. * are written to one or the other to change state (avoiding a
  26. * read-modify-write sequence).
  27. */
  28. #include "qemu/osdep.h"
  29. #include "hw/intc/aspeed_vic.h"
  30. #include "hw/irq.h"
  31. #include "migration/vmstate.h"
  32. #include "qemu/bitops.h"
  33. #include "qemu/log.h"
  34. #include "qemu/module.h"
  35. #include "trace.h"
  36. #define AVIC_NEW_BASE_OFFSET 0x80
  37. #define AVIC_L_MASK 0xFFFFFFFFU
  38. #define AVIC_H_MASK 0x0007FFFFU
  39. #define AVIC_EVENT_W_MASK (0x78000ULL << 32)
  40. static void aspeed_vic_update(AspeedVICState *s)
  41. {
  42. uint64_t new = (s->raw & s->enable);
  43. uint64_t flags;
  44. flags = new & s->select;
  45. trace_aspeed_vic_update_fiq(!!flags);
  46. qemu_set_irq(s->fiq, !!flags);
  47. flags = new & ~s->select;
  48. trace_aspeed_vic_update_irq(!!flags);
  49. qemu_set_irq(s->irq, !!flags);
  50. }
  51. static void aspeed_vic_set_irq(void *opaque, int irq, int level)
  52. {
  53. uint64_t irq_mask;
  54. bool raise;
  55. AspeedVICState *s = (AspeedVICState *)opaque;
  56. if (irq > ASPEED_VIC_NR_IRQS) {
  57. qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
  58. __func__, irq);
  59. return;
  60. }
  61. trace_aspeed_vic_set_irq(irq, level);
  62. irq_mask = BIT(irq);
  63. if (s->sense & irq_mask) {
  64. /* level-triggered */
  65. if (s->event & irq_mask) {
  66. /* high-sensitive */
  67. raise = level;
  68. } else {
  69. /* low-sensitive */
  70. raise = !level;
  71. }
  72. s->raw = deposit64(s->raw, irq, 1, raise);
  73. } else {
  74. uint64_t old_level = s->level & irq_mask;
  75. /* edge-triggered */
  76. if (s->dual_edge & irq_mask) {
  77. raise = (!!old_level) != (!!level);
  78. } else {
  79. if (s->event & irq_mask) {
  80. /* rising-sensitive */
  81. raise = !old_level && level;
  82. } else {
  83. /* falling-sensitive */
  84. raise = old_level && !level;
  85. }
  86. }
  87. if (raise) {
  88. s->raw = deposit64(s->raw, irq, 1, raise);
  89. }
  90. }
  91. s->level = deposit64(s->level, irq, 1, level);
  92. aspeed_vic_update(s);
  93. }
  94. static uint64_t aspeed_vic_read(void *opaque, hwaddr offset, unsigned size)
  95. {
  96. AspeedVICState *s = (AspeedVICState *)opaque;
  97. hwaddr n_offset;
  98. uint64_t val;
  99. bool high;
  100. if (offset < AVIC_NEW_BASE_OFFSET) {
  101. high = false;
  102. n_offset = offset;
  103. } else {
  104. high = !!(offset & 0x4);
  105. n_offset = (offset & ~0x4);
  106. }
  107. switch (n_offset) {
  108. case 0x80: /* IRQ Status */
  109. case 0x00:
  110. val = s->raw & ~s->select & s->enable;
  111. break;
  112. case 0x88: /* FIQ Status */
  113. case 0x04:
  114. val = s->raw & s->select & s->enable;
  115. break;
  116. case 0x90: /* Raw Interrupt Status */
  117. case 0x08:
  118. val = s->raw;
  119. break;
  120. case 0x98: /* Interrupt Selection */
  121. case 0x0c:
  122. val = s->select;
  123. break;
  124. case 0xa0: /* Interrupt Enable */
  125. case 0x10:
  126. val = s->enable;
  127. break;
  128. case 0xb0: /* Software Interrupt */
  129. case 0x18:
  130. val = s->trigger;
  131. break;
  132. case 0xc0: /* Interrupt Sensitivity */
  133. case 0x24:
  134. val = s->sense;
  135. break;
  136. case 0xc8: /* Interrupt Both Edge Trigger Control */
  137. case 0x28:
  138. val = s->dual_edge;
  139. break;
  140. case 0xd0: /* Interrupt Event */
  141. case 0x2c:
  142. val = s->event;
  143. break;
  144. case 0xe0: /* Edge Triggered Interrupt Status */
  145. val = s->raw & ~s->sense;
  146. break;
  147. /* Illegal */
  148. case 0xa8: /* Interrupt Enable Clear */
  149. case 0xb8: /* Software Interrupt Clear */
  150. case 0xd8: /* Edge Triggered Interrupt Clear */
  151. qemu_log_mask(LOG_GUEST_ERROR,
  152. "%s: Read of write-only register with offset 0x%"
  153. HWADDR_PRIx "\n", __func__, offset);
  154. val = 0;
  155. break;
  156. default:
  157. qemu_log_mask(LOG_GUEST_ERROR,
  158. "%s: Bad register at offset 0x%" HWADDR_PRIx "\n",
  159. __func__, offset);
  160. val = 0;
  161. break;
  162. }
  163. if (high) {
  164. val = extract64(val, 32, 19);
  165. } else {
  166. val = extract64(val, 0, 32);
  167. }
  168. trace_aspeed_vic_read(offset, size, val);
  169. return val;
  170. }
  171. static void aspeed_vic_write(void *opaque, hwaddr offset, uint64_t data,
  172. unsigned size)
  173. {
  174. AspeedVICState *s = (AspeedVICState *)opaque;
  175. hwaddr n_offset;
  176. bool high;
  177. if (offset < AVIC_NEW_BASE_OFFSET) {
  178. high = false;
  179. n_offset = offset;
  180. } else {
  181. high = !!(offset & 0x4);
  182. n_offset = (offset & ~0x4);
  183. }
  184. trace_aspeed_vic_write(offset, size, data);
  185. /* Given we have members using separate enable/clear registers, deposit64()
  186. * isn't quite the tool for the job. Instead, relocate the incoming bits to
  187. * the required bit offset based on the provided access address
  188. */
  189. if (high) {
  190. data &= AVIC_H_MASK;
  191. data <<= 32;
  192. } else {
  193. data &= AVIC_L_MASK;
  194. }
  195. switch (n_offset) {
  196. case 0x98: /* Interrupt Selection */
  197. case 0x0c:
  198. /* Register has deposit64() semantics - overwrite requested 32 bits */
  199. if (high) {
  200. s->select &= AVIC_L_MASK;
  201. } else {
  202. s->select &= ((uint64_t) AVIC_H_MASK) << 32;
  203. }
  204. s->select |= data;
  205. break;
  206. case 0xa0: /* Interrupt Enable */
  207. case 0x10:
  208. s->enable |= data;
  209. break;
  210. case 0xa8: /* Interrupt Enable Clear */
  211. case 0x14:
  212. s->enable &= ~data;
  213. break;
  214. case 0xb0: /* Software Interrupt */
  215. case 0x18:
  216. qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. "
  217. "IRQs requested: 0x%016" PRIx64 "\n", __func__, data);
  218. break;
  219. case 0xb8: /* Software Interrupt Clear */
  220. case 0x1c:
  221. qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. "
  222. "IRQs to be cleared: 0x%016" PRIx64 "\n", __func__, data);
  223. break;
  224. case 0xd0: /* Interrupt Event */
  225. /* Register has deposit64() semantics - overwrite the top four valid
  226. * IRQ bits, as only the top four IRQs (GPIOs) can change their event
  227. * type */
  228. if (high) {
  229. s->event &= ~AVIC_EVENT_W_MASK;
  230. s->event |= (data & AVIC_EVENT_W_MASK);
  231. } else {
  232. qemu_log_mask(LOG_GUEST_ERROR,
  233. "Ignoring invalid write to interrupt event register");
  234. }
  235. break;
  236. case 0xd8: /* Edge Triggered Interrupt Clear */
  237. case 0x38:
  238. s->raw &= ~(data & ~s->sense);
  239. break;
  240. case 0x80: /* IRQ Status */
  241. case 0x00:
  242. case 0x88: /* FIQ Status */
  243. case 0x04:
  244. case 0x90: /* Raw Interrupt Status */
  245. case 0x08:
  246. case 0xc0: /* Interrupt Sensitivity */
  247. case 0x24:
  248. case 0xc8: /* Interrupt Both Edge Trigger Control */
  249. case 0x28:
  250. case 0xe0: /* Edge Triggered Interrupt Status */
  251. qemu_log_mask(LOG_GUEST_ERROR,
  252. "%s: Write of read-only register with offset 0x%"
  253. HWADDR_PRIx "\n", __func__, offset);
  254. break;
  255. default:
  256. qemu_log_mask(LOG_GUEST_ERROR,
  257. "%s: Bad register at offset 0x%" HWADDR_PRIx "\n",
  258. __func__, offset);
  259. break;
  260. }
  261. aspeed_vic_update(s);
  262. }
  263. static const MemoryRegionOps aspeed_vic_ops = {
  264. .read = aspeed_vic_read,
  265. .write = aspeed_vic_write,
  266. .endianness = DEVICE_LITTLE_ENDIAN,
  267. .valid.min_access_size = 4,
  268. .valid.max_access_size = 4,
  269. .valid.unaligned = false,
  270. };
  271. static void aspeed_vic_reset(DeviceState *dev)
  272. {
  273. AspeedVICState *s = ASPEED_VIC(dev);
  274. s->level = 0;
  275. s->raw = 0;
  276. s->select = 0;
  277. s->enable = 0;
  278. s->trigger = 0;
  279. s->sense = 0x1F07FFF8FFFFULL;
  280. s->dual_edge = 0xF800070000ULL;
  281. s->event = 0x5F07FFF8FFFFULL;
  282. }
  283. #define AVIC_IO_REGION_SIZE 0x20000
  284. static void aspeed_vic_realize(DeviceState *dev, Error **errp)
  285. {
  286. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  287. AspeedVICState *s = ASPEED_VIC(dev);
  288. memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_vic_ops, s,
  289. TYPE_ASPEED_VIC, AVIC_IO_REGION_SIZE);
  290. sysbus_init_mmio(sbd, &s->iomem);
  291. qdev_init_gpio_in(dev, aspeed_vic_set_irq, ASPEED_VIC_NR_IRQS);
  292. sysbus_init_irq(sbd, &s->irq);
  293. sysbus_init_irq(sbd, &s->fiq);
  294. }
  295. static const VMStateDescription vmstate_aspeed_vic = {
  296. .name = "aspeed.new-vic",
  297. .version_id = 1,
  298. .minimum_version_id = 1,
  299. .fields = (VMStateField[]) {
  300. VMSTATE_UINT64(level, AspeedVICState),
  301. VMSTATE_UINT64(raw, AspeedVICState),
  302. VMSTATE_UINT64(select, AspeedVICState),
  303. VMSTATE_UINT64(enable, AspeedVICState),
  304. VMSTATE_UINT64(trigger, AspeedVICState),
  305. VMSTATE_UINT64(sense, AspeedVICState),
  306. VMSTATE_UINT64(dual_edge, AspeedVICState),
  307. VMSTATE_UINT64(event, AspeedVICState),
  308. VMSTATE_END_OF_LIST()
  309. }
  310. };
  311. static void aspeed_vic_class_init(ObjectClass *klass, void *data)
  312. {
  313. DeviceClass *dc = DEVICE_CLASS(klass);
  314. dc->realize = aspeed_vic_realize;
  315. dc->reset = aspeed_vic_reset;
  316. dc->desc = "ASPEED Interrupt Controller (New)";
  317. dc->vmsd = &vmstate_aspeed_vic;
  318. }
  319. static const TypeInfo aspeed_vic_info = {
  320. .name = TYPE_ASPEED_VIC,
  321. .parent = TYPE_SYS_BUS_DEVICE,
  322. .instance_size = sizeof(AspeedVICState),
  323. .class_init = aspeed_vic_class_init,
  324. };
  325. static void aspeed_vic_register_types(void)
  326. {
  327. type_register_static(&aspeed_vic_info);
  328. }
  329. type_init(aspeed_vic_register_types);