void spirw(uint cs, void *buf, int len) { Spiregs *r; assert(cs <= 2); assert(len < (1<<16)); qlock(&spi.lock); if(waserror()){ qunlock(&spi.lock); nexterror(); } if(spi.regs == 0) spiinit(); r = spi.regs; r->dlen = len; r->cs = (cs << Csshift) | Rxclear | Txclear | Dmaen | Adcs | Ta; /* * Start write channel before read channel - cache wb before inv */ dmastart(DmaChanSpiTx, DmaDevSpiTx, DmaM2D, buf, &r->data, len); dmastart(DmaChanSpiRx, DmaDevSpiRx, DmaD2M, &r->data, buf, len); if(dmawait(DmaChanSpiRx) < 0) error(Eio); cachedinvse(buf, len); r->cs = 0; qunlock(&spi.lock); poperror(); }
/* * try to confirm sane operation */ void dmatest(void) { int n, done; uchar *bp; static ulong pat = 0x87654321; static Rendez trendez; if (up == nil) panic("dmatest: up not set yet"); bp = (uchar *)KADDR(PHYSDRAM + 128*MB); memset(bp, Testbyte, Scratch); done = 0; dmastart((void *)PADDR(bp), Postincr, (void *)PADDR(&pat), Const, Testsize, &trendez, &done); sleep(&trendez, istestdmadone, &done); cachedinvse(bp, Scratch); if (((ulong *)bp)[0] != pat) panic("dmainit: copied incorrect data %#lux != %#lux", ((ulong *)bp)[0], pat); for (n = Testsize; n < Scratch && bp[n] != Testbyte; n++) ; if (n >= Scratch) panic("dmainit: ran wild over memory, clobbered ≥%,d bytes", n); if (bp[n] == Testbyte && n != Testsize) iprint("dma: %d-byte dma stopped after %d bytes!\n", Testsize, n); }
static void emmcio(int write, uchar *buf, int len) { u32int *r; int i; r = (u32int*)EMMCREGS; assert((len&3) == 0); okay(1); if(waserror()){ okay(0); nexterror(); } if(write) dmastart(DmaChanEmmc, DmaDevEmmc, DmaM2D, buf, &r[Data], len); else dmastart(DmaChanEmmc, DmaDevEmmc, DmaD2M, &r[Data], buf, len); if(dmawait(DmaChanEmmc) < 0) error(Eio); if(!write) cachedinvse(buf, len); WR(Irpten, Datadone|Err); tsleep(&emmc.r, datadone, 0, 3000); WR(Irpten, 0); emmc.datadone = 0; i = r[Interrupt]; if((i & Datadone) == 0){ print("emmcio: %d timeout intr %ux stat %ux\n", write, i, r[Status]); WR(Interrupt, i); error(Eio); } if(i & Err){ print("emmcio: %d error intr %ux stat %ux\n", write, r[Interrupt], r[Status]); WR(Interrupt, i); error(Eio); } if(i) WR(Interrupt, i); poperror(); okay(0); }