pl080.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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, target_phys_addr_t 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. hw_error("pl080_read: Bad offset %x\n", (int)offset);
  266. return 0;
  267. }
  268. }
  269. static void pl080_write(void *opaque, target_phys_addr_t offset,
  270. uint64_t value, unsigned size)
  271. {
  272. pl080_state *s = (pl080_state *)opaque;
  273. int i;
  274. if (offset >= 0x100 && offset < 0x200) {
  275. i = (offset & 0xe0) >> 5;
  276. if (i >= s->nchannels)
  277. goto bad_offset;
  278. switch (offset >> 2) {
  279. case 0: /* SrcAddr */
  280. s->chan[i].src = value;
  281. break;
  282. case 1: /* DestAddr */
  283. s->chan[i].dest = value;
  284. break;
  285. case 2: /* LLI */
  286. s->chan[i].lli = value;
  287. break;
  288. case 3: /* Control */
  289. s->chan[i].ctrl = value;
  290. break;
  291. case 4: /* Configuration */
  292. s->chan[i].conf = value;
  293. pl080_run(s);
  294. break;
  295. }
  296. }
  297. switch (offset >> 2) {
  298. case 2: /* IntTCClear */
  299. s->tc_int &= ~value;
  300. break;
  301. case 4: /* IntErrorClear */
  302. s->err_int &= ~value;
  303. break;
  304. case 8: /* SoftBReq */
  305. case 9: /* SoftSReq */
  306. case 10: /* SoftLBReq */
  307. case 11: /* SoftLSReq */
  308. /* ??? Implement these. */
  309. hw_error("pl080_write: Soft DMA not implemented\n");
  310. break;
  311. case 12: /* Configuration */
  312. s->conf = value;
  313. if (s->conf & (PL080_CONF_M1 | PL080_CONF_M1)) {
  314. hw_error("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. hw_error("pl080_write: Bad offset %x\n", (int)offset);
  324. }
  325. pl080_update(s);
  326. }
  327. static const MemoryRegionOps pl080_ops = {
  328. .read = pl080_read,
  329. .write = pl080_write,
  330. .endianness = DEVICE_NATIVE_ENDIAN,
  331. };
  332. static int pl08x_init(SysBusDevice *dev, int nchannels)
  333. {
  334. pl080_state *s = FROM_SYSBUS(pl080_state, dev);
  335. memory_region_init_io(&s->iomem, &pl080_ops, s, "pl080", 0x1000);
  336. sysbus_init_mmio(dev, &s->iomem);
  337. sysbus_init_irq(dev, &s->irq);
  338. s->nchannels = nchannels;
  339. return 0;
  340. }
  341. static int pl080_init(SysBusDevice *dev)
  342. {
  343. return pl08x_init(dev, 8);
  344. }
  345. static int pl081_init(SysBusDevice *dev)
  346. {
  347. return pl08x_init(dev, 2);
  348. }
  349. static void pl080_class_init(ObjectClass *klass, void *data)
  350. {
  351. DeviceClass *dc = DEVICE_CLASS(klass);
  352. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  353. k->init = pl080_init;
  354. dc->no_user = 1;
  355. dc->vmsd = &vmstate_pl080;
  356. }
  357. static TypeInfo pl080_info = {
  358. .name = "pl080",
  359. .parent = TYPE_SYS_BUS_DEVICE,
  360. .instance_size = sizeof(pl080_state),
  361. .class_init = pl080_class_init,
  362. };
  363. static void pl081_class_init(ObjectClass *klass, void *data)
  364. {
  365. DeviceClass *dc = DEVICE_CLASS(klass);
  366. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  367. k->init = pl081_init;
  368. dc->no_user = 1;
  369. dc->vmsd = &vmstate_pl080;
  370. }
  371. static TypeInfo pl081_info = {
  372. .name = "pl081",
  373. .parent = TYPE_SYS_BUS_DEVICE,
  374. .instance_size = sizeof(pl080_state),
  375. .class_init = pl081_class_init,
  376. };
  377. /* The PL080 and PL081 are the same except for the number of channels
  378. they implement (8 and 2 respectively). */
  379. static void pl080_register_types(void)
  380. {
  381. type_register_static(&pl080_info);
  382. type_register_static(&pl081_info);
  383. }
  384. type_init(pl080_register_types)