2 * bcm2835 dma controller
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
10 * Experiments show that only channels 2-5,11-12 work with mmc
14 #include "../port/lib.h"
15 #include "../port/error.h"
21 #define DMAREGS (VIRTIO+0x7000)
26 Nchan = 7, /* number of dma channels */
27 Regsize = 0x100, /* size of regs for each chan */
28 Cbalign = 32, /* control block byte alignment */
31 /* registers for each dma controller */
42 /* collective registers */
77 typedef struct Ctlr Ctlr;
97 static Ctlr dma[Nchan];
98 static u32int *dmaregs = (u32int*)DMAREGS;
101 dump(char *msg, uchar *p, int n)
105 print(" %2.2x", *p++);
110 dumpdregs(char *msg, u32int *r)
114 print("%s: %#p =", msg, r);
115 for(i = 0; i < 9; i++)
116 print(" %8.8uX", r[i]);
123 return ((Ctlr*)a)->dmadone;
127 dmainterrupt(Ureg*, void *a)
132 ctlr->regs[Cs] = Int;
138 dmastart(int chan, int dev, int dir, void *src, void *dst, int len)
145 if(ctlr->regs == nil){
146 ctlr->regs = (u32int*)(DMAREGS + chan*Regsize);
147 ctlr->cb = xspanalloc(sizeof(Cb), Cbalign, 0);
148 assert(ctlr->cb != nil);
149 dmaregs[Enable] |= 1 << chan;
150 ctlr->regs[Cs] = Reset;
151 while(ctlr->regs[Cs] & Reset)
153 intrenable(IRQDMA(chan), dmainterrupt, ctlr, 0, "dma");
159 cachedwbinvse(dst, len);
160 ti = Srcdreq | Destinc;
161 cb->sourcead = DMAIO(src);
162 cb->destad = DMAADDR(dst);
165 cachedwbse(src, len);
166 ti = Destdreq | Srcinc;
167 cb->sourcead = DMAADDR(src);
168 cb->destad = DMAIO(dst);
171 cachedwbse(src, len);
172 cachedwbinvse(dst, len);
173 ti = Srcinc | Destinc;
174 cb->sourcead = DMAADDR(src);
175 cb->destad = DMAADDR(dst);
178 cb->ti = ti | dev << Permapshift | Inten;
182 cachedwbse(cb, sizeof(Cb));
185 ctlr->regs[Conblkad] = DMAADDR(cb);
186 DBG print("dma start: %ux %ux %ux %ux %ux %ux\n",
187 cb->ti, cb->sourcead, cb->destad, cb->txfrlen,
188 cb->stride, cb->nextconbk);
189 DBG print("intstatus %ux\n", dmaregs[Intstatus]);
190 dmaregs[Intstatus] = 0;
191 ctlr->regs[Cs] = Int;
194 DBG dumpdregs("before Active", ctlr->regs);
195 ctlr->regs[Cs] = Active;
196 DBG dumpdregs("after Active", ctlr->regs);
207 tsleep(&ctlr->r, dmadone, ctlr, 3000);
210 DBG dumpdregs("after sleep", r);
212 if((s & (Active|End|Error)) != End){
213 print("dma chan %d %s Cs %ux Debug %ux\n", chan,
214 (s&End)? "error" : "timeout", s, r[Debug]);
216 r[Debug] = Clrerrors;