From 61f25155acd99caef08897da390382d5c7fbfd74 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Tue, 14 Mar 2006 16:14:48 +0100 Subject: [PATCH] Add DMA support for MPC83xx. --- CHANGELOG | 2 + cpu/mpc83xx/cpu.c | 85 +++++++++++++++++++++++++++++++++++ include/asm-ppc/immap_83xx.h | 87 +++++++++++++++++++++++++++++++++++- 3 files changed, 173 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index f4819235a8..81e7cf2615 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 63f82422f5..f24d3a4b1c 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -191,3 +191,88 @@ ft_cpu_setup(void *blob, bd_t *bd) #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 2b2693c32f..b0e17ab9be 100644 --- a/include/asm-ppc/immap_83xx.h +++ b/include/asm-ppc/immap_83xx.h @@ -847,10 +847,95 @@ typedef struct spi8349 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 */