Add DMA support for MPC83xx.
diff --git a/CHANGELOG b/CHANGELOG
index f481923..81e7cf2 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,8 @@
 Changes since U-Boot 1.1.4:
 ======================================================================
 
+* Add DMA support for MPC83xx.
+
 * Add sync in do_reset() routine for MPC83xx after RPR register
   was written to. It is need on some targets when BAT translation
   is enabled.
diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c
index 63f8242..f24d3a4 100644
--- a/cpu/mpc83xx/cpu.c
+++ b/cpu/mpc83xx/cpu.c
@@ -191,3 +191,88 @@
 #endif
 }
 #endif
+
+#if defined(CONFIG_DDR_ECC)
+void dma_init(void)
+{
+	volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
+	volatile dma8349_t *dma = &immap->dma;
+	volatile u32 status = swab32(dma->dmasr0);
+	volatile u32 dmamr0 = swab32(dma->dmamr0);
+
+	debug("DMA-init\n");
+
+	/* initialize DMASARn, DMADAR and DMAABCRn */
+	dma->dmadar0 = (u32)0;
+	dma->dmasar0 = (u32)0;
+	dma->dmabcr0 = 0;
+
+	__asm__ __volatile__ ("sync");
+	__asm__ __volatile__ ("isync");
+
+	/* clear CS bit */
+	dmamr0 &= ~DMA_CHANNEL_START;
+	dma->dmamr0 = swab32(dmamr0);
+	__asm__ __volatile__ ("sync");
+	__asm__ __volatile__ ("isync");
+
+	/* while the channel is busy, spin */
+	while(status & DMA_CHANNEL_BUSY) {
+		status = swab32(dma->dmasr0);
+	}
+
+	debug("DMA-init end\n");
+}
+
+uint dma_check(void)
+{
+	volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
+	volatile dma8349_t *dma = &immap->dma;
+	volatile u32 status = swab32(dma->dmasr0);
+	volatile u32 byte_count = swab32(dma->dmabcr0);
+
+	/* while the channel is busy, spin */
+	while (status & DMA_CHANNEL_BUSY) {
+		status = swab32(dma->dmasr0);
+	}
+
+	if (status & DMA_CHANNEL_TRANSFER_ERROR) {
+		printf ("DMA Error: status = %x @ %d\n", status, byte_count);
+	}
+
+	return status;
+}
+
+int dma_xfer(void *dest, u32 count, void *src)
+{
+	volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
+	volatile dma8349_t *dma = &immap->dma;
+	volatile u32 dmamr0;
+
+	/* initialize DMASARn, DMADAR and DMAABCRn */
+	dma->dmadar0 = swab32((u32)dest);
+	dma->dmasar0 = swab32((u32)src);
+	dma->dmabcr0 = swab32(count);
+
+	__asm__ __volatile__ ("sync");
+	__asm__ __volatile__ ("isync");
+
+	/* init direct transfer, clear CS bit */
+	dmamr0 = (DMA_CHANNEL_TRANSFER_MODE_DIRECT |
+			DMA_CHANNEL_SOURCE_ADDRESS_HOLD_8B |
+			DMA_CHANNEL_SOURCE_ADRESSS_HOLD_EN);
+	
+	dma->dmamr0 = swab32(dmamr0);
+
+	__asm__ __volatile__ ("sync");
+	__asm__ __volatile__ ("isync");
+
+	/* set CS to start DMA transfer */
+	dmamr0 |= DMA_CHANNEL_START;
+	dma->dmamr0 = swab32(dmamr0);
+	__asm__ __volatile__ ("sync");
+	__asm__ __volatile__ ("isync");
+
+	return ((int)dma_check());
+}
+#endif /*CONFIG_DDR_ECC*/
diff --git a/include/asm-ppc/immap_83xx.h b/include/asm-ppc/immap_83xx.h
index 2b2693c..b0e17ab 100644
--- a/include/asm-ppc/immap_83xx.h
+++ b/include/asm-ppc/immap_83xx.h
@@ -847,10 +847,95 @@
 	u8 res1[0xD8];
 } spi8349_t;
 
+
+/*
+ * DMA/Messaging Unit
+ */
 typedef struct dma8349 {
-	u8 fixme[0x300];
+	u32 res0[0xC];	/* 0x0-0x29 reseverd */
+	u32 omisr;	/* 0x30 Outbound message interrupt status register */
+	u32 omimr;	/* 0x34 Outbound message interrupt mask register */
+	u32 res1[0x6];	/* 0x38-0x49 reserved */
+
+	u32 imr0;	/* 0x50 Inbound message register 0 */
+	u32 imr1;	/* 0x54 Inbound message register 1 */
+	u32 omr0;	/* 0x58 Outbound message register 0 */
+	u32 omr1;	/* 0x5C Outbound message register 1 */
+
+	u32 odr;	/* 0x60 Outbound doorbell register */
+	u32 res2;	/* 0x64-0x67 reserved */
+	u32 idr;	/* 0x68 Inbound doorbell register */
+	u32 res3[0x5];	/* 0x6C-0x79 reserved */
+
+	u32 imisr;	/* 0x80 Inbound message interrupt status register */
+	u32 imimr;	/* 0x84 Inbound message interrupt mask register */
+	u32 res4[0x1E];	/* 0x88-0x99 reserved */
+
+	u32 dmamr0;	/* 0x100 DMA 0 mode register */
+	u32 dmasr0;	/* 0x104 DMA 0 status register */
+	u32 dmacdar0;	/* 0x108 DMA 0 current descriptor address register */
+	u32 res5;	/* 0x10C reserved */
+	u32 dmasar0;	/* 0x110 DMA 0 source address register */
+	u32 res6;	/* 0x114 reserved */
+	u32 dmadar0;	/* 0x118 DMA 0 destination address register */
+	u32 res7;	/* 0x11C reserved */
+	u32 dmabcr0;	/* 0x120 DMA 0 byte count register */
+	u32 dmandar0;	/* 0x124 DMA 0 next descriptor address register */
+	u32 res8[0x16];	/* 0x128-0x179 reserved */
+
+	u32 dmamr1;	/* 0x180 DMA 1 mode register */
+	u32 dmasr1;	/* 0x184 DMA 1 status register */
+	u32 dmacdar1;	/* 0x188 DMA 1 current descriptor address register */
+	u32 res9;	/* 0x18C reserved */
+	u32 dmasar1;	/* 0x190 DMA 1 source address register */
+	u32 res10;	/* 0x194 reserved */
+	u32 dmadar1;	/* 0x198 DMA 1 destination address register */
+	u32 res11;	/* 0x19C reserved */
+	u32 dmabcr1;	/* 0x1A0 DMA 1 byte count register */
+	u32 dmandar1;	/* 0x1A4 DMA 1 next descriptor address register */
+	u32 res12[0x16];/* 0x1A8-0x199 reserved */
+
+	u32 dmamr2;	/* 0x200 DMA 2 mode register */
+	u32 dmasr2;	/* 0x204 DMA 2 status register */
+	u32 dmacdar2;	/* 0x208 DMA 2 current descriptor address register */
+	u32 res13;	/* 0x20C reserved */
+	u32 dmasar2;	/* 0x210 DMA 2 source address register */
+	u32 res14;	/* 0x214 reserved */
+	u32 dmadar2;	/* 0x218 DMA 2 destination address register */
+	u32 res15;	/* 0x21C reserved */
+	u32 dmabcr2;	/* 0x220 DMA 2 byte count register */
+	u32 dmandar2;	/* 0x224 DMA 2 next descriptor address register */
+	u32 res16[0x16];/* 0x228-0x279 reserved */
+
+	u32 dmamr3;	/* 0x280 DMA 3 mode register */
+	u32 dmasr3;	/* 0x284 DMA 3 status register */
+	u32 dmacdar3;	/* 0x288 DMA 3 current descriptor address register */
+	u32 res17;	/* 0x28C reserved */
+	u32 dmasar3;	/* 0x290 DMA 3 source address register */
+	u32 res18;	/* 0x294 reserved */
+	u32 dmadar3;	/* 0x298 DMA 3 destination address register */
+	u32 res19;	/* 0x29C reserved */
+	u32 dmabcr3;	/* 0x2A0 DMA 3 byte count register */
+	u32 dmandar3;	/* 0x2A4 DMA 3 next descriptor address register */
+
+	u32 dmagsr;	/* 0x2A8 DMA general status register */
+	u32 res20[0x15];/* 0x2AC-0x2FF reserved */
 } dma8349_t;
 
+/* DMAMRn bits */
+#define DMA_CHANNEL_START			(0x00000001)		/* Bit - DMAMRn CS */
+#define DMA_CHANNEL_TRANSFER_MODE_DIRECT	(0x00000004)		/* Bit - DMAMRn CTM */
+#define DMA_CHANNEL_SOURCE_ADRESSS_HOLD_EN	(0x00001000)		/* Bit - DMAMRn SAHE */
+#define DMA_CHANNEL_SOURCE_ADDRESS_HOLD_1B	(0x00000000)		/* 2Bit- DMAMRn SAHTS 1byte */
+#define DMA_CHANNEL_SOURCE_ADDRESS_HOLD_2B	(0x00004000)		/* 2Bit- DMAMRn SAHTS 2bytes */
+#define DMA_CHANNEL_SOURCE_ADDRESS_HOLD_4B	(0x00008000)		/* 2Bit- DMAMRn SAHTS 4bytes */
+#define DMA_CHANNEL_SOURCE_ADDRESS_HOLD_8B	(0x0000c000)		/* 2Bit- DMAMRn SAHTS 8bytes */
+#define DMA_CHANNEL_SNOOP			(0x00010000)		/* Bit - DMAMRn DMSEN */
+
+/* DMASRn bits */
+#define DMA_CHANNEL_BUSY 			(0x00000004)		/* Bit - DMASRn CB */
+#define DMA_CHANNEL_TRANSFER_ERROR		(0x00000080)		/* Bit - DMASRn TE */
+
 /*
  * PCI Software Configuration Registers
  */