blob: 6dafcaedd7fef4dd71fc91da9edd233c10fb8d74 [file] [log] [blame]
/*
* 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;
}