PageRenderTime 26ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/hw/dma/pl080.c

https://gitlab.com/storedmirrors/qemu
C | 449 lines | 390 code | 38 blank | 21 comment | 52 complexity | 58e4a7a47a400458de4a47fa29f5e7a9 MD5 | raw file
  1. /*
  2. * Arm PrimeCell PL080/PL081 DMA controller
  3. *
  4. * Copyright (c) 2006 CodeSourcery.
  5. * Written by Paul Brook
  6. *
  7. * This code is licensed under the GPL.
  8. */
  9. #include "qemu/osdep.h"
  10. #include "hw/sysbus.h"
  11. #include "migration/vmstate.h"
  12. #include "qemu/log.h"
  13. #include "qemu/module.h"
  14. #include "hw/dma/pl080.h"
  15. #include "hw/hw.h"
  16. #include "hw/irq.h"
  17. #include "hw/qdev-properties.h"
  18. #include "qapi/error.h"
  19. #define PL080_CONF_E 0x1
  20. #define PL080_CONF_M1 0x2
  21. #define PL080_CONF_M2 0x4
  22. #define PL080_CCONF_H 0x40000
  23. #define PL080_CCONF_A 0x20000
  24. #define PL080_CCONF_L 0x10000
  25. #define PL080_CCONF_ITC 0x08000
  26. #define PL080_CCONF_IE 0x04000
  27. #define PL080_CCONF_E 0x00001
  28. #define PL080_CCTRL_I 0x80000000
  29. #define PL080_CCTRL_DI 0x08000000
  30. #define PL080_CCTRL_SI 0x04000000
  31. #define PL080_CCTRL_D 0x02000000
  32. #define PL080_CCTRL_S 0x01000000
  33. static const VMStateDescription vmstate_pl080_channel = {
  34. .name = "pl080_channel",
  35. .version_id = 1,
  36. .minimum_version_id = 1,
  37. .fields = (VMStateField[]) {
  38. VMSTATE_UINT32(src, pl080_channel),
  39. VMSTATE_UINT32(dest, pl080_channel),
  40. VMSTATE_UINT32(lli, pl080_channel),
  41. VMSTATE_UINT32(ctrl, pl080_channel),
  42. VMSTATE_UINT32(conf, pl080_channel),
  43. VMSTATE_END_OF_LIST()
  44. }
  45. };
  46. static const VMStateDescription vmstate_pl080 = {
  47. .name = "pl080",
  48. .version_id = 1,
  49. .minimum_version_id = 1,
  50. .fields = (VMStateField[]) {
  51. VMSTATE_UINT8(tc_int, PL080State),
  52. VMSTATE_UINT8(tc_mask, PL080State),
  53. VMSTATE_UINT8(err_int, PL080State),
  54. VMSTATE_UINT8(err_mask, PL080State),
  55. VMSTATE_UINT32(conf, PL080State),
  56. VMSTATE_UINT32(sync, PL080State),
  57. VMSTATE_UINT32(req_single, PL080State),
  58. VMSTATE_UINT32(req_burst, PL080State),
  59. VMSTATE_UINT8(tc_int, PL080State),
  60. VMSTATE_UINT8(tc_int, PL080State),
  61. VMSTATE_UINT8(tc_int, PL080State),
  62. VMSTATE_STRUCT_ARRAY(chan, PL080State, PL080_MAX_CHANNELS,
  63. 1, vmstate_pl080_channel, pl080_channel),
  64. VMSTATE_INT32(running, PL080State),
  65. VMSTATE_END_OF_LIST()
  66. }
  67. };
  68. static const unsigned char pl080_id[] =
  69. { 0x80, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
  70. static const unsigned char pl081_id[] =
  71. { 0x81, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
  72. static void pl080_update(PL080State *s)
  73. {
  74. bool tclevel = (s->tc_int & s->tc_mask);
  75. bool errlevel = (s->err_int & s->err_mask);
  76. qemu_set_irq(s->interr, errlevel);
  77. qemu_set_irq(s->inttc, tclevel);
  78. qemu_set_irq(s->irq, errlevel || tclevel);
  79. }
  80. static void pl080_run(PL080State *s)
  81. {
  82. int c;
  83. int flow;
  84. pl080_channel *ch;
  85. int swidth;
  86. int dwidth;
  87. int xsize;
  88. int n;
  89. int src_id;
  90. int dest_id;
  91. int size;
  92. uint8_t buff[4];
  93. uint32_t req;
  94. s->tc_mask = 0;
  95. for (c = 0; c < s->nchannels; c++) {
  96. if (s->chan[c].conf & PL080_CCONF_ITC)
  97. s->tc_mask |= 1 << c;
  98. if (s->chan[c].conf & PL080_CCONF_IE)
  99. s->err_mask |= 1 << c;
  100. }
  101. if ((s->conf & PL080_CONF_E) == 0)
  102. return;
  103. /* If we are already in the middle of a DMA operation then indicate that
  104. there may be new DMA requests and return immediately. */
  105. if (s->running) {
  106. s->running++;
  107. return;
  108. }
  109. s->running = 1;
  110. while (s->running) {
  111. for (c = 0; c < s->nchannels; c++) {
  112. ch = &s->chan[c];
  113. again:
  114. /* Test if thiws channel has any pending DMA requests. */
  115. if ((ch->conf & (PL080_CCONF_H | PL080_CCONF_E))
  116. != PL080_CCONF_E)
  117. continue;
  118. flow = (ch->conf >> 11) & 7;
  119. if (flow >= 4) {
  120. hw_error(
  121. "pl080_run: Peripheral flow control not implemented\n");
  122. }
  123. src_id = (ch->conf >> 1) & 0x1f;
  124. dest_id = (ch->conf >> 6) & 0x1f;
  125. size = ch->ctrl & 0xfff;
  126. req = s->req_single | s->req_burst;
  127. switch (flow) {
  128. case 0:
  129. break;
  130. case 1:
  131. if ((req & (1u << dest_id)) == 0)
  132. size = 0;
  133. break;
  134. case 2:
  135. if ((req & (1u << src_id)) == 0)
  136. size = 0;
  137. break;
  138. case 3:
  139. if ((req & (1u << src_id)) == 0
  140. || (req & (1u << dest_id)) == 0)
  141. size = 0;
  142. break;
  143. }
  144. if (!size)
  145. continue;
  146. /* Transfer one element. */
  147. /* ??? Should transfer multiple elements for a burst request. */
  148. /* ??? Unclear what the proper behavior is when source and
  149. destination widths are different. */
  150. swidth = 1 << ((ch->ctrl >> 18) & 7);
  151. dwidth = 1 << ((ch->ctrl >> 21) & 7);
  152. for (n = 0; n < dwidth; n+= swidth) {
  153. address_space_read(&s->downstream_as, ch->src,
  154. MEMTXATTRS_UNSPECIFIED, buff + n, swidth);
  155. if (ch->ctrl & PL080_CCTRL_SI)
  156. ch->src += swidth;
  157. }
  158. xsize = (dwidth < swidth) ? swidth : dwidth;
  159. /* ??? This may pad the value incorrectly for dwidth < 32. */
  160. for (n = 0; n < xsize; n += dwidth) {
  161. address_space_write(&s->downstream_as, ch->dest + n,
  162. MEMTXATTRS_UNSPECIFIED, buff + n, dwidth);
  163. if (ch->ctrl & PL080_CCTRL_DI)
  164. ch->dest += swidth;
  165. }
  166. size--;
  167. ch->ctrl = (ch->ctrl & 0xfffff000) | size;
  168. if (size == 0) {
  169. /* Transfer complete. */
  170. if (ch->lli) {
  171. ch->src = address_space_ldl_le(&s->downstream_as,
  172. ch->lli,
  173. MEMTXATTRS_UNSPECIFIED,
  174. NULL);
  175. ch->dest = address_space_ldl_le(&s->downstream_as,
  176. ch->lli + 4,
  177. MEMTXATTRS_UNSPECIFIED,
  178. NULL);
  179. ch->ctrl = address_space_ldl_le(&s->downstream_as,
  180. ch->lli + 12,
  181. MEMTXATTRS_UNSPECIFIED,
  182. NULL);
  183. ch->lli = address_space_ldl_le(&s->downstream_as,
  184. ch->lli + 8,
  185. MEMTXATTRS_UNSPECIFIED,
  186. NULL);
  187. } else {
  188. ch->conf &= ~PL080_CCONF_E;
  189. }
  190. if (ch->ctrl & PL080_CCTRL_I) {
  191. s->tc_int |= 1 << c;
  192. }
  193. }
  194. goto again;
  195. }
  196. if (--s->running)
  197. s->running = 1;
  198. }
  199. }
  200. static uint64_t pl080_read(void *opaque, hwaddr offset,
  201. unsigned size)
  202. {
  203. PL080State *s = (PL080State *)opaque;
  204. uint32_t i;
  205. uint32_t mask;
  206. if (offset >= 0xfe0 && offset < 0x1000) {
  207. if (s->nchannels == 8) {
  208. return pl080_id[(offset - 0xfe0) >> 2];
  209. } else {
  210. return pl081_id[(offset - 0xfe0) >> 2];
  211. }
  212. }
  213. if (offset >= 0x100 && offset < 0x200) {
  214. i = (offset & 0xe0) >> 5;
  215. if (i >= s->nchannels)
  216. goto bad_offset;
  217. switch ((offset >> 2) & 7) {
  218. case 0: /* SrcAddr */
  219. return s->chan[i].src;
  220. case 1: /* DestAddr */
  221. return s->chan[i].dest;
  222. case 2: /* LLI */
  223. return s->chan[i].lli;
  224. case 3: /* Control */
  225. return s->chan[i].ctrl;
  226. case 4: /* Configuration */
  227. return s->chan[i].conf;
  228. default:
  229. goto bad_offset;
  230. }
  231. }
  232. switch (offset >> 2) {
  233. case 0: /* IntStatus */
  234. return (s->tc_int & s->tc_mask) | (s->err_int & s->err_mask);
  235. case 1: /* IntTCStatus */
  236. return (s->tc_int & s->tc_mask);
  237. case 3: /* IntErrorStatus */
  238. return (s->err_int & s->err_mask);
  239. case 5: /* RawIntTCStatus */
  240. return s->tc_int;
  241. case 6: /* RawIntErrorStatus */
  242. return s->err_int;
  243. case 7: /* EnbldChns */
  244. mask = 0;
  245. for (i = 0; i < s->nchannels; i++) {
  246. if (s->chan[i].conf & PL080_CCONF_E)
  247. mask |= 1 << i;
  248. }
  249. return mask;
  250. case 8: /* SoftBReq */
  251. case 9: /* SoftSReq */
  252. case 10: /* SoftLBReq */
  253. case 11: /* SoftLSReq */
  254. /* ??? Implement these. */
  255. return 0;
  256. case 12: /* Configuration */
  257. return s->conf;
  258. case 13: /* Sync */
  259. return s->sync;
  260. default:
  261. bad_offset:
  262. qemu_log_mask(LOG_GUEST_ERROR,
  263. "pl080_read: Bad offset %x\n", (int)offset);
  264. return 0;
  265. }
  266. }
  267. static void pl080_write(void *opaque, hwaddr offset,
  268. uint64_t value, unsigned size)
  269. {
  270. PL080State *s = (PL080State *)opaque;
  271. int i;
  272. if (offset >= 0x100 && offset < 0x200) {
  273. i = (offset & 0xe0) >> 5;
  274. if (i >= s->nchannels)
  275. goto bad_offset;
  276. switch ((offset >> 2) & 7) {
  277. case 0: /* SrcAddr */
  278. s->chan[i].src = value;
  279. break;
  280. case 1: /* DestAddr */
  281. s->chan[i].dest = value;
  282. break;
  283. case 2: /* LLI */
  284. s->chan[i].lli = value;
  285. break;
  286. case 3: /* Control */
  287. s->chan[i].ctrl = value;
  288. break;
  289. case 4: /* Configuration */
  290. s->chan[i].conf = value;
  291. pl080_run(s);
  292. break;
  293. }
  294. return;
  295. }
  296. switch (offset >> 2) {
  297. case 2: /* IntTCClear */
  298. s->tc_int &= ~value;
  299. break;
  300. case 4: /* IntErrorClear */
  301. s->err_int &= ~value;
  302. break;
  303. case 8: /* SoftBReq */
  304. case 9: /* SoftSReq */
  305. case 10: /* SoftLBReq */
  306. case 11: /* SoftLSReq */
  307. /* ??? Implement these. */
  308. qemu_log_mask(LOG_UNIMP, "pl080_write: Soft DMA not implemented\n");
  309. break;
  310. case 12: /* Configuration */
  311. s->conf = value;
  312. if (s->conf & (PL080_CONF_M1 | PL080_CONF_M2)) {
  313. qemu_log_mask(LOG_UNIMP,
  314. "pl080_write: Big-endian DMA not implemented\n");
  315. }
  316. pl080_run(s);
  317. break;
  318. case 13: /* Sync */
  319. s->sync = value;
  320. break;
  321. default:
  322. bad_offset:
  323. qemu_log_mask(LOG_GUEST_ERROR,
  324. "pl080_write: Bad offset %x\n", (int)offset);
  325. }
  326. pl080_update(s);
  327. }
  328. static const MemoryRegionOps pl080_ops = {
  329. .read = pl080_read,
  330. .write = pl080_write,
  331. .endianness = DEVICE_NATIVE_ENDIAN,
  332. };
  333. static void pl080_reset(DeviceState *dev)
  334. {
  335. PL080State *s = PL080(dev);
  336. int i;
  337. s->tc_int = 0;
  338. s->tc_mask = 0;
  339. s->err_int = 0;
  340. s->err_mask = 0;
  341. s->conf = 0;
  342. s->sync = 0;
  343. s->req_single = 0;
  344. s->req_burst = 0;
  345. s->running = 0;
  346. for (i = 0; i < s->nchannels; i++) {
  347. s->chan[i].src = 0;
  348. s->chan[i].dest = 0;
  349. s->chan[i].lli = 0;
  350. s->chan[i].ctrl = 0;
  351. s->chan[i].conf = 0;
  352. }
  353. }
  354. static void pl080_init(Object *obj)
  355. {
  356. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  357. PL080State *s = PL080(obj);
  358. memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
  359. sysbus_init_mmio(sbd, &s->iomem);
  360. sysbus_init_irq(sbd, &s->irq);
  361. sysbus_init_irq(sbd, &s->interr);
  362. sysbus_init_irq(sbd, &s->inttc);
  363. s->nchannels = 8;
  364. }
  365. static void pl080_realize(DeviceState *dev, Error **errp)
  366. {
  367. PL080State *s = PL080(dev);
  368. if (!s->downstream) {
  369. error_setg(errp, "PL080 'downstream' link not set");
  370. return;
  371. }
  372. address_space_init(&s->downstream_as, s->downstream, "pl080-downstream");
  373. }
  374. static void pl081_init(Object *obj)
  375. {
  376. PL080State *s = PL080(obj);
  377. s->nchannels = 2;
  378. }
  379. static Property pl080_properties[] = {
  380. DEFINE_PROP_LINK("downstream", PL080State, downstream,
  381. TYPE_MEMORY_REGION, MemoryRegion *),
  382. DEFINE_PROP_END_OF_LIST(),
  383. };
  384. static void pl080_class_init(ObjectClass *oc, void *data)
  385. {
  386. DeviceClass *dc = DEVICE_CLASS(oc);
  387. dc->vmsd = &vmstate_pl080;
  388. dc->realize = pl080_realize;
  389. device_class_set_props(dc, pl080_properties);
  390. dc->reset = pl080_reset;
  391. }
  392. static const TypeInfo pl080_info = {
  393. .name = TYPE_PL080,
  394. .parent = TYPE_SYS_BUS_DEVICE,
  395. .instance_size = sizeof(PL080State),
  396. .instance_init = pl080_init,
  397. .class_init = pl080_class_init,
  398. };
  399. static const TypeInfo pl081_info = {
  400. .name = TYPE_PL081,
  401. .parent = TYPE_PL080,
  402. .instance_init = pl081_init,
  403. };
  404. /* The PL080 and PL081 are the same except for the number of channels
  405. they implement (8 and 2 respectively). */
  406. static void pl080_register_types(void)
  407. {
  408. type_register_static(&pl080_info);
  409. type_register_static(&pl081_info);
  410. }
  411. type_init(pl080_register_types)