2 * omap3530 system dma controller
4 * terminology: a block consist of frame(s), a frame consist of elements
5 * (uchar, ushort, or ulong sized).
8 #include "../port/lib.h"
13 #include "../port/error.h"
14 #include "../port/netif.h"
25 * dma req lines 1, 2, 6, 63 are available for `system expansion'
28 typedef struct Regs Regs;
29 typedef struct Dchan Dchan;
32 /* bitfield of intrs pending, by Dchan; write 1s to clear */
34 ulong irqen[Nirq]; /* bitfield of intrs enabled, by Dchan */
35 ulong syssts; /* 1<<0 is Resetdone */
36 ulong syscfg; /* 1<<1 is Softreset */
37 uchar _pad1[0x64 - 0x30];
39 ulong caps[5]; /* caps[1] not defined */
40 ulong gcr; /* knobs */
44 ulong ccr; /* chan ctrl: incr, etc. */
45 ulong clnkctrl; /* link ctrl */
46 ulong cicr; /* intr ctrl */
47 ulong csr; /* status */
48 ulong csdp; /* src & dest params */
49 ulong cen; /* element # */
50 ulong cfn; /* frame # */
51 ulong cssa; /* src start addr */
52 ulong cdsa; /* dest start addr */
53 ulong csei; /* src element index */
54 ulong csfi; /* src frame index | pkt size */
55 ulong cdei; /* dest element index */
56 ulong cdfi; /* dest frame index | pkt size */
57 ulong csac; /* src addr value (read-only?) */
58 ulong cdac; /* dest addr value */
59 ulong ccen; /* curr transferred element # (in frame) */
60 ulong ccfn; /* curr transferred frame # (in xfer) */
74 typedef struct Xfer Xfer;
77 int *done; /* flag to set on intr */
84 Regs *regs = (Regs *)PHYSSDMA;
86 cp = regs->chan + irq;
87 return cp->csr & Blocki;
91 dmaintr(Ureg *, void *a)
93 int i = (int)a; /* dma request & chan # */
95 Regs *regs = (Regs *)PHYSSDMA;
97 assert(i >= 0 && i < Nirq);
100 assert(xfer[i].rend != nil);
101 wakeup(xfer[i].rend);
104 if(!(cp->csr & Blocki))
105 iprint("dmaintr: req %d: Blocki not set; csr %#lux\n",
107 cp->csr |= cp->csr; /* extinguish intr source */
109 regs->irqsts[i] = regs->irqsts[i]; /* extinguish intr source */
111 regs->irqen[i] &= ~(1 << i);
119 zerowds(ulong *wdp, int cnt)
126 istestdmadone(void *arg)
137 Regs *regs = (Regs *)PHYSSDMA;
139 if (probeaddr((uintptr)®s->syssts) < 0)
140 panic("dmainit: no syssts reg");
143 regs->syscfg |= 1<<1; /* Softreset */
145 while(!(regs->syssts & (1<<0))) /* Resetdone? */
148 for (n = 0; n < Nchan; n++) {
155 cp->cen = cp->cfn = 0;
156 cp->cssa = cp->cdsa = 0;
157 cp->csei = cp->csfi = 0;
158 cp->cdei = cp->cdfi = 0;
159 // cp->csac = cp->cdac = 0; // ro
160 cp->ccen = cp->ccfn = 0;
163 zerowds((void *)regs->irqsts, sizeof regs->irqsts / sizeof(ulong));
164 zerowds((void *)regs->irqen, sizeof regs->irqen / sizeof(ulong));
167 regs->gcr = 65; /* burst size + 1 */
170 for (n = 0; n < Nirq; n++) {
171 snprint(name, sizeof name, "dma%d", n);
172 intrenable(Baseirq + n, dmaintr, (void *)n, nil, name);
183 * try to confirm sane operation
190 static ulong pat = 0x87654321;
191 static Rendez trendez;
194 panic("dmatest: up not set yet");
195 bp = (uchar *)KADDR(PHYSDRAM + 128*MB);
196 memset(bp, Testbyte, Scratch);
198 dmastart((void *)PADDR(bp), Postincr, (void *)PADDR(&pat), Const,
199 Testsize, &trendez, &done);
200 sleep(&trendez, istestdmadone, &done);
201 cachedinvse(bp, Scratch);
203 if (((ulong *)bp)[0] != pat)
204 panic("dmainit: copied incorrect data %#lux != %#lux",
205 ((ulong *)bp)[0], pat);
206 for (n = Testsize; n < Scratch && bp[n] != Testbyte; n++)
209 panic("dmainit: ran wild over memory, clobbered ≥%,d bytes", n);
210 if (bp[n] == Testbyte && n != Testsize)
211 iprint("dma: %d-byte dma stopped after %d bytes!\n",
215 /* addresses are physical */
217 dmastart(void *to, int tmode, void *from, int fmode, uint len, Rendez *rend,
223 Regs *regs = (Regs *)PHYSSDMA;
224 static Lock alloclck;
226 /* allocate free irq (and chan) */
228 for (irq = 0; irq < Nirq && xfer[irq].rend != nil; irq++)
231 panic("dmastart: no available irqs; too many concurrent dmas");
233 xfer[irq].rend = rend; /* for wakeup at intr time */
234 xfer[irq].done = done;
238 ruplen = ROUND(len, sizeof(ulong));
241 cp = regs->chan + chan;
242 cp->ccr &= ~Enable; /* paranoia */
244 regs->irqen[irq] &= ~(1 << chan);
247 cp->csdp = 2; /* 2 = log2(sizeof(ulong)) */
248 cp->cssa = (uintptr)from;
249 cp->cdsa = (uintptr)to;
250 cp->ccr = tmode << 14 | fmode << 12;
251 cp->csei = cp->csfi = cp->cdei = cp->cdfi = 1;
252 cp->cen = ruplen / sizeof(ulong); /* ulongs / frame */
253 cp->cfn = 1; /* 1 frame / xfer */
254 cp->cicr = Blocki; /* intr at end of block */
256 regs->irqen[irq] |= 1 << chan;
259 cp->ccr |= Enable; /* fire! */