AnsweredAssumed Answered

DMA engine of MPC8349E issues incorrect PCI read command

Question asked by Dmitry Vasilchenko on Nov 13, 2008
Latest reply on May 12, 2009 by huangxianguo huangxianguo
Hello!

We are trying to use the MPC8349E DMA engine to transfer data from a PCI memory and have faced the following problem: regardless of the "PRC" (PCI read command) field in the  DMAMR0 (DMA Mode) register commands of type "Memory read line" (code 0b1110) are issued on the bus.

We expected that DMA engine issues burst transfer using "Memory read" command (code 0b0110) when DMAMR0 bits 10 and 11 are cleared. But ChipScope on the target PCI device shows that "Memory read line" commands (code 0b1110) are issued instead of the burst transfer. Please, refer to the code below.

Any suggestions are welcome!


Regards,

Dmitry Vasilchenko,
RINA ltd.

/* ========================== cut here ================================ */

#define DMA_OFFSET 0x8000

#define DMASR0 0x104
#define DMASAR0 0x110
#define DMADAR0 0x118
#define DMABCR0 0x120
#define DMAMR0 0x100

/* Direct mode snoop enable */
#define DMAMR_SEN (1 << 20)

/* PCI Read Line Command */
#define DMAMR_PCI_READ_LINE (1 << 10)
/* PCI Read Multiple Command */
#define DMAMR_PCI_READ_MULT (1 << 11)

/* Channel Transfer Mode */
#define DMAMR_CTM (1 << 2)

/* Channel start */
#define DMAMR_CS 1

void __iomem *DMA_BASE = ioremap(get_immrbase() + DMA_OFFSET, 0x300);

void __iomem *DMA_SR = DMA_BASE + DMASR0;
void __iomem *DMA_MR = DMA_BASE + DMAMR0;
void __iomem *DMA_SAR = DMA_BASE + DMASAR0;
void __iomem *DMA_DAR = DMA_BASE + DMADAR0;
void __iomem *DMA_BCR = DMA_BASE + DMABCR0;

/* Source Address */
out_le32(DMA_SAR, src);
/* Destination Address */
out_le32(DMA_DAR, dst);
/* Counter */
out_le32(DMA_BCR, size);

/* DMA mode */
reg = DMAMR_CTM | DMAMR_SEN;
out_le32(DMA_MR, reg);

printk("Going to start transfer: 0x%08lx->0x%08lx(0x%08lx) mode=0x%08lx\n",
    in_le32(DMA_SAR), in_le32(DMA_DAR), in_le32(DMA_BCR), in_le32(DMA_MR));

/* Start transfer */
reg |= DMAMR_CS;
out_le32(DMA_MR, reg);

/* Check status */
reg = in_le32(DMA_SR);
while (reg & DMASR_CB) {
    reg = in_le32(DMA_SR);
}
printk("Done! DMA Status=0x%08lx\n", reg);

/* ========================== cut here ================================ */

Outcomes