www.pudn.com > ucosii_demo.rar > dma.c, change:2007-08-16,size:2562b
/*
* dma.c
*
* Handle all DMA relative operations.
*
* Author: Seeger Chin
* e-mail: seeger.chin@gmail.com
*
* Copyright (C) 2006 Ingenic Semiconductor Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <regs.h>
#include <ops.h>
static unsigned int dma_mode[NUM_DMA], dma_unit_size[NUM_DMA], dma_irq[NUM_DMA];
static int inited = 0;
extern void dma_stop(int);
void dma_start(int ch, unsigned int srcAddr, unsigned int dstAddr,
unsigned int count)
{
//dma_stop
dma_stop(ch);
//set_dma_addr
REG_DMAC_DSAR(ch) = srcAddr;
REG_DMAC_DDAR(ch) = dstAddr;
//set_dma_count
REG_DMAC_DTCR(ch) = count / dma_unit_size[ch];
//enable_dma
REG_DMAC_DCCSR(ch) = dma_mode[ch];
REG_DMAC_DCCSR(ch) &= ~(DMAC_DCCSR_HLT|DMAC_DCCSR_TC|DMAC_DCCSR_AR);
__dmac_enable_channel(ch);
if (dma_irq[ch])
__dmac_channel_enable_irq(ch);
}
void dma_stop(int ch)
{
int i;
#define DMA_DISABLE_POLL 0x5000
if (!__dmac_channel_enabled(ch))
return;
for (i=0;i<DMA_DISABLE_POLL;i++)
if (__dmac_channel_transmit_end_detected(ch))
break;
__dmac_disable_channel(ch);
if (dma_irq[ch])
__dmac_channel_disable_irq(ch);
}
void dma_request(int ch, void (*irq_handler)(unsigned int), unsigned int arg,
unsigned int mode, unsigned int type)
{
if (!inited) {
inited = 1;
__dmac_enable_all_channels();
}
dma_mode[ch] = mode;
REG_DMAC_DRSR(ch) = type;
if (irq_handler) {
request_irq(IRQ_DMA_0 + ch, irq_handler, arg);
dma_irq[ch] = 1;
}
}
void dma_block_size(int ch, int nbyte)
{
dma_mode[ch] &= ~DMAC_DCCSR_DS_MASK;
dma_unit_size[ch] = nbyte;
switch (nbyte) {
case 1:
dma_mode[ch] |= DMAC_DCCSR_DS_8b;
break;
case 2:
dma_mode[ch] |= DMAC_DCCSR_DS_16b;
break;
case 4:
dma_mode[ch] |= DMAC_DCCSR_DS_32b;
break;
case 16:
dma_mode[ch] |= DMAC_DCCSR_DS_16B;
break;
case 32:
dma_mode[ch] |= DMAC_DCCSR_DS_32B;
break;
}
}
void dma_dest_size(int ch, int nbit)
{
dma_mode[ch] &= ~DMAC_DCCSR_DWDH_MASK;
switch (nbit) {
case 8:
dma_mode[ch] |= DMAC_DCCSR_DWDH_8;
break;
case 16:
dma_mode[ch] |= DMAC_DCCSR_DWDH_16;
break;
case 32:
dma_mode[ch] |= DMAC_DCCSR_DWDH_32;
break;
}
}
void dma_src_size(int ch, int nbit)
{
dma_mode[ch] &= ~DMAC_DCCSR_SWDH_MASK;
switch (nbit) {
case 8:
dma_mode[ch] |= DMAC_DCCSR_SWDH_8;
break;
case 16:
dma_mode[ch] |= DMAC_DCCSR_SWDH_16;
break;
case 32:
dma_mode[ch] |= DMAC_DCCSR_SWDH_32;
break;
}
}