MPC8245 dma driver

From: virgil (vanuichi_at_yahoo.com)
Date: 11/01/04

  • Next message: I R A Darth Aggie: "Re: CD images, ISO"
    Date: 1 Nov 2004 13:30:41 -0800
    
    

    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;i<2;i++)
       {
          txd[i]->sa = 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("<1>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("<1>dma_t:%x",dma_t);
     // dma_r = (DMAS*) ioremap(DMA_SPACE(1),1024*1024);
    //printk("<1>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 ("<1> Device %s inserted\n",DEVICE_NAME);
    */
    printk("uuuu");
    for(i=0;i<100000;i++)
    {
      if (rrr[0] == 'H') {printk("wwww");break;}
    }
    rrr[4] = '\0';
    printk("%s.....",rrr);
      return SUCCESS;
    }

    Virgil


  • Next message: I R A Darth Aggie: "Re: CD images, ISO"

    Relevant Pages

    • MPC8245 dma driver
      ... #define U32 unsigned int ... volatile U32 hsa; ... typedef struct dmas{ ... U8* scr; ...
      (comp.os.linux.embedded)
    • MPC8245 dma driver
      ... #define U32 unsigned int ... volatile U32 hsa; ... typedef struct dmas{ ... U8* scr; ...
      (comp.os.linux.development.apps)
    • MPC8245 dma driver
      ... #define U32 unsigned int ... volatile U32 hsa; ... typedef struct dmas{ ... U8* scr; ...
      (comp.os.linux.hardware)