MPC8245 dma driver

Hello,

I'm quite new to (embedded-kernel level) linux even though I have a lot of experience otherwise with embedded systems, RTOSes. I was asked to help and develop a DMA driver which would enable a clean access between the MPC8245 and a PCI area (SDRAM), where other processor would read the data. The driver would be written at kernel level. Since I plunged into this feature I wasn't aware how complex all the memory aspect is. While I seem to understand the module interface, the memory accesses are far less obvious to me. There are 2 modes of operation for this particular DMA (chaining and direct). The code reflects that. I tried both and it doesn't work. In the init command I could call the "ch_"/none versions for chaining/direct modes. The only thing I managed to make work is to write to 0xfdcc0000 (over PCI) (I guess it comes from 4G - 48M memory map). Whether this helps me to actually write the driver, I don't know. How do I access a register in the EUMB region? Is it using ioremap? or _nocache? Is that a logical/phys memory? What do I save in the source adress/dest address? What format? Bus address? Virtual? Should I use writeb(w,l), readb(w,l)? Or just go and access the registers?

Really appreciate any help.

Following are some code lines: #define MPC8240_EUMBAR 0xf8000000-0x100000 #define DMA_SPACE(x) MPC8240_EUMBAR+0x1000+0x100*((x)+1) #define I2C_SPACE MPC8240_EUMBAR+0x3000 #define U32 unsigned int #define U8 unsigned char #define MEMORY_SIZE 13*1024*1024

typedef struct txdes { volatile U32 sa; volatile U32 hsa; volatile U32 da; volatile U32 hda; volatile U32 next; volatile U32 hnext; volatile U32 count; volatile U32 res; } TXD;

typedef struct dmas{ volatile U32 dmr; volatile U32 dsr; volatile U32 cdar; volatile U32 hcdar; volatile U32 sar; volatile U32 hsar; volatile U32 dar; volatile U32 hdar; volatile U32 bcr; volatile U32 ndar; } DMAS;

volatile DMAS* dma_t; volatile DMAS* dma_r; volatile TXD* txd[2]; volatile TXD* rxd[2]; char hllo[8] = "Hello"; char rrr[8];

static ch_dma_init() { int i; U32 temp; dma_t = (DMAS*) ioremap_nocache(DMA_SPACE(0),1024*1024); txd[0] = kmalloc(1024,GFP_KERNEL); temp = kmalloc(1024,GFP_KERNEL); temp += 0x40; temp &= 0xffffffe0; txd[0] = (TXD*)temp; printk("desc0:%x %x\n",txd[0],virt_to_bus(&txd[0])); temp = kmalloc(1024,GFP_KERNEL); temp += 0x40; temp &= 0xffffffe0; txd[1] = (TXD*)temp; printk("desc1:%x %x\n",txd[1],virt_to_bus(hllo)); for (i=0;isa = virt_to_bus(hllo); //txd[i]->da = virt_to_bus(rrr); txd[i]->da = 0xfdcc0008; txd[i]->count = 4; if (i==1) { txd[i]->next = 3; }else { txd[i]->next = virt_to_bus(&txd[1]) | 2; } } writel(virt_to_bus(&txd[0]),&dma_t->cdar); printk("prim %x %x %x %x %x %x\n", (((U32)readl(&dma_t->dmr))),(((U32)readl(&dma_t->dsr))), (((U32)readl(&dma_t->cdar))),(((U32)readl(&dma_t->sar))), (((U32)readl(&dma_t->dar))),(((U32)readl(&dma_t->bcr))));

}

static int direct_dma_init(void) { U8* scr; char* ttt; U8* hhh; // scr = (U8*)(spPciSyscfg_c + g_virt_start_addr); dev = pci_find_device(0x14e4,0x5615,dev); if (dev == NULL) { printk("no logical\n"); } ttt = kmalloc(6656,GFP_KERNEL|GFP_DMA); //scr = ioremap(spPciSyscfg_c,1024*1024); // scr = ioremap((unsigned long)pci_resource_start(dev,0),1024*1024); scr = 0xfdcc0000; if (scr == NULL) { printk("cannot allocate\n"); } // scr += spPciSyscfg_c; printk("pci:%x ttt:%x",scr,ttt); dma_t = (DMAS*) ioremap(DMA_SPACE(0),1024*1024); printk("udma_t:%x",dma_t); //hhh = ioremap(I2C_SPACE,1024*1024); hhh = ioremap(MPC8240_EUMBAR,1024*1024); printk("vdma_t:%x",dma_t); printk("hhh:%x hhh:%x %x %x %x %x %x %x %x", readl(((U32*)(hhh+0x41030))), readl(((U32*)(hhh+0x3004))),readl(((U32*)(hhh+0x41020))), (((U32)readl(&dma_t->dmr))),(((U32)readl(&dma_t->dsr))), (((U32)readl(&dma_t->cdar))),(((U32)readl(&dma_t->sar))), (((U32)readl(&dma_t->dar))),(((U32)readl(&dma_t->bcr)))); //dma_t = __va((DMAS*) DMA_SPACE(0)); printk("dma_t:%x",dma_t); // dma_r = (DMAS*) ioremap(DMA_SPACE(1),1024*1024); //printk("dma_r:%x",dma_r); //poll dma channel DSR[CB] //if (!DSR[CB]) return; if (dma_t->dsr & 0x4) { printk("nu pe aici0"); return; } //if (dma_r->dsr & 0x4) { //printk("nu pe aici1"); // return; // } //SAR = hllo; //dma_t->sar = virt_to_bus(hllo); //dma_t->sar = (0xfdcc0000); writel(virt_to_bus(hllo),&dma_t->sar); //dma_t->sar = ( virt_to_bus(hllo)); //DAR = scr; //dma_t->dar = __le32_to_cpu(0xfdcc0008); writel(virt_to_bus(rrr),&dma_t->dar); //dma_t->dar = __le32_to_cpu(virt_to_bus(rrr)); //BCR = strlen(hllo); //dma_t->bcr = strlen(hllo) + 1; //dma_t->bcr = __le32_to_cpu(3); writel(3,&dma_t->bcr); //CDAR[CTT](channel0) = 01 (local->PCI); //dma_t->cdar =(0x2); //dma_t->cdar =(0x0); //dma_t->cdar =__le32_to_cpu(0x6); writel(0,&dma_t->cdar); //CDAR[CTT](channel1) = 10 (PCI->local); // dma_r->cdar = 0x4; //DMR[CTM](channelX) = 1; (direct mode) //dma_t->dmr |= __le32_to_cpu(0x4); writel(4,&dma_t->dmr); //writeb(22,scr); }

void dma_start_t(void) { //DMR[CS](x) = 0; //dma_t->dmr &= __le32_to_cpu(~0x1); writel((~0x1) | 0x4,&dma_t->dmr); //DMR[CS](x) = 1; //dma_t->dmr |= __le32_to_cpu(0x1); writel(5, &dma_t->dmr); }

void ch_dma_start_t(void) { U32 tt; //DMR[CS](x) = 0; //dma_t->dmr &= __le32_to_cpu(~0x1); writel((~0x1),&dma_t->dmr); //DMR[CS](x) = 1; //dma_t->dmr |= __le32_to_cpu(0x1); writel(1, &dma_t->dmr); printk("astept"); tt = readl(&dma_t->dsr); writel(tt,&dma_t->dsr); printk("prim %x %x %x %x %x %x tt:%x\n", (((U32)readl(&dma_t->dmr))),(((U32)readl(&dma_t->dsr))), (((U32)readl(&dma_t->cdar))),(((U32)readl(&dma_t->sar))), (((U32)readl(&dma_t->dar))),(((U32)readl(&dma_t->bcr))),tt);

}

int init_module(void) { int err,i;

ch_dma_init(); ch_dma_start_t(); /* err = register_chrdev(MY_MAJOR,DEVICE_NAME,&Fops); if (err) { PRINTK ("Device failed with %d\n",err); unregister_chrdev(MY_MAJOR,DEVICE_NAME); return err; } PRINTK (" Device %s inserted\n",DEVICE_NAME);

*/ printk("uuuu"); for(i=0;i
Reply to
virgil
Loading thread data ...

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.