pl080.c 12 KB

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