| /* |
| * Driver for DMA device for pxa |
| * |
| * Copyright (c) 2009 Marvell Inc. |
| * |
| * Licensed under the GPL-2 or later. |
| */ |
| |
| #include <asm/arch/pxa_dma.h> |
| #include <common.h> |
| #include <asm/io.h> |
| |
| #define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) |
| #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) |
| |
| void dmac_start_transfer(int channel) |
| { |
| DCSR(channel) |= DCSR_RUN; |
| } |
| |
| unsigned int dmac_read_dcsr(int channel) |
| { |
| return DCSR(channel); |
| } |
| |
| void config_descriptor(unsigned int *p_desc, |
| unsigned int *p_next_desc, |
| unsigned int p_src_addr, |
| unsigned int p_tag_addr, |
| unsigned int p_cmd, |
| unsigned int stop_bit) |
| { |
| unsigned int addr = ((unsigned int)p_next_desc | (stop_bit & 0x1)); |
| ((struct dma_descp *)p_desc)->ddadr = addr; |
| ((struct dma_descp *)p_desc)->dsadr = p_src_addr; |
| ((struct dma_descp *)p_desc)->dtadr = p_tag_addr; |
| ((struct dma_descp *)p_desc)->dcmd = p_cmd; |
| |
| return; |
| } |
| |
| void dmac_descriptor_fetch(unsigned int channel) |
| { |
| DCSR(channel) &= ~DCSR_NODESC; |
| } |
| |
| void load_descriptor(struct dma_descp *p_desc, unsigned int channel) |
| { |
| DDADR(channel) = (unsigned int)p_desc; |
| dmac_descriptor_fetch(channel); |
| } |
| |
| void dmac_map_device_to_channel(int device_num, int channel) |
| { |
| DRCMR(device_num) = DRCMR_MAPVLD + channel; |
| } |
| |
| void dmac_user_aligment(int channel) |
| { |
| DALGN |= (1<<channel); |
| } |
| |
| void pxa2xx_spi_dma_prepare(int channel, unsigned int srcAddr, |
| unsigned int targetAddr, DMAC_COMMAND *pCmd) |
| { |
| u32 dma_width; |
| unsigned int command = 0; |
| |
| switch (pCmd->width) { |
| case 1: |
| dma_width = DCMD_WIDTH1; |
| break; |
| case 2: |
| dma_width = DCMD_WIDTH2; |
| break; |
| default: |
| dma_width = DCMD_WIDTH4; |
| break; |
| } |
| command = (unsigned int)((pCmd->len) | (dma_width) | |
| ((pCmd->size) << 16) | |
| ((pCmd->flowTrg) << 28) | |
| ((pCmd->flowSrc) << 29) | |
| ((pCmd->incTrgAddr) << 30)| |
| ((pCmd->incSrcAddr) << 31) |
| ); |
| |
| DCSR(channel) = RESET_DMA_CHANNEL; |
| DSADR(channel) = srcAddr; |
| DTADR(channel) = targetAddr; |
| DCMD(channel) = command; |
| } |
| |
| unsigned int pxa_dma_read(unsigned int dst, unsigned int src, |
| unsigned int len, unsigned int channel) |
| { |
| DMAC_COMMAND dmac_cmd = {0}; |
| memset(&dmac_cmd, 0x0, sizeof(DMAC_COMMAND)); |
| |
| dmac_cmd.incTrgAddr = 1; /* Increase destionation. */ |
| dmac_cmd.incSrcAddr = 0; |
| dmac_cmd.flowSrc = 1; |
| dmac_cmd.flowTrg = 0; |
| dmac_cmd.size = 2; /* Max burst size 2: 16bytes. */ |
| dmac_cmd.width = 3; |
| dmac_cmd.len = len; |
| |
| pxa2xx_spi_dma_prepare(channel, src, dst, &dmac_cmd); |
| |
| return 0; |
| } |
| |
| unsigned int pxa_dma_write(unsigned int dst, unsigned int src, |
| unsigned int len, unsigned int channel) |
| { |
| DMAC_COMMAND dmac_cmd = {0}; |
| memset(&dmac_cmd, 0x0, sizeof(DMAC_COMMAND)); |
| |
| dmac_cmd.incTrgAddr = 0; |
| dmac_cmd.incSrcAddr = 1; |
| dmac_cmd.flowSrc = 0; |
| dmac_cmd.flowTrg = 1; |
| dmac_cmd.size = 3; /* Max burst size 2: 16bytes. */ |
| dmac_cmd.width = 3; |
| dmac_cmd.len = len; |
| |
| pxa2xx_spi_dma_prepare(channel, src, dst, &dmac_cmd); |
| |
| return 0; |
| } |