diff options
author | aiju <devnull@localhost> | 2020-01-12 03:40:42 +0000 |
---|---|---|
committer | aiju <devnull@localhost> | 2020-01-12 03:40:42 +0000 |
commit | 561346d07f176356e9841891e5213672c0a33878 (patch) | |
tree | 33ff950950ded02e47c0889c899d00f310148ce8 /sys/src/9/cycv/dma.c | |
parent | 7cf8369411a3b9348f862bccaa4147b9aaf38e67 (diff) |
cyclone v kernel: fpga support, fix CONFADDR
Diffstat (limited to 'sys/src/9/cycv/dma.c')
-rw-r--r-- | sys/src/9/cycv/dma.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/sys/src/9/cycv/dma.c b/sys/src/9/cycv/dma.c new file mode 100644 index 000000000..211e71ec2 --- /dev/null +++ b/sys/src/9/cycv/dma.c @@ -0,0 +1,265 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "../port/error.h" + +#define dmar ((ulong*)DMAS_BASE) + +enum { + DSR = 0x000, + DPC = 0x004/4, + INTEN = 0x20 / 4, + INT_EVENT_RIS = 0x024 / 4, + INTMIS = 0x028 / 4, + INTCLR = 0x02C / 4, + FSRD = 0x030 / 4, + FSRC = 0x034 / 4, + FTRD = 0x038 / 4, + DBGSTATUS = 0xD00 / 4, + DBGCMD = 0xD04 / 4, + DBGINST0 = 0xD08 / 4, + DBGINST1 = 0xD0C / 4, + CR0 = 0xE00 / 4, + CR1, CR2, CR3, CR4, CRD, + WD = 0xE80 / 4, +}; +enum { + DMAStopped, + DMAExecuting, + DMACacheMiss, + DMAUpdatingPC, + DMAWaitingForEvent, + DMAAtBarrier, + DMAWaitingForPeripheral = 7, + DMAKilling, + DMACompleting, + DMAFaultingCompleting=14, + DMAFaulting, +}; +#define FTR(n) dmar[(0x40/4 + (n))] +#define CSR(n) dmar[(0x100/4 + (n)*2)] +#define CPC(n) dmar[(0x104/4 + (n)*2)] +#define SAR(n) dmar[(0x400/4 + (n)*8)] +#define DAR(n) dmar[(0x404/4 + (n)*8)] +#define CCR(n) dmar[(0x408/4 + (n)*8)] +#define LC0(n) dmar[(0x40C/4 + (n)*8)] +#define LC1(n) dmar[(0x410/4 + (n)*8)] + +#define DST_BURST(n) (((n)-1&0xf)<<18) +#define DST_BEAT_1 (0) +#define DST_BEAT_2 (1<<15) +#define DST_BEAT_4 (2<<15) +#define DST_BEAT_8 (3<<15) +#define DST_BEAT_16 (4<<15) +#define SRC_BURST(n) (((n)-1&0xf)<<4) +#define SRC_BEAT_1 (0) +#define SRC_BEAT_2 (1<<1) +#define SRC_BEAT_4 (2<<1) +#define SRC_BEAT_8 (3<<1) +#define SRC_BEAT_16 (4<<1) + +#define dmaMOV_SARn 0x00bc +#define dmaMOV_CCRn 0x01bc +#define dmaMOV_DARn 0x02bc +#define dmaLP0(n) (((n)-1&0xff)<<8|0x20) +#define dmaLP1(n) (((n)-1&0xff)<<8|0x22) +#define dmaLPEND0(n) (((n)&0xff)<<8|0x38) +#define dmaLPEND1(n) (((n)&0xff)<<8|0x3c) +#define dmaLD 0x04 +#define dmaST 0x08 +#define dmaSEV(n) (((n)&31)<<11|0x34) +#define dmaEND 0x00 +#define dmaWMB 0x13 + +static QLock dmalock; +static Rendez dmarend; +static int finished; +static ulong code[64]; + +static int +isfinished(void *) +{ + return finished; +} +static void +dmairq(Ureg *, void *) +{ + dmar[INTCLR] = -1; + finished = 1; + wakeup(&dmarend); +} + +static void +compactify(ulong *lp) +{ + uchar *p, *q; + + q = p = (uchar *) lp; + for(;;){ + switch(*p){ + case 0xbc: + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[4]; + q[3] = p[5]; + q[4] = p[6]; + q[5] = p[7]; + q += 6; p += 8; + break; + case 0x20: case 0x22: case 0x38: case 0x3c: case 0x34: + q[0] = p[0]; + q[1] = p[1]; + q += 2; p += 4; + break; + case 0x04: case 0x08: case 0x13: + q[0] = p[0]; + q++; p += 4; + break; + case 0x00: + q[0] = 0; + return; + default: + panic("DMA: unknown opcode %.2x", *p); + } + } +} + +#define BURST(n) *p++ = dmaMOV_CCRn, *p++ = DST_BEAT_4 | SRC_BEAT_4 | SRC_BURST(n) | DST_BURST(n) | attr + +void +dmacopy(void *dst, void *src, ulong n, int attr) +{ + ulong *p; + + assert((n & 3) == 0 && ((uintptr)src & 3) == 0 && ((uintptr)dst & 3) == 0); + while(n > (1<<22)){ + dmacopy(dst, src, 1<<22, attr); + if((attr & SRC_INC) != 0) src = (uchar*)src + (1<<22); + if((attr & DST_INC) != 0) dst = (uchar*)dst + (1<<22); + } + if(n == 0) return; + qlock(&dmalock); + p = code; + *p++ = dmaMOV_SARn; *p++ = PADDR(src); + *p++ = dmaMOV_DARn; *p++ = PADDR(dst); + if((n >> 6) >= 1){ + BURST(16); + if((n>>14) >= 1){ + if((n>>14) > 1) *p++ = dmaLP0(n >> 14); + *p++ = dmaLP1(256); + *p++ = dmaLD; + *p++ = dmaST; + *p++ = dmaLPEND1(2); + if((n>>14) > 1) *p++ = dmaLPEND0(6); + n &= (1<<14)-1; + } + if((n >> 6) >= 1){ + if((n>>6) > 1) *p++ = dmaLP0(n >> 6); + *p++ = dmaLD; + *p++ = dmaST; + if((n>>6) > 1) *p++ = dmaLPEND0(2); + n &= 63; + } + } + if(n >= 4){ + BURST(n>>2); + *p++ = dmaLD; + *p++ = dmaST; + } + *p++ = dmaWMB; + *p++ = dmaSEV(0); + *p = dmaEND; + compactify(code); + if((CSR(0) & 0xf) != DMAStopped){ + while((dmar[DBGSTATUS] & 1) != 0) + tsleep(&up->sleep, return0, nil, 1); + dmar[DBGINST0] = 0x1 << 16 | 1; + dmar[DBGCMD] = 0; + while((dmar[DBGSTATUS] & 1) != 0) + tsleep(&up->sleep, return0, nil, 1); + while((CSR(0) & 0xf) != DMAStopped) + tsleep(&up->sleep, return0, nil, 1); + } + cleandse(code, code + nelem(code)); + while((dmar[DBGSTATUS] & 1) != 0) + tsleep(&up->sleep, return0, nil, 1); + dmar[DBGINST0] = 0xa0 << 16; + dmar[DBGINST1] = PADDR(code); + finished = 0; + dmar[DBGCMD] = 0; + while(!finished) + sleep(&dmarend, isfinished, nil); + qunlock(&dmalock); +} + + +static void +dmaabort(Ureg *, void *) +{ + int i; + + if((dmar[FSRD] & 1) != 0){ + iprint("dma: manager fault: "); + if((dmar[FTRD] & 1<<30) != 0) + iprint("debug instruction, "); + if((dmar[FTRD] & 1<<16) != 0) + iprint("instruction fetch error, "); + if((dmar[FTRD] & 1<<5) != 0) + iprint("event security violation, "); + if((dmar[FTRD] & 1<<4) != 0) + iprint("DMAGO security violation, "); + if((dmar[FTRD] & 1<<1) != 0) + iprint("operand invalid, "); + if((dmar[FTRD] & 1<<0) != 0) + iprint("undefined instruction, "); + iprint("\n"); + } + for(i = 0; i < 8; i++){ + if((dmar[FSRC] & 1<<i) == 0) + continue; + iprint("dma: channel %d fault\n", i); + iprint("code = %.8p, PC = %.8ulx\n", code, CPC(i)); + iprint("CCRn = %.8ulx, CSRn = %.8ulx\n", CCR(i), CSR(i)); + iprint("LC0 = %.2ulx, LC1 = %.2ulx\n", LC0(i), LC1(i)); + if((FTR(i) & 1<<31) != 0) + iprint("insufficient resources, "); + if((FTR(i) & 1<<30) != 0) + iprint("debug instruction, "); + if((FTR(i) & 1<<18) != 0) + iprint("read error, "); + if((FTR(i) & 1<<17) != 0) + iprint("write error, "); + if((FTR(i) & 1<<16) != 0) + iprint("instruction fetch error, "); + if((FTR(i) & 1<<13) != 0) + iprint("FIFO underflow, "); + if((FTR(i) & 1<<12) != 0) + iprint("FIFO error, "); + if((FTR(i) & 1<<7) != 0) + iprint("CCRn security violation, "); + if((FTR(i) & 1<<6) != 0) + iprint("peripheral security violation, "); + if((FTR(i) & 1<<5) != 0) + iprint("event security violation, "); + if((FTR(i) & 1<<4) != 0) + iprint("DMAGO security violation, "); + if((FTR(i) & 1<<1) != 0) + iprint("operand invalid, "); + if((FTR(i) & 1<<0) != 0) + iprint("undefined instruction, "); + iprint("\n"); + } + panic("DMA fault"); +} + +void +dmalink(void) +{ + dmar[INTEN] = 1; + intrenable(DMAIRQ0, dmairq, nil, LEVEL, "dma"); + intrenable(DMAABORTIRQ, dmaabort, nil, LEVEL, "dma_abort"); +} |