dma.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * bcm2835 dma controller
  3. *
  4. * simplest to use only channels 0-6
  5. * channels 7-14 have reduced functionality
  6. * channel 15 is at a weird address
  7. * channels 0 and 15 have an "external 128 bit 8 word read FIFO"
  8. * for memory to memory transfers
  9. *
  10. * Experiments show that only channels 2-5,11-12 work with mmc
  11. */
  12. #include "u.h"
  13. #include "../port/lib.h"
  14. #include "../port/error.h"
  15. #include "mem.h"
  16. #include "dat.h"
  17. #include "fns.h"
  18. #include "io.h"
  19. #define DMAREGS (VIRTIO+0x7000)
  20. #define DBG if(Dbg)
  21. enum {
  22. Nchan = 7, /* number of dma channels */
  23. Regsize = 0x100, /* size of regs for each chan */
  24. Cbalign = 32, /* control block byte alignment */
  25. Dbg = 0,
  26. /* registers for each dma controller */
  27. Cs = 0x00>>2,
  28. Conblkad = 0x04>>2,
  29. Ti = 0x08>>2,
  30. Sourcead = 0x0c>>2,
  31. Destad = 0x10>>2,
  32. Txfrlen = 0x14>>2,
  33. Stride = 0x18>>2,
  34. Nextconbk = 0x1c>>2,
  35. Debug = 0x20>>2,
  36. /* collective registers */
  37. Intstatus = 0xfe0>>2,
  38. Enable = 0xff0>>2,
  39. /* Cs */
  40. Reset = 1<<31,
  41. Abort = 1<<30,
  42. Error = 1<<8,
  43. Waitwrite = 1<<6,
  44. Waitdreq = 1<<5,
  45. Paused = 1<<4,
  46. Dreq = 1<<3,
  47. Int = 1<<2,
  48. End = 1<<1,
  49. Active = 1<<0,
  50. /* Ti */
  51. Permapshift= 16,
  52. Srcignore = 1<<11,
  53. Srcdreq = 1<<10,
  54. Srcwidth128 = 1<<9,
  55. Srcinc = 1<<8,
  56. Destignore = 1<<7,
  57. Destdreq = 1<<6,
  58. Destwidth128 = 1<<5,
  59. Destinc = 1<<4,
  60. Waitresp = 1<<3,
  61. Tdmode = 1<<1,
  62. Inten = 1<<0,
  63. /* Debug */
  64. Lite = 1<<28,
  65. Clrerrors = 7<<0,
  66. };
  67. typedef struct Ctlr Ctlr;
  68. typedef struct Cb Cb;
  69. struct Ctlr {
  70. u32int *regs;
  71. Cb *cb;
  72. Rendez r;
  73. int dmadone;
  74. };
  75. struct Cb {
  76. u32int ti;
  77. u32int sourcead;
  78. u32int destad;
  79. u32int txfrlen;
  80. u32int stride;
  81. u32int nextconbk;
  82. u32int reserved[2];
  83. };
  84. static Ctlr dma[Nchan];
  85. static u32int *dmaregs = (u32int*)DMAREGS;
  86. static void
  87. dump(char *msg, uchar *p, int n)
  88. {
  89. print("%s", msg);
  90. while(n-- > 0)
  91. print(" %2.2x", *p++);
  92. print("\n");
  93. }
  94. static void
  95. dumpdregs(char *msg, u32int *r)
  96. {
  97. int i;
  98. print("%s: %#p =", msg, r);
  99. for(i = 0; i < 9; i++)
  100. print(" %8.8uX", r[i]);
  101. print("\n");
  102. }
  103. static int
  104. dmadone(void *a)
  105. {
  106. return ((Ctlr*)a)->dmadone;
  107. }
  108. static void
  109. dmainterrupt(Ureg*, void *a)
  110. {
  111. Ctlr *ctlr;
  112. ctlr = a;
  113. ctlr->regs[Cs] = Int;
  114. ctlr->dmadone = 1;
  115. wakeup(&ctlr->r);
  116. }
  117. void
  118. dmastart(int chan, int dev, int dir, void *src, void *dst, int len)
  119. {
  120. Ctlr *ctlr;
  121. Cb *cb;
  122. int ti;
  123. ctlr = &dma[chan];
  124. if(ctlr->regs == nil){
  125. ctlr->regs = (u32int*)(DMAREGS + chan*Regsize);
  126. ctlr->cb = xspanalloc(sizeof(Cb), Cbalign, 0);
  127. assert(ctlr->cb != nil);
  128. dmaregs[Enable] |= 1<<chan;
  129. ctlr->regs[Cs] = Reset;
  130. while(ctlr->regs[Cs] & Reset)
  131. ;
  132. intrenable(IRQDMA(chan), dmainterrupt, ctlr, 0, "dma");
  133. }
  134. cb = ctlr->cb;
  135. ti = 0;
  136. switch(dir){
  137. case DmaD2M:
  138. cachedwbinvse(dst, len);
  139. ti = Srcdreq | Destinc;
  140. cb->sourcead = DMAIO(src);
  141. cb->destad = DMAADDR(dst);
  142. break;
  143. case DmaM2D:
  144. cachedwbse(src, len);
  145. ti = Destdreq | Srcinc;
  146. cb->sourcead = DMAADDR(src);
  147. cb->destad = DMAIO(dst);
  148. break;
  149. case DmaM2M:
  150. cachedwbse(src, len);
  151. cachedwbinvse(dst, len);
  152. ti = Srcinc | Destinc;
  153. cb->sourcead = DMAADDR(src);
  154. cb->destad = DMAADDR(dst);
  155. break;
  156. }
  157. cb->ti = ti | dev<<Permapshift | Inten;
  158. cb->txfrlen = len;
  159. cb->stride = 0;
  160. cb->nextconbk = 0;
  161. cachedwbse(cb, sizeof(Cb));
  162. ctlr->regs[Cs] = 0;
  163. microdelay(1);
  164. ctlr->regs[Conblkad] = DMAADDR(cb);
  165. DBG print("dma start: %ux %ux %ux %ux %ux %ux\n",
  166. cb->ti, cb->sourcead, cb->destad, cb->txfrlen,
  167. cb->stride, cb->nextconbk);
  168. DBG print("intstatus %ux\n", dmaregs[Intstatus]);
  169. dmaregs[Intstatus] = 0;
  170. ctlr->regs[Cs] = Int;
  171. microdelay(1);
  172. coherence();
  173. DBG dumpdregs("before Active", ctlr->regs);
  174. ctlr->regs[Cs] = Active;
  175. DBG dumpdregs("after Active", ctlr->regs);
  176. }
  177. int
  178. dmawait(int chan)
  179. {
  180. Ctlr *ctlr;
  181. u32int *r;
  182. int s;
  183. ctlr = &dma[chan];
  184. tsleep(&ctlr->r, dmadone, ctlr, 3000);
  185. ctlr->dmadone = 0;
  186. r = ctlr->regs;
  187. DBG dumpdregs("after sleep", r);
  188. s = r[Cs];
  189. if((s & (Active|End|Error)) != End){
  190. print("dma chan %d %s Cs %ux Debug %ux\n", chan,
  191. (s&End)? "error" : "timeout", s, r[Debug]);
  192. r[Cs] = Reset;
  193. r[Debug] = Clrerrors;
  194. return -1;
  195. }
  196. r[Cs] = Int|End;
  197. return 0;
  198. }